diff --git a/.gitattributes b/.gitattributes index e0e62f9e1b21c1e0f9f9b9396f0e2b2ad52eb0ea..6b238a44aebdadd1c224f0e4e2c2d42d5f2c0601 100644 --- a/.gitattributes +++ b/.gitattributes @@ -29,5 +29,6 @@ *.mat filter=lfs diff=lfs merge=lfs -text *.met filter=lfs diff=lfs merge=lfs -text *.pcm filter=lfs diff=lfs merge=lfs -text +*.sofa filter=lfs diff=lfs merge=lfs -text *.wav filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index eaf8b0cb7b11e5f4c3bc0732e0dcb6920a3e38df..c87c691a4af7f6c50a681db4a373b100e84c7558 100644 --- a/.gitignore +++ b/.gitignore @@ -3,17 +3,21 @@ # Compiler output Unix IVAS_cod IVAS_dec +IVAS_rend +IVAS_crend_unit_test obj/ *.a *.o *.P # default CMake -build/**/* +build*/**/* # Compiler output VS2017 IVAS_cod.exe IVAS_dec.exe +IVAS_rend.exe +IVAS_crend_unit_test.exe *.user .vs/ Debug_*/ @@ -31,22 +35,40 @@ scripts/ivas_pytests/tests/unit_tests/crend/Release_*/ scripts/td_object_renderer/object_renderer_standalone/renderer_standalone scripts/td_object_renderer/object_renderer_standalone/renderer_standalone.exe -# Prerenderer -scripts/prerenderer/IVAS_prerenderer -scripts/prerenderer/IVAS_prerenderer.exe - # General/scripts .DS_Store .vscode +.cache *.log *.bak +.\#* scripts/c-code_instrument/ scripts/ifdef_instrument.list scripts/ref/ scripts/test/ +scripts/out/ scripts/self_test_summary.txt +scripts/cppp/ +binary/ +tests/renderer/cut +tests/renderer/ref +tests/dut +tests/ref +scripts/testv/*_cut*.pcm +# default reference binary name +IVAS_cod_ref +IVAS_dec_ref # Python files that pop up when running scripts __pycache__/ *.py[cod] *$py.class + +# history +.history/ + +#externals +Externals/ + +# coan output files that are created when cleaning out switches +coan_out_* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7df1635da67e33f778dd607200cb4ece465a33c9..71ff18eb921492704a10719070618a85b697eae4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,102 +1,701 @@ 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" + SANITIZER_TESTS: "CLANG1 CLANG2" + 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" + EXIT_CODE_NON_BE: 123 + EXIT_CODE_FAIL: 1 +default: + interruptible: true # Make all jobs by default interruptible + artifacts: + expire_in: 2 weeks -# prevent running two pipelines on pushes to merge request branches +# This sets when pipelines are created. Jobs have more specific rules to restrict them. workflow: rules: # see https://docs.gitlab.com/ee/ci/yaml/workflow.html#switch-between-branch-pipelines-and-merge-request-pipelines - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push" when: never - - when: always - + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Pushes to main + - if: $CI_PIPELINE_SOURCE == 'schedule' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Scheduled in main + - if: $CI_PIPELINE_SOURCE == 'web' # for testing stages: + - .pre - maintenance - build - test - compare + - validate + - 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." + echo "Current job is run on commit $CI_COMMIT_SHA" + 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) + + + +.merge-request-comparison-setup-codec: + &merge-request-comparison-setup-codec ### build test binaries, initial clean for paranoia reasons + - make clean + - mkdir build + - cd build + - cmake .. + - make -j + - mv IVAS_cod ../IVAS_cod_test + - mv IVAS_dec ../IVAS_dec_test + - mv IVAS_rend .. + - cd .. + - rm -rf build/* + + ### store the current commit hash + - source_branch_commit_sha=$(git rev-parse HEAD) + + ### checkout version to compare against + - *mr-fetch-target-branch + + - *mr-get-target-commit + - git checkout $target_commit + + ### build reference binaries + - cd build + - cmake .. + - make -j + - mv IVAS_cod ../IVAS_cod_ref + - mv IVAS_dec ../IVAS_dec_ref + - cd .. + + # rename test binaries back + - mv IVAS_cod_test IVAS_cod + - mv IVAS_dec_test IVAS_dec + +.merge-request-comparison-check: &merge-request-comparison-check + - if [ $zero_errors != 1 ]; then echo "Run errors encountered!"; exit $EXIT_CODE_FAIL; fi + - if [ $exit_code -eq 1 ] && [ $non_be_flag == 0 ]; then echo "Non-bitexact cases without non-BE tag encountered!"; exit $EXIT_CODE_FAIL; fi + - if [ $exit_code -eq 1 ] && [ $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 - -# template for all test jobs -.test-job: +# --------------------------------------------------------------- +# 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 - when: on_success -# template test job on linux +.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: - extends: .test-job tags: - ivas-linux +.build-job-linux: + stage: build + timeout: "4 minutes" + tags: + - ivas-linux + +.build-job-windows: + stage: build + 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 - cp -r scripts/testv/* $TESTV_DIR/ - -# build all components of the project, i.e. codec itself, the unittests, the prerenderer and the standalone version of the TD object renderer -build-all-linux-make: - extends: .test-job-linux - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' +# template for build jobs to include the check for warnings +.build-job-with-check-for-warnings: + extends: .build-job-linux + stage: build + allow_failure: + exit_codes: + - 123 + +.build-job-windows-with-check-for-warnings: + extends: .build-job-windows stage: build + allow_failure: + exit_codes: + - 123 + + +# --------------------------------------------------------------- +# .pre jobs for setting up things +# --------------------------------------------------------------- + +# See: https://gitlab.com/gitlab-org/gitlab/-/issues/194023 +# Solution to make main branch pipelines uninterruptible while all other +# pipelines can be interrupted by default. This works because all jobs +# after uninterruptible jobs will be uninterruptible. Resource group +# setting avoids rare case where two fast merges could still interrupt +# pipeline. This should be revisited if there are updates to Gitlab. +uninterruptible: + stage: .pre + interruptible: false + resource_group: uninterruptible + script: + - echo "$CI_COMMIT_BRANCH is uninterruptible" + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + when: always + tags: + - ivas-linux + + + +# --------------------------------------------------------------- +# Validation jobs +# --------------------------------------------------------------- + +check-if-branch-is-up-to-date-with-main: + extends: + - .rules-merge-request + stage: validate + needs: [] + tags: + - ivas-linux script: - - bash ci/build_all_linux.sh + - 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) + - echo $commits_behind_count + - if [ $commits_behind_count -eq 0 ]; then exit 0; else exit 1; fi; + + +# --------------------------------------------------------------- +# Build jobs +# --------------------------------------------------------------- + +build-codec-linux-make: + extends: + - .build-job-with-check-for-warnings + - .rules-basis + script: + - *print-common-info + - make -j 2>&1 | tee $BUILD_OUTPUT + # need to use the "|| exit $?" suffix to get the allowed_failure return code, otherwise the job fails with code 1...< + - ci/check_for_warnings.py $BUILD_OUTPUT || exit $? build-codec-linux-cmake: - extends: .test-job-linux - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - stage: build + extends: + - .build-job-with-check-for-warnings + - .rules-basis script: + - *print-common-info - mkdir build - cd build - cmake .. - - make -j + - cd .. + - make -C build -j 2>&1 | tee $BUILD_OUTPUT + # need to use the "|| exit $?" suffix to get the allowed_failure return code, otherwise the job fails with code 1...< + - ci/check_for_warnings.py $BUILD_OUTPUT || exit $? build-codec-instrumented-linux: - extends: .test-job-linux - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - stage: build + extends: + - .build-job-linux + - .rules-basis script: + - *print-common-info - bash ci/build_codec_instrumented_linux.sh # make sure that the codec builds with msan, asan and usan build-codec-sanitizers-linux: - extends: .test-job-linux - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - stage: build + extends: + - .build-job-linux + - .rules-basis script: + - *print-common-info - bash ci/build_codec_sanitizers_linux.sh +build-codec-windows-cmake: + extends: + - .build-job-windows-with-check-for-warnings + - .rules-basis + script: + - *print-common-info-windows + - $winoutdata = $null + - cmake -G "Visual Studio 15 2017" . -Bbuild + - cmake --build build -j | tee -variable winoutdata + - $winoutdata | Out-File $BUILD_OUTPUT -Encoding Utf8 + - ("& python ci/check_for_warnings.py '$BUILD_OUTPUT'") | Invoke-Expression + - ("exit $LASTEXITCODE") | Invoke-Expression + +build-codec-windows-msbuild: + extends: + - .build-job-windows-with-check-for-warnings + - .rules-basis + script: + - *print-common-info-windows + - $winoutdata = $null + - MSBuild.exe .\Workspace_msvc\Workspace_msvc.sln /property:Configuration=Debug | tee -variable winoutdata + - $winoutdata | Out-File $BUILD_OUTPUT -Encoding Utf8 + - ("& python ci/check_for_warnings.py '$BUILD_OUTPUT'") | Invoke-Expression + - ("exit $LASTEXITCODE") | Invoke-Expression + +# --------------------------------------------------------------- +# Test jobs for merge requests +# --------------------------------------------------------------- # test that runs all modes with 1s input signals codec-smoke-test: - extends: .test-job-linux-needs-testv-dir - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + extends: + - .test-job-linux-needs-testv-dir + - .rules-merge-request + timeout: "5 minutes" stage: test + needs: ["build-codec-linux-cmake"] script: + - *print-common-info - bash ci/smoke_test.sh + ### analyze for failures + - if cat smoke_test_output.txt | grep -c "failed"; then echo "Smoke test without PLC failed"; exit 1; fi + - if cat smoke_test_output_plc.txt | grep -c "failed"; then echo "Smoke test with PLC failed"; exit 1; fi + - if cat smoke_test_output_jbm_noEXT.txt | grep -c "failed"; then echo "Smoke test JBM part failed"; exit 1; fi + - if cat smoke_test_output_hrtf.txt | grep -c "failed"; then echo "Smoke test with external hrtf files failed"; exit 1; fi artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" paths: - - out/logs + - smoke_test_output.txt + - smoke_test_output_plc.txt + - smoke_test_output_jbm_noEXT.txt + - smoke_test_output_hrtf.txt + expose_as: "Smoke test results" +# code selftest testvectors with memory-sanitizer binaries +codec-msan: + extends: + - .test-job-linux + - .rules-merge-request + stage: test + needs: ["build-codec-sanitizers-linux"] + script: + - *print-common-info + - python3 ci/disable_ram_counting.py + - make clean + - make -j CLANG=1 + - python3 scripts/self_test.py --create | tee test_output.txt + - run_errors=$(cat test_output.txt | grep -ic "run errors") || true + - if [ $run_errors != 0 ] ; then echo "Run errors in self_test.py with Clang memory-sanitizer"; exit 1; fi + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + paths: + - scripts/ref/logs/ + - test_output.txt + expose_as: "msan selftest results" + +# code selftest testvectors with address-sanitizer binaries +codec-asan: + extends: + - .test-job-linux + - .rules-merge-request + stage: test + needs: ["build-codec-sanitizers-linux"] + script: + - *print-common-info + - python3 ci/disable_ram_counting.py + - make clean + - make -j CLANG=2 + - python3 scripts/self_test.py --create | tee test_output.txt + - run_errors=$(cat test_output.txt | grep -ic "run errors") || true + - if [ $run_errors != 0 ] ; then echo "Run errors in self_test.py with Clang address-sanitizer"; exit 1; fi + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + paths: + - scripts/ref/logs/ + - test_output.txt + expose_as: "asan selftest results" + +# test renderer executable +renderer-smoke-test: + extends: + - .test-job-linux + - .rules-merge-request + needs: ["build-codec-linux-make"] + stage: test + script: + - make -j IVAS_rend + - python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" + when: always + paths: + - report-junit.xml + expose_as: "renderer make pytest results" + reports: + junit: + - report-junit.xml + +# test renderer executable with cmake + asan +renderer-asan: + extends: + - .test-job-linux + - .rules-merge-request + needs: ["build-codec-linux-cmake"] + stage: test + script: + - python3 ci/disable_ram_counting.py + - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=asan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true + - cmake --build cmake-build -- -j + - python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py + + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" + when: always + paths: + - report-junit.xml + expose_as: "renderer asan pytest results" + reports: + junit: + - report-junit.xml + +# test renderer executable with cmake + msan +renderer-msan: + extends: + - .test-job-linux + - .rules-merge-request + needs: ["build-codec-linux-cmake"] + stage: test + script: + - python3 ci/disable_ram_counting.py + - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=msan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true + - cmake --build cmake-build -- -j + - python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py + + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" + when: always + paths: + - report-junit.xml + expose_as: "renderer msan pytest results" + reports: + junit: + - report-junit.xml + +# compare renderer bitexactness between target and source branch +renderer-pytest-on-merge-request: + extends: + - .test-job-linux + - .rules-merge-request + needs: ["build-codec-linux-make"] + # TODO: set reasonable timeout, will most likely take less + timeout: "20 minutes" + stage: compare + script: + - *print-common-info + + # some helper variables - "|| true" to prevent failures from grep not finding anything + - non_be_flag=$(echo $CI_MERGE_REQUEST_TITLE | grep -c --ignore-case "\[rend\(erer\)*[ -]*non[ -]*be\]") || true + # TODO: needs splitting the test between reference and cut generation + #- ref_using_main=$(echo $CI_MERGE_REQUEST_TITLE | grep -c --ignore-case "\[ref[ -]*using[ -]*main\]") || true + + # store the current commit hash + - source_branch_commit_sha=$(git rev-parse HEAD) + + - *mr-fetch-target-branch + - *mr-get-target-commit + - git checkout $target_commit + + # build reference binaries + - make -j IVAS_rend + - mv IVAS_rend IVAS_rend_ref + + # back to source branch + - git checkout $source_branch_commit_sha + - make clean + - make -j IVAS_rend + + # run test + - exit_code=0 + - python3 -m pytest -q --log-level ERROR -n auto -rA --html=report.html --self-contained-html --junit-xml=report-junit.xml tests/renderer/test_renderer_be_comparison.py || exit_code=$? + - zero_errors=$(cat report-junit.xml | grep -c 'errors="0"') || true + + - *merge-request-comparison-check + + allow_failure: + exit_codes: + - 123 + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" + when: always + paths: + - report-junit.xml + - report.html + expose_as: "pytest renderer results" + reports: + junit: + - report-junit.xml # compare bit exactness between target and source branch -self-test-on-merge-request: - extends: .test-job-linux +ivas-pytest-on-merge-request: + extends: + - .test-job-linux + - .rules-merge-request stage: compare - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + needs: ["build-codec-linux-cmake", "codec-smoke-test"] + timeout: "10 minutes" + script: + - *print-common-info + - *merge-request-comparison-setup-codec + + # some helper variables - "|| true" to prevent failures from grep not finding anything + - non_be_flag=$(echo $CI_MERGE_REQUEST_TITLE | grep -c --ignore-case "\[non[ -]*be\]") || true + - ref_using_main=$(echo $CI_MERGE_REQUEST_TITLE | grep -c --ignore-case "\[ref[ -]*using[ -]*main\]") || true + + ### If ref_using_main is not set, checkoug the source branch to use scripts and input from there + - if [ $ref_using_main == 0 ]; then git checkout $source_branch_commit_sha; fi + + ### prepare pytest + # create short test vectors + - python3 tests/create_short_testvectors.py + # create references + - python3 -m pytest tests -v --update_ref 1 -m create_ref + - python3 -m pytest tests -v --update_ref 1 -m create_ref_part2 + + ### Run test using branch scripts and input + - if [ $ref_using_main == 1 ]; then git checkout $source_branch_commit_sha; fi + + ### run pytest + - exit_code=0 + - python3 -m pytest tests -v --html=report.html --self-contained-html --junit-xml=report-junit.xml || exit_code=$? + - zero_errors=$(cat report-junit.xml | grep -c 'errors="0"') || true + + - *merge-request-comparison-check + + allow_failure: + exit_codes: + - 123 + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + when: always + paths: + - report-junit.xml + - report.html + expose_as: "pytest ivas results" + reports: + junit: + - report-junit.xml + +evs-pytest-on-merge-request: + extends: + - .test-job-linux + - .rules-merge-request + stage: compare + needs: ["build-codec-linux-cmake", "codec-smoke-test"] + timeout: "10 minutes" script: + - *print-common-info + - *merge-request-comparison-setup-codec + + # some helper variables - "|| true" to prevent failures from grep not finding anything + - non_be_flag=$(echo $CI_MERGE_REQUEST_TITLE | grep -c --ignore-case "\[evs[ -]*non[ -]*be\]") || true + - ref_using_main=$(echo $CI_MERGE_REQUEST_TITLE | grep -c --ignore-case "\[ref[ -]*using[ -]*main\]") || true + + ### If ref_using_main is not set, checkoug the source branch to use scripts and input from there + - if [ $ref_using_main == 0 ]; then git checkout $source_branch_commit_sha; fi + + ### prepare pytest + # create references + - python3 -m pytest tests/test_param_file.py -v --update_ref 1 -m create_ref --param_file scripts/config/self_test_evs.prm + + ### Run test using branch scripts and input + - if [ $ref_using_main == 1 ]; then git checkout $source_branch_commit_sha; fi + + ### run pytest for EVS cases + - exit_code=0 + - python3 -m pytest tests/test_param_file.py -v --param_file scripts/config/self_test_evs.prm --html=report.html --self-contained-html --junit-xml=report-junit-evs.xml || exit_code=$? + - zero_errors=$(cat report-junit-evs.xml | grep -c 'errors="0"') || true + + - *merge-request-comparison-check + + allow_failure: + exit_codes: + - 123 + artifacts: + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + when: always + paths: + - report-junit-evs.xml + - report.html + expose_as: "pytest evs results" + reports: + junit: + - report-junit-evs.xml + +voip-be-on-merge-request: + extends: + - .test-job-linux-needs-testv-dir + - .rules-merge-request + stage: compare # Or should it be test? Comparison is done within one git revision + needs: ["build-codec-linux-make", codec-smoke-test] + timeout: "10 minutes" + script: + - *print-common-info + - bash ci/ivas_voip_be_test.sh + +clang-format-check: + extends: + - .test-job-linux + - .rules-merge-request + variables: + ARTIFACT_BASE_NAME: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--formatting-fix" + stage: validate + needs: [] + timeout: "5 minutes" + script: + # Set up variables. This can't be done in the "variables" section because variables are not expanded properly there + - PATCH_FILE_NAME="$ARTIFACT_BASE_NAME".patch + - > + INSTRUCTIONS_GITLAB="To fix formatting issues:\n + - download the diff patch available as artifact of this job\n + - unzip the artifact and place the patch file in the root directory of your local IVAS repo\n + - run: git apply $PATCH_FILE_NAME\n + - commit new changes" + - > + INSTRUCTIONS_README="To fix formatting issues:\n + - place the patch file in the root directory of your local IVAS repo\n + - run: git apply $PATCH_FILE_NAME\n + - commit new changes" + + - scripts/check-format.sh -af -p 8 || format_problems=$? + - if [ $format_problems == 0 ] ; then exit 0; fi + + - mkdir tmp-formatting-fix + - git diff > "tmp-formatting-fix/$PATCH_FILE_NAME" + + # Print instructions to job output + - echo -e "$INSTRUCTIONS_GITLAB" + + # Include readme in the artifact, in case someone misses the job printout (e.g. getting the artifact via MR interface) + - echo -e "$INSTRUCTIONS_README" > "tmp-formatting-fix/readme.txt" + + - exit $format_problems + artifacts: + paths: + - tmp-formatting-fix/ + when: on_failure + name: "$ARTIFACT_BASE_NAME" + expose_as: 'formatting patch' + +# --------------------------------------------------------------- +# Test jobs for main branch +# --------------------------------------------------------------- + +# check bitexactness to EVS +be-2-evs-linux: + extends: + - .test-job-linux + - .rules-main-push + tags: + - be-2-evs-temp + stage: test + needs: ["build-codec-linux-cmake"] + timeout: "20 minutes" # To be revisited + script: + - *print-common-info + + - mkdir build + - cd build + - cmake .. + - make -j + - cd .. + + # copy over to never change the testvector dir + - cp -r $EVS_BE_TEST_DIR ./evs_be_test + - cp build/IVAS_cod ./evs_be_test/bin/EVS_cod + - cp build/IVAS_dec ./evs_be_test/bin/EVS_dec + + - cd evs_be_test + - python3 ../ci/run_evs_be_test.py + +codec-comparison-on-main-push: + extends: + - .test-job-linux + - .rules-main-push + stage: compare + needs: ["build-codec-linux-cmake"] + timeout: "30 minutes" # To be revisited + script: + - *print-common-info + - latest_commit=$(git rev-parse HEAD) # Latest commit + - *get-previous-merge-commit-sha # Stored in previous_merge_commit shell variable now + - echo "Comparing changes from $previous_merge_commit to $latest_commit" + - git --no-pager diff --stat $previous_merge_commit..$latest_commit + + # Rest is more or less placeholder adapted from MR self test. This should be replaced with more complex tests. + ### build test binaries, initial clean for paranoia reasons - make clean - mkdir build @@ -108,19 +707,9 @@ self-test-on-merge-request: - cd .. - rm -rf build/* - ### store the current commit hash - - source_branch_commit_sha=$(git rev-parse HEAD) - - ### checkout version to compare against - # 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 - - ### 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) - - git checkout $target_commit + ### compare to the previous merge commit in the main branch + - git fetch origin main + - git checkout $previous_merge_commit ### build reference binaries - cd build @@ -130,24 +719,435 @@ self-test-on-merge-request: - mv IVAS_dec ../IVAS_dec_ref - cd .. - ### re-checkout the commit from the source branch to have up-to-date self_test.py and scripts/testv (and actually everything) - - git checkout $source_branch_commit_sha + # helper variable - "|| true" to prevent failures from grep not finding anything + - non_be_flag=$(echo $CI_COMMIT_MESSAGE | grep -c --ignore-case "\[non[ -]*be\]") || true + - ref_using_main=$(echo $CI_COMMIT_MESSAGE | grep -c --ignore-case "\[ref[ -]*using[ -]*main\]") || true + + ### re-checkout the latest commit in the main branch, if ref_using_main is not set + - if [ $ref_using_main == 0 ]; then git checkout $latest_commit;fi + + ### prepare pytest + # create short test vectors + - python3 tests/create_short_testvectors.py + # rename test binaries back + - mv IVAS_cod_test IVAS_cod + - mv IVAS_dec_test IVAS_dec + # create references + - python3 -m pytest tests -v --update_ref 1 -m create_ref + - python3 -m pytest tests -v --update_ref 1 -m create_ref_part2 - ### run selftest - - ls -altr scripts/testv - - python3 ./scripts/self_test.py --encref IVAS_cod_ref --decref IVAS_dec_ref --enctest IVAS_cod_test --dectest IVAS_dec_test | tee test_output.txt + ### re-checkout the latest commit here, if ref_using_main is set + - if [ $ref_using_main -eq 1 ]; then git checkout $latest_commit;fi - ### analyse test output - # check for crashes during the test, if any happened, fail the test - - if cat test_output.txt | grep -c "Run errors were encountered for the following conditions:"; then echo "Codec had run errors"; exit 1; fi - # check for non bitexact output and fail test if the merge request does not have a non-BE tag - - if ! cat test_output.txt | grep -c "All [0-9]* tests are bitexact" && ! echo $CI_MERGE_REQUEST_TITLE | grep -c --ignore-case "\[non[ -]*be\]"; then echo "Non-bitexact cases without non-BE tag encountered"; exit 1; fi + ### run pytest + - exit_code=0 + - python3 -m pytest tests -v --html=report.html --self-contained-html --junit-xml=report-junit.xml || exit_code=$? + - if [ $exit_code -eq 1 ] && [ $non_be_flag == 0 ]; then echo "pytest run had failures and non-BE flag not present"; exit $EXIT_CODE_FAIL; fi + - zero_errors=$(cat report-junit.xml | grep -c 'errors="0"') || true + - if [ $exit_code -eq 1 ] && [ $zero_errors == 1 ]; then echo "pytest run had failures, but no errors and non-BE flag present"; exit $EXIT_CODE_NON_BE; fi + - if [ $exit_code -ne 0 ]; then echo "pytest run had errors"; exit $EXIT_CODE_FAIL; fi; + allow_failure: + exit_codes: + - 123 artifacts: + name: "main-push--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + when: always paths: - - test_output.txt - - scripts/test/logs - - scripts/ref/logs + - report-junit.xml + - report.html + expose_as: "Results of comparison to previous merge commit" + reports: + junit: report-junit.xml + +# --------------------------------------------------------------- +# Scheduled jobs on main +# --------------------------------------------------------------- +.sanitizer-test-template: + extends: + # TODO: still needed since MASA ltv vectors are not there yet + # when they were added, we can add a needs-ltv-dir template + - .test-job-linux-needs-testv-dir + stage: test + tags: + - sanitizer_test_main + artifacts: + name: "$CI_JOB_NAME--main--sha-$CI_COMMIT_SHORT_SHA" + when: always + paths: + - ep_015.g192 + - ./LOGS_PLC + - ./LOGS_noPLC + +### --- sanitizer schedule A --- + +.sanitizer-test-schedule-A: + extends: + - .sanitizer-test-template + + +sanitizer-test-mono: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + timeout: 2 hour + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py mono mono --tests $SANITIZER_TESTS + +sanitizer-test-stereo: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + when: delayed + start_in: 2 hour + timeout: 2 hour + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py stereo $OUT_FORMATS_CHANNEL_BASED --tests $SANITIZER_TESTS + +sanitizer-test-stereodmxevs: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + when: delayed + start_in: 4 hours + timeout: 2 hour + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py StereoDmxEVS mono --tests $SANITIZER_TESTS + +sanitizer-test-ism1: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + when: delayed + start_in: 6 hours + timeout: 2 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + +sanitizer-test-ism2: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + when: delayed + start_in: 8 hours + timeout: 3 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + +sanitizer-test-ism3: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + when: delayed + start_in: 11 hours + timeout: 3 hour + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + +sanitizer-test-ism4: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + when: delayed + start_in: 14 hours + timeout: 4 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + +sanitizer-test-masa: + extends: .sanitizer-test-schedule-A + rules: + - if: $SANITIZER_SCHEDULE_A + when: delayed + start_in: 18 hours + timeout: 3 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py MASA $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS +### --- sanitizer schedule B --- + +.sanitizer-test-schedule-B: + extends: + - .sanitizer-test-template + timeout: 4 hours + +sanitizer-test-mc-5_1: + extends: .sanitizer-test-schedule-B + rules: + - if: $SANITIZER_SCHEDULE_B + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py 5_1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + +sanitizer-test-mc-5_1_2: + extends: .sanitizer-test-schedule-B + rules: + - if: $SANITIZER_SCHEDULE_B + when: delayed + start_in: 4 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py 5_1_2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + +sanitizer-test-mc-5_1_4: + extends: .sanitizer-test-schedule-B + rules: + - if: $SANITIZER_SCHEDULE_B + when: delayed + start_in: 8 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py 5_1_4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + +sanitizer-test-mc-7_1: + extends: .sanitizer-test-schedule-B + rules: + - if: $SANITIZER_SCHEDULE_B + when: delayed + start_in: 12 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py 7_1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + +sanitizer-test-mc-7_1_4: + extends: .sanitizer-test-schedule-B + rules: + - if: $SANITIZER_SCHEDULE_B + when: delayed + start_in: 16 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py 7_1_4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + +### --- sanitizer schedule C --- + +.sanitizer-test-schedule-C: + extends: + - .sanitizer-test-template + timeout: 6 hours + +sanitizer-test-sba: + extends: .sanitizer-test-schedule-C + rules: + - if: $SANITIZER_SCHEDULE_C + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py SBA $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + +sanitizer-test-planarsba: + extends: .sanitizer-test-schedule-C + rules: + - if: $SANITIZER_SCHEDULE_C + when: delayed + start_in: 6 hours + script: + - *update-ltv-repo + - python3 ci/run_scheduled_sanitizer_test.py PlanarSBA $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + +# GCOV/LCOV coverage analysis of self_test suite +coverage-test-on-main-scheduled: + extends: + - .test-job-linux-needs-testv-dir + - .rules-main-scheduled + tags: + - ivas-linux + stage: test + rules: + # only run in scheduled pipeline that passes this env vars + - if: $COVERAGE_TEST + script: + - *print-common-info + - make GCOV=1 -j + - cp IVAS_rend IVAS_rend_ref # Copy exec to be able to run renderer script + - python3 tests/create_short_testvectors.py + - python3 -m pytest tests -v -n 0 --update_ref 1 -m create_ref --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec + - python3 -m pytest tests -v -n 0 --update_ref 1 -m create_ref_part2 --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec + - python3 -m pytest tests/test_param_file.py -v -n 0 --update_ref 1 -m create_ref --param_file scripts/config/self_test_evs.prm --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec + - bash ci/smoke_test.sh coverage + - python3 -m pytest -q -n auto tests/renderer/test_renderer_be_comparison.py + - bash ci/ivas_voip_be_test.sh coverage + - lcov -c -d obj -o coverage.info + - commit_sha=$(git rev-parse HEAD) + - genhtml coverage.info -o coverage -t "Coverage on main @ $commit_sha" + artifacts: + name: "main-coverage-sha-$CI_COMMIT_SHORT_SHA" + when: always + expire_in: 1 week + paths: + - coverage.info + - coverage + + +# --------------------------------------------------------------- +# Complexity measurement jobs +# --------------------------------------------------------------- + +.complexity-measurements-setup: &complexity-measurements-setup + # create necessary environment + - mkdir -p wmops/logs + + - job_id=$(python3 ci/get_id_of_last_job_occurence.py $CI_COMMIT_REF_NAME $CI_JOB_NAME) + - 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 + - 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 + - rm artifacts.zip + - rm -rf $public_dir + +.complexity-measurements-prepare-artifacts: &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 wmops/*.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 + # patch the format in the title + - 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: + # still needed as long as no long MASA testvectors are there + - .test-job-linux-needs-testv-dir + tags: + - test-complexity-measurement + timeout: 3 hours 30 minutes + stage: test + artifacts: + name: "$CI_JOB_NAME--$CI_COMMIT_REF_NAME--sha-$CI_COMMIT_SHA" + paths: + - $CI_JOB_NAME-public + +complexity-stereo-in-stereo-out: + extends: + - .complexity-template + rules: + - if: $MEASURE_COMPLEXITY_LINUX + script: + - *print-common-info + - *update-ltv-repo + - *complexity-measurements-setup + - in_format=stereo + - out_format=stereo + - bash ci/complexity_measurements/getWmops.sh "$in_format" "$out_format" + - *complexity-measurements-prepare-artifacts + +complexity-ism-in-binaural-out: + extends: + - .complexity-template + rules: + - if: $MEASURE_COMPLEXITY_LINUX + when: delayed + start_in: 1 hour + script: + - *print-common-info + - *update-ltv-repo + - *complexity-measurements-setup + - in_format=ISM + - out_format=BINAURAL + - bash ci/complexity_measurements/getWmops.sh "ISM1 ISM2 ISM3 ISM4" "$out_format" + - *complexity-measurements-prepare-artifacts + +complexity-sba-hoa3-in-hoa3-out: + extends: + - .complexity-template + rules: + - if: $MEASURE_COMPLEXITY_LINUX + when: delayed + start_in: 2 hours 30 minutes + script: + - *print-common-info + - *update-ltv-repo + - *complexity-measurements-setup + - in_format=SBA + - out_format=HOA3 + - bash ci/complexity_measurements/getWmops.sh "$in_format" "$out_format" + - *complexity-measurements-prepare-artifacts + +complexity-mc-in-7_1_4-out: + extends: + - .complexity-template + rules: + - if: $MEASURE_COMPLEXITY_LINUX + when: delayed + start_in: 4 hours + script: + - *print-common-info + - *update-ltv-repo + - *complexity-measurements-setup + - in_format=MC + - out_format=7_1_4 + - bash ci/complexity_measurements/getWmops.sh "$in_format" "$out_format" + - *complexity-measurements-prepare-artifacts + +complexity-masa-in-7_1_4-out: + extends: + - .complexity-template + rules: + - if: $MEASURE_COMPLEXITY_LINUX + when: delayed + start_in: 7 hours 30 minutes + script: + - *print-common-info + - *update-ltv-repo + - *complexity-measurements-setup + - in_format=MASA + - out_format=7_1_4 + - bash ci/complexity_measurements/getWmops.sh "$in_format" "$out_format" + - *complexity-measurements-prepare-artifacts + +complexity-StereoDmxEVS-stereo-in-mono-out: + extends: + - .complexity-template + rules: + - if: $MEASURE_COMPLEXITY_LINUX + when: delayed + start_in: 8 hours 30 minutes + script: + - *print-common-info + - *update-ltv-repo + - *complexity-measurements-setup + - in_format=StereoDmxEVS + - out_format=mono + - bash ci/complexity_measurements/getWmops.sh "$in_format" "$out_format" + - *complexity-measurements-prepare-artifacts + +# --------------------------------------------------------------- +# Other jobs +# --------------------------------------------------------------- + +# job that sets up gitlab pages website +pages: + stage: deploy + tags: + - ivas-linux + rules: + - if: $UPDATE_PAGES + script: + - python3 ci/setup_pages.py + artifacts: + paths: + - public # Pull state of a branch on 3GPP repo, push to a mirror repo. pull-from-3gpp-forge: @@ -157,10 +1157,10 @@ pull-from-3gpp-forge: script: # Set up git LFS for mirroring (see: https://github.com/git-lfs/git-lfs/issues/1762) - git lfs install --skip-smudge --local - + # Check out mirror branch - by default the runner checks out by commit hash, which results in detached head state - git checkout $CI_COMMIT_BRANCH - + # Pull commits from upstream - git remote add upstream https://forge.3gpp.org/rep/ivas-codec-pc/ivas-codec.git - git pull --ff-only --tags upstream $MIRROR_SOURCE_BRANCH @@ -168,4 +1168,3 @@ pull-from-3gpp-forge: # Push to mirror, include tags. Option `-o ci.skip` tells GitLab to skip CI for the pushed commits (assumed already tested upstream) - git push --tags -o ci.skip "https://${GITLAB_USER_LOGIN}:${MIRROR_ACCESS_TOKEN}@${CI_REPOSITORY_URL#*@}" "HEAD:${CI_COMMIT_BRANCH}" - diff --git a/.gitlab/issue_templates/bug_report.md b/.gitlab/issue_templates/bug_report.md new file mode 100644 index 0000000000000000000000000000000000000000..03c9638b1687d4b9c89fe6f9bba2f4c27efe6b0f --- /dev/null +++ b/.gitlab/issue_templates/bug_report.md @@ -0,0 +1,19 @@ +### Basic info + +- Commit SHA: +- Platform: + +### Bug description + + +### Ways to reproduce + +(Clear steps or refer to a failing automated test, e.g. with a pipeline link) + + + + + +/label ~Priority:: ~Company: ~Subpart: +/label ~Type:Bug ~Status::ToDo diff --git a/.gitlab/issue_templates/default.md b/.gitlab/issue_templates/default.md new file mode 100644 index 0000000000000000000000000000000000000000..b1243d30d761ebb0327398e45a0792486a92e52d --- /dev/null +++ b/.gitlab/issue_templates/default.md @@ -0,0 +1,7 @@ +(Generic issue template) + + + +/label ~Priority:: ~Company: ~Subpart: ~Type: +/label ~Status::ToDo diff --git a/.gitlab/issue_templates/sanitizer_error.md b/.gitlab/issue_templates/sanitizer_error.md new file mode 100644 index 0000000000000000000000000000000000000000..10ba7c7991ee472add8e72ec93d480c6d5f2ea4e --- /dev/null +++ b/.gitlab/issue_templates/sanitizer_error.md @@ -0,0 +1,39 @@ +### Basic info + +- Commit SHA: + +### Bug description + +Clang (msan/asan?) sanitizer test in pipeline found an error: + + +``` + +``` + + +Link to test pipeline: XXX + +### Ways to reproduce + +Using the [scripts](https://forge.3gpp.org/rep/ivas-codec-pc/ivas-codec/-/wikis/Software-development/pyivastest-howto#how-to-reproduce-tests): + + +``` +python3 scripts/IvasBuildAndRunChecks.py --checks CLANGX -m MODE -p /path/to/my/local/ci_linux_ltv_local.json +``` +or directly: + +``` +make clean +make -j CLANG=X +./IVAS_cod ... +eid-xor -vbr -fer bit ep_015.g192 bit_fer +./IVAS_dec ... +``` + + + +/label ~"Priority::Critical" ~Company: ~Subpart: +/label ~Type:Bug ~Status::ToDo diff --git a/.gitlab/merge_request_templates/generic_merge_request.md b/.gitlab/merge_request_templates/generic_merge_request.md new file mode 100644 index 0000000000000000000000000000000000000000..495bb9ce77a64c236afc8e26ea57047ca562aa65 --- /dev/null +++ b/.gitlab/merge_request_templates/generic_merge_request.md @@ -0,0 +1,12 @@ + +- Related issues: +- Requested reviewers: + +### Description + + + +/label ~Priority:: ~Company: ~Subpart: ~Type: ~Status:: + + + diff --git a/.gitlab/merge_request_templates/maintenance_task_mr.md b/.gitlab/merge_request_templates/maintenance_task_mr.md new file mode 100644 index 0000000000000000000000000000000000000000..9ddda469d79e44d85bb15a68c03d142304df533d --- /dev/null +++ b/.gitlab/merge_request_templates/maintenance_task_mr.md @@ -0,0 +1,9 @@ +- Requested reviewers: + +### Description + + + +/label ~Maintenance: +/label ~Status:: +/label ~Type: diff --git a/CMakeLists.txt b/CMakeLists.txt index ad70b858448a5fad0aebaf21c90c28419f70fbe7..8098dc1c6896db669b7b31edfd2717f703442fcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,43 +108,46 @@ if(WMOPS) add_definitions("-DWMOPS=1") endif() - project(stereo-evs) set_property(GLOBAL PROPERTY USE_FOLDERS ON) # make Visual Studio projects look nicer include(CTest) -include_directories( - lib_com - lib_debug - lib_dec - lib_enc - lib_util -) - file(GLOB libComSrcs "lib_com/*.c") file(GLOB libComHeaders "lib_com/*.h") add_library(lib_com ${libComSrcs} ${libComHeaders}) if(UNIX) target_link_libraries(lib_com m) endif() +target_include_directories(lib_com PUBLIC lib_com PRIVATE lib_enc lib_dec lib_rend lib_debug) file(GLOB libDebugSrcs "lib_debug/*.c") file(GLOB libDebugHeaders "lib_debug/*.h") add_library(lib_debug ${libDebugSrcs} ${libDebugHeaders}) +target_link_libraries(lib_debug lib_com) +target_include_directories(lib_debug PUBLIC lib_debug PRIVATE lib_enc lib_dec lib_rend) file(GLOB libEncSrcs "lib_enc/*.c") file(GLOB libEncHeaders "lib_enc/*.h") add_library(lib_enc ${libEncSrcs} ${libEncHeaders}) target_link_libraries(lib_enc lib_com lib_debug) +target_include_directories(lib_enc PUBLIC lib_enc PRIVATE lib_dec lib_rend) + +file(GLOB libRendSrcs "lib_rend/*.c") +file(GLOB libRendHeaders "lib_rend/*.h") +add_library(lib_rend ${libRendSrcs} ${libRendHeaders}) +target_link_libraries(lib_rend lib_dec lib_com lib_debug) # Todo refactor: This dependency on lib_dec should be removed. +target_include_directories(lib_rend PUBLIC lib_rend PRIVATE lib_enc) file(GLOB libDecSrcs "lib_dec/*.c") file(GLOB libDecHeaders "lib_dec/*.h") add_library(lib_dec ${libDecSrcs} ${libDecHeaders}) -target_link_libraries(lib_dec lib_com lib_debug) +target_link_libraries(lib_dec lib_com lib_rend lib_debug) +target_include_directories(lib_dec PUBLIC lib_dec lib_rend PRIVATE lib_enc) file(GLOB libUtilSrcs "lib_util/*.c") file(GLOB libUtilHeaders "lib_util/*.h") add_library(lib_util ${libUtilSrcs} ${libUtilHeaders}) +target_include_directories(lib_util PUBLIC lib_util PRIVATE lib_com lib_enc lib_dec lib_rend lib_debug) add_executable(IVAS_cod apps/encoder.c) target_link_libraries(IVAS_cod lib_enc lib_util) @@ -158,11 +161,16 @@ if(WIN32) target_link_libraries(IVAS_dec Ws2_32) endif() -if(${IVAS_BUILD_PRERENDERER}) - add_executable(IVAS_prerenderer - scripts/prerenderer/prerenderer.c - ${libEncSrcs} - ${libDecSrcs} - ) - target_link_libraries(IVAS_prerenderer lib_com lib_dec lib_debug lib_util) +add_executable(IVAS_rend apps/renderer.c) +target_link_libraries(IVAS_rend lib_rend lib_util) +target_include_directories(IVAS_rend PRIVATE lib_enc) + +if(COPY_EXECUTABLES_FROM_BUILD_DIR) + # Optionally copy executables to the same place where Make puts them (useful for tests that expect executables in specific places) + add_custom_command(TARGET IVAS_cod POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") + add_custom_command(TARGET IVAS_dec POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") + add_custom_command(TARGET IVAS_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") endif() + +# Allow creating packages for CMake install +install(TARGETS lib_enc lib_dec lib_rend lib_com lib_util ARCHIVE DESTINATION lib) diff --git a/LICENSE.md b/LICENSE.md index 86e7d39ae78af379ad50fe4f18c1da3284947cd4..aa9c35e4f9786f3321942cacb1f56d7d91840e20 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/Makefile b/Makefile index 76c916c1d2cd05f1d4bbc38bbff20f9a9b43ab19..7f8874d3439cc1fb73096cd5af609880ba9b874a 100644 --- a/Makefile +++ b/Makefile @@ -5,33 +5,25 @@ SRC_LIBCOM = lib_com SRC_LIBDEBUG = lib_debug SRC_LIBDEC = lib_dec SRC_LIBENC = lib_enc +SRC_LIBREND = lib_rend SRC_LIBUTIL = lib_util SRC_APP = apps BUILD = build OBJDIR = obj -# Dirs for python unittests -UTESTS_SCRIPT_DIR = scripts/ivas_pytests -UTESTS_DIR = $(UTESTS_SCRIPT_DIR)/tests/unit_tests -UTESTS_CREND_DIR = $(UTESTS_DIR)/crend - -# Source paths for python unittests -SRC_UTESTS = $(UTESTS_CREND_DIR) - - -SRC_DIRS = $(sort -u $(SRC_LIBCOM) $(SRC_LIBDEBUG) $(SRC_LIBDEC) $(SRC_LIBENC) $(SRC_LIBUTIL) $(SRC_APP) $(SRC_UTESTS)) +SRC_DIRS = $(sort -u $(SRC_LIBCOM) $(SRC_LIBDEBUG) $(SRC_LIBDEC) $(SRC_LIBENC) $(SRC_LIBREND) $(SRC_LIBUTIL) $(SRC_APP)) # Name of CLI binaries CLI_APIDEC ?= IVAS_dec CLI_APIENC ?= IVAS_cod +CLI_APIREND ?= IVAS_rend LIB_LIBCOM ?= libivascom.a LIB_LIBDEBUG ?= libivasdebug.a LIB_LIBDEC ?= libivasdec.a LIB_LIBENC ?= libivasenc.a +LIB_LIBREND ?= libivasrend.a LIB_LIBUTIL ?= libivasutil.a -CLI_UTESTS_CREND ?= IVAS_crend_unit_test - # Default tool settings CC ?= gcc RM ?= rm -f @@ -125,31 +117,27 @@ SRCS_LIBCOM = $(foreach DIR,$(SRC_LIBCOM),$(patsubst $(DIR)/%,%,$(wildcard $(D SRCS_LIBDEBUG = $(foreach DIR,$(SRC_LIBDEBUG),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) SRCS_LIBDEC = $(foreach DIR,$(SRC_LIBDEC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) SRCS_LIBENC = $(foreach DIR,$(SRC_LIBENC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) +SRCS_LIBREND = $(foreach DIR,$(SRC_LIBREND),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) SRCS_LIBUTIL = $(foreach DIR,$(SRC_LIBUTIL),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) -SRCS_UTESTS_CREND = $(foreach DIR,$(UTESTS_CREND_DIR),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) - OBJS_LIBCOM = $(addprefix $(OBJDIR)/,$(SRCS_LIBCOM:.c=.o)) OBJS_LIBDEBUG = $(addprefix $(OBJDIR)/,$(SRCS_LIBDEBUG:.c=.o)) OBJS_LIBDEC = $(addprefix $(OBJDIR)/,$(SRCS_LIBDEC:.c=.o)) OBJS_LIBENC = $(addprefix $(OBJDIR)/,$(SRCS_LIBENC:.c=.o)) +OBJS_LIBREND = $(addprefix $(OBJDIR)/,$(SRCS_LIBREND:.c=.o)) OBJS_LIBUTIL = $(addprefix $(OBJDIR)/,$(SRCS_LIBUTIL:.c=.o)) OBJS_CLI_APIDEC = $(OBJDIR)/decoder.o OBJS_CLI_APIENC = $(OBJDIR)/encoder.o - -OBJS_CLI_UTESTS_CREND = $(addprefix $(OBJDIR)/,$(SRCS_UTESTS_CREND:.c=.o)) - -OBJS_UTESTS = $(OBJS_CLI_UTESTS_CREND) - +OBJS_CLI_APPREND = $(OBJDIR)/renderer.o DEPS = $(addprefix $(OBJDIR)/,$(SRCS_LIBCOM:.c=.P) $(SRCS_LIBDEBUG:.c=.P) $(SRCS_LIBDEC:.c=.P) \ $(SRCS_LIBENC:.c=.P) $(SRCS_LIBUTIL:.c=.P)) ############################################################################### -.PHONY: all clean clean_unittests clean_all +.PHONY: all clean -all: $(CLI_APIENC) $(CLI_APIDEC) +all: $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) $(OBJDIR): $(QUIET)mkdir -p $(OBJDIR) @@ -157,7 +145,7 @@ $(OBJDIR): $(LIB_LIBCOM): $(OBJS_LIBCOM) $(QUIET_AR)$(AR) rcs $@ $^ -$(LIB_LIBDEC): $(OBJS_LIBDEC) +$(LIB_LIBDEC): $(OBJS_LIBDEC) $(OBJS_LIBREND) $(QUIET_AR)$(AR) rcs $@ $^ $(LIB_LIBDEBUG): $(OBJS_LIBDEBUG) @@ -166,31 +154,28 @@ $(LIB_LIBDEBUG): $(OBJS_LIBDEBUG) $(LIB_LIBENC): $(OBJS_LIBENC) $(QUIET_AR)$(AR) rcs $@ $^ -$(LIB_LIBUTIL): $(OBJS_LIBUTIL) +$(LIB_LIBREND): $(OBJS_LIBREND) $(QUIET_AR)$(AR) rcs $@ $^ -$(CLI_APIENC): $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(OBJS_CLI_APIENC) - $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIENC) -L. -livasutil -livasenc -livascom -livasdebug $(LDLIBS) -o $(CLI_APIENC) +$(LIB_LIBUTIL): $(OBJS_LIBUTIL) + $(QUIET_AR)$(AR) rcs $@ $^ -$(CLI_APIDEC): $(LIB_LIBDEC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(OBJS_CLI_APIDEC) - $(QUIET_LINK)$(CC) $(OBJS_CLI_APIDEC) $(LDFLAGS) -L. -livasutil -livasdec -livascom -livasdebug $(LDLIBS) -o $(CLI_APIDEC) +$(CLI_APIENC): $(OBJS_CLI_APIENC) $(LIB_LIBENC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIENC) -L. -livasenc -livascom -livasutil -livasdebug $(LDLIBS) -o $(CLI_APIENC) -$(CLI_UTESTS_CREND): $(LIB_LIBDEC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBENC) $(LIB_LIBUTIL) $(OBJS_CLI_UTESTS_CREND) - $(QUIET_LINK)$(CC) $(OBJS_CLI_UTESTS_CREND) $(LDFLAGS) -L. -livasutil -livasdec -livascom -livasdebug $(LDLIBS) -o $(UTESTS_CREND_DIR)/$(CLI_UTESTS_CREND) +$(CLI_APIDEC): $(OBJS_CLI_APIDEC) $(LIB_LIBDEC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIDEC) -L. -livasdec -livascom -livasutil -livasdebug $(LDLIBS) -o $(CLI_APIDEC) -unittests: $(CLI_UTESTS_CREND) +$(CLI_APIREND): $(OBJS_CLI_APPREND) $(LIB_LIBREND) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LIBDEC) + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APPREND) -L. -livasrend -livasdec -livasutil -livasdebug -livascom $(LDLIBS) -o $(CLI_APIREND) -libs: $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBUTIL) +libs: $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBREND) $(LIB_LIBUTIL) -clean: clean_unittests +clean: $(QUIET)$(RM) $(OBJS_LIBENC) $(OBJS_LIBDEC) $(DEPS) $(QUIET)$(RM) $(DEPS:.P=.d) $(QUIET)test ! -d $(OBJDIR) || rm -rf $(OBJDIR) - $(QUIET)$(RM) $(CLI_APIENC) $(CLI_APIDEC) $(CLI_PRD) $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBUTIL) - -clean_unittests: - $(QUIET)$(RM) $(OBJS_UTESTS) - $(QUIET)$(RM) $(UTESTS_CREND_DIR)/$(CLI_UTESTS_CREND) + $(QUIET)$(RM) $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBUTIL) $(LIB_LIBREND) $(OBJDIR)/%.o : %.c | $(OBJDIR) $(QUIET_CC)$(CC) $(CFLAGS) -c -MD -o $@ $< diff --git a/Workspace_msvc/Workspace_msvc.sln b/Workspace_msvc/Workspace_msvc.sln index be693e81ccdd6c6a725c8b9697cc74ccd8bfdf75..fbdb561ee2403a9fbcb65671157eafc4b8a21f88 100644 --- a/Workspace_msvc/Workspace_msvc.sln +++ b/Workspace_msvc/Workspace_msvc.sln @@ -8,6 +8,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_enc", "lib_enc.vcxproj" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_com", "lib_com.vcxproj", "{39EC200D-7795-4FF8-B214-B24EDA5526AE}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_rend", "lib_rend.vcxproj", "{718DE063-A18B-BB72-9150-62B892E6FFA6}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_util", "lib_util.vcxproj", "{2FA8F384-0775-F3B7-F8C3-85209222FC70}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_debug", "lib_debug.vcxproj", "{54509728-928B-44D9-A118-A6F92F08B34F}" @@ -16,21 +18,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decoder", "decoder.vcxproj" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encoder", "encoder.vcxproj", "{B3FC9DFC-7268-8660-7C0D-B60BAF02C554}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderer", "renderer.vcxproj", "{12B4C8A5-1E06-4E30-B443-D1F916F52B47}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{51160D4C-55C9-4C16-A792-D94507225746}" ProjectSection(SolutionItems) = preProject ..\.clang-format = ..\.clang-format EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ivas_crend_unit_test", "..\scripts\ivas_pytests\tests\unit_tests\crend\ivas_crend_unit_test.vcxproj", "{32354377-ACA7-40F9-9A0E-87FC956F0B78}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 - Unittests|Win32 = Unittests|Win32 - Unittests|x64 = Unittests|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -39,71 +39,54 @@ Global {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Release|Win32.ActiveCfg = Release|Win32 {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Release|Win32.Build.0 = Release|Win32 {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Release|x64.ActiveCfg = Release|Win32 - {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Unittests|Win32.ActiveCfg = Unittests|Win32 - {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Unittests|Win32.Build.0 = Unittests|Win32 - {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Unittests|x64.ActiveCfg = Unittests|Win32 {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Debug|Win32.ActiveCfg = Debug|Win32 {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Debug|Win32.Build.0 = Debug|Win32 {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Debug|x64.ActiveCfg = Debug|Win32 {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Release|Win32.ActiveCfg = Release|Win32 {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Release|Win32.Build.0 = Release|Win32 {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Release|x64.ActiveCfg = Release|Win32 - {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Unittests|Win32.ActiveCfg = Unittests|Win32 - {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Unittests|Win32.Build.0 = Unittests|Win32 - {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Unittests|x64.ActiveCfg = Unittests|Win32 {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Debug|Win32.ActiveCfg = Debug|Win32 {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Debug|Win32.Build.0 = Debug|Win32 {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Debug|x64.ActiveCfg = Debug|Win32 {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Release|Win32.ActiveCfg = Release|Win32 {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Release|Win32.Build.0 = Release|Win32 {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Release|x64.ActiveCfg = Release|Win32 - {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Unittests|Win32.ActiveCfg = Unittests|Win32 - {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Unittests|Win32.Build.0 = Unittests|Win32 - {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Unittests|x64.ActiveCfg = Unittests|Win32 + {718DE063-A18B-BB72-9150-62B892E6FFA6}.Debug|Win32.ActiveCfg = Debug|Win32 + {718DE063-A18B-BB72-9150-62B892E6FFA6}.Debug|Win32.Build.0 = Debug|Win32 + {718DE063-A18B-BB72-9150-62B892E6FFA6}.Debug|x64.ActiveCfg = Debug|Win32 + {718DE063-A18B-BB72-9150-62B892E6FFA6}.Release|Win32.ActiveCfg = Release|Win32 + {718DE063-A18B-BB72-9150-62B892E6FFA6}.Release|Win32.Build.0 = Release|Win32 + {718DE063-A18B-BB72-9150-62B892E6FFA6}.Release|x64.ActiveCfg = Release|Win32 {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Debug|Win32.ActiveCfg = Debug|Win32 {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Debug|Win32.Build.0 = Debug|Win32 {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Debug|x64.ActiveCfg = Debug|Win32 {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Release|Win32.ActiveCfg = Release|Win32 {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Release|Win32.Build.0 = Release|Win32 {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Release|x64.ActiveCfg = Release|Win32 - {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Unittests|Win32.ActiveCfg = Unittests|Win32 - {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Unittests|Win32.Build.0 = Unittests|Win32 - {2FA8F384-0775-F3B7-F8C3-85209222FC70}.Unittests|x64.ActiveCfg = Unittests|Win32 {54509728-928B-44D9-A118-A6F92F08B34F}.Debug|Win32.ActiveCfg = Debug|Win32 {54509728-928B-44D9-A118-A6F92F08B34F}.Debug|Win32.Build.0 = Debug|Win32 {54509728-928B-44D9-A118-A6F92F08B34F}.Debug|x64.ActiveCfg = Debug|Win32 {54509728-928B-44D9-A118-A6F92F08B34F}.Release|Win32.ActiveCfg = Release|Win32 {54509728-928B-44D9-A118-A6F92F08B34F}.Release|Win32.Build.0 = Release|Win32 {54509728-928B-44D9-A118-A6F92F08B34F}.Release|x64.ActiveCfg = Release|Win32 - {54509728-928B-44D9-A118-A6F92F08B34F}.Unittests|Win32.ActiveCfg = Unittests|Win32 - {54509728-928B-44D9-A118-A6F92F08B34F}.Unittests|Win32.Build.0 = Unittests|Win32 - {54509728-928B-44D9-A118-A6F92F08B34F}.Unittests|x64.ActiveCfg = Unittests|Win32 {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Debug|Win32.ActiveCfg = Debug|Win32 {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Debug|Win32.Build.0 = Debug|Win32 {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Debug|x64.ActiveCfg = Debug|Win32 {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Release|Win32.ActiveCfg = Release|Win32 {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Release|Win32.Build.0 = Release|Win32 {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Release|x64.ActiveCfg = Release|Win32 - {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Unittests|Win32.ActiveCfg = Unittests|Win32 - {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Unittests|Win32.Build.0 = Unittests|Win32 - {E3DCBC31-7FC9-D127-E000-529F8460D5FD}.Unittests|x64.ActiveCfg = Unittests|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Debug|Win32.ActiveCfg = Debug|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Debug|Win32.Build.0 = Debug|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Debug|x64.ActiveCfg = Debug|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Release|Win32.ActiveCfg = Release|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Release|Win32.Build.0 = Release|Win32 {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Release|x64.ActiveCfg = Release|Win32 - {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Unittests|Win32.ActiveCfg = Unittests|Win32 - {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Unittests|Win32.Build.0 = Unittests|Win32 - {B3FC9DFC-7268-8660-7C0D-B60BAF02C554}.Unittests|x64.ActiveCfg = Unittests|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Debug|Win32.ActiveCfg = Debug|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Debug|x64.ActiveCfg = Debug|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Release|Win32.ActiveCfg = Release|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Release|x64.ActiveCfg = Release|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Unittests|Win32.ActiveCfg = Release|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Unittests|Win32.Build.0 = Release|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Unittests|x64.ActiveCfg = Release|Win32 - {32354377-ACA7-40F9-9A0E-87FC956F0B78}.Unittests|x64.Build.0 = Release|Win32 + {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Debug|Win32.ActiveCfg = Debug|Win32 + {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Debug|Win32.Build.0 = Debug|Win32 + {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Debug|x64.ActiveCfg = Debug|Win32 + {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Release|Win32.ActiveCfg = Release|Win32 + {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Release|Win32.Build.0 = Release|Win32 + {12B4C8A5-1E06-4E30-B443-D1F916F52B47}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Workspace_msvc/decoder.vcxproj b/Workspace_msvc/decoder.vcxproj index 8a71725962dd0cceb6df2ff03d37d99408437832..e59992847c71b085235a5232aad1afa7d710d17f 100644 --- a/Workspace_msvc/decoder.vcxproj +++ b/Workspace_msvc/decoder.vcxproj @@ -9,10 +9,6 @@ Release Win32 - - Unittests - Win32 - decoder @@ -27,12 +23,6 @@ false MultiByte - - Application - v141 - false - MultiByte - Application v141 @@ -46,10 +36,6 @@ - - - - @@ -65,13 +51,6 @@ false IVAS_dec - - ..\ - .\Debug_$(ProjectName)\ - false - false - IVAS_dec - ..\ .\Release_$(ProjectName)\ @@ -89,7 +68,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_dec;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) EnableFastChecks @@ -121,56 +100,6 @@ MachineX86 - - - - - - - $(IntDir)$(ProjectName).tlb - - - - - Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) - - - EnableFastChecks - MultiThreadedDebug - false - - - - - $(IntDir)$(ProjectName).pdb - Level4 - true - OldStyle - Default - %(DisableSpecificWarnings) - - - _DEBUG;%(PreprocessorDefinitions) - 0x0c0c - - - - - $(OutDir)$(TargetName).exe - true - - - true - $(IntDir)$(ProjectName).pdb - Console - false - - - MachineX86 - - $(IntDir)$(ProjectName).tlb @@ -183,7 +112,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_dec;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true diff --git a/Workspace_msvc/encoder.vcxproj b/Workspace_msvc/encoder.vcxproj index 755e404b67a52507e54da9b60b2690d42ab4b6d5..bcfe92a4db2218e2e04ae78a7cf7ea35cdc24349 100644 --- a/Workspace_msvc/encoder.vcxproj +++ b/Workspace_msvc/encoder.vcxproj @@ -89,7 +89,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_enc;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) EnableFastChecks @@ -198,7 +198,7 @@ Neither false false - ..\lib_enc;..\lib_dec;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) + ..\lib_enc;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj index a8063b8498401f1f8f9954fbf75efe81d1425bea..23aa2ae3f0b6722871f7f9d2c37b27e41f46862f 100644 --- a/Workspace_msvc/lib_com.vcxproj +++ b/Workspace_msvc/lib_com.vcxproj @@ -78,7 +78,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks @@ -109,7 +109,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) @@ -147,7 +147,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true @@ -244,9 +244,9 @@ + - @@ -261,7 +261,6 @@ - @@ -269,6 +268,7 @@ + diff --git a/Workspace_msvc/lib_com.vcxproj.filters b/Workspace_msvc/lib_com.vcxproj.filters index c33a360403d72a43643e3956c57da676d39cefc0..7b6854e7184cd0ec212f9819aa783944db688a6a 100644 --- a/Workspace_msvc/lib_com.vcxproj.filters +++ b/Workspace_msvc/lib_com.vcxproj.filters @@ -379,9 +379,6 @@ common_evs_c - - common_ivas_c - common_ivas_c @@ -445,9 +442,6 @@ common_ivas_c - - common_ivas_c - common_ivas_c @@ -466,6 +460,12 @@ common_ivas_c + + common_ivas_c + + + common_ivas_c + diff --git a/Workspace_msvc/lib_debug.vcxproj b/Workspace_msvc/lib_debug.vcxproj index 58dbb6aab7a0e9da53c0f896fd1122c1b74e2148..3b648fae048920ae06aa709785d4b49d2e58d710 100644 --- a/Workspace_msvc/lib_debug.vcxproj +++ b/Workspace_msvc/lib_debug.vcxproj @@ -73,7 +73,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) false @@ -97,7 +97,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) false @@ -124,7 +124,7 @@ AnySuitable false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true @@ -143,20 +143,14 @@ - - - - - + + - - - - - + + diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index 94abc50aeb37d4287d726c4f49e69c126faace87..e1c0f9ead1e80039fb23607500d3580bece6215c 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -89,7 +89,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks @@ -126,7 +126,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) @@ -169,7 +169,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) true @@ -264,71 +264,50 @@ - - - + + - - - - + + - + - - - - - - - - + + - - - - - - - - - - - - + - - + @@ -342,10 +321,9 @@ - - + @@ -393,10 +371,7 @@ - - - @@ -419,6 +394,10 @@ {54509728-928b-44d9-a118-a6f92f08b34f} false + + {718DE063-A18B-BB72-9150-62B892E6FFA6} + false + diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters index 13ac1ed64628a7efbfa6924b8d44db15839fbf3b..d1dedc413cef958bb637b92972c2b95ef1656319 100644 --- a/Workspace_msvc/lib_dec.vcxproj.filters +++ b/Workspace_msvc/lib_dec.vcxproj.filters @@ -13,9 +13,6 @@ dec_ivas_c - - dec_ivas_c - dec_ivas_c @@ -28,24 +25,6 @@ dec_ivas_c - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - dec_ivas_c @@ -406,24 +385,9 @@ dec_ivas_c - - dec_ivas_c - - - dec_ivas_c - dec_ivas_c - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - dec_ivas_c @@ -448,15 +412,9 @@ dec_ivas_c - - dec_ivas_c - dec_ivas_c - - dec_ivas_c - dec_ivas_c @@ -505,83 +463,59 @@ dec_ivas_c - - dec_ivas_c - dec_ivas_c - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - dec_ivas_c - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - - - dec_ivas_c - - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c - + dec_ivas_c @@ -598,9 +532,6 @@ dec_h - - dec_h - dec_h @@ -626,12 +557,6 @@ dec_h - - dec_h - - - dec_h - diff --git a/Workspace_msvc/lib_enc.vcxproj b/Workspace_msvc/lib_enc.vcxproj index 7eb81ef8e2423ddfa7364bcea9314ab3e01a93fe..15f0d535745d95fec1fd22eb4d139f5ca5e8d06f 100644 --- a/Workspace_msvc/lib_enc.vcxproj +++ b/Workspace_msvc/lib_enc.vcxproj @@ -89,7 +89,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks @@ -129,7 +129,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) @@ -176,7 +176,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true @@ -206,17 +206,18 @@ + + - - + @@ -330,8 +331,8 @@ - + diff --git a/Workspace_msvc/lib_enc.vcxproj.filters b/Workspace_msvc/lib_enc.vcxproj.filters index 5874c4a6277819ef4fbd409eaeba58d02c1daf59..21941038ec37e6a53cc81c9c3c915e69cbe0ac5f 100644 --- a/Workspace_msvc/lib_enc.vcxproj.filters +++ b/Workspace_msvc/lib_enc.vcxproj.filters @@ -550,9 +550,6 @@ enc_ivas_c - - enc_ivas_c - enc_ivas_c @@ -575,13 +572,19 @@ enc_ivas_c - + enc_ivas_c - + + enc_ivas_c + + + enc_ivas_c + + enc_ivas_c - + enc_ivas_c diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..865652649a8a320ff0769bd83170528445da8ab3 --- /dev/null +++ b/Workspace_msvc/lib_rend.vcxproj @@ -0,0 +1,256 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Unittests + Win32 + + + + lib_rend + {718DE063-A18B-BB72-9150-62B892E6FFA6} + evs_dec + 10.0.17763.0 + + + StaticLibrary + v141 + false + MultiByte + + + StaticLibrary + v141 + false + MultiByte + + + + StaticLibrary + v141 + false + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27428.2015 + + + .\Debug_$(ProjectName)\ + .\Debug_$(ProjectName)\ + false + false + libivasrend + + + .\Debug_$(ProjectName)\ + .\Debug_$(ProjectName)\ + false + false + libivasrend + + + .\Release_$(ProjectName)\ + .\Release_$(ProjectName)\ + false + false + libivasrend + + + + + + + .\Debug\$(ProjectName).tlb + + + + Disabled + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + OldStyle + Default + %(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib; %(AdditionalDependencies) + $(OutDir)$(TargetName).lib + true + + + + + + + + + .\Debug\$(ProjectName).tlb + + + + + Disabled + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) + + + EnableFastChecks + MultiThreadedDebug + false + + + + + $(IntDir)$(ProjectName).pdb + Level4 + true + OldStyle + Default + %(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib; %(AdditionalDependencies) + $(OutDir)$(TargetName).lib + true + + + + + + + + $(IntDir)$(ProjectName).tlb + + + + MaxSpeed + AnySuitable + false + Neither + false + false + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + + Default + %(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib; %(AdditionalDependencies) + $(OutDir)$(TargetName).lib + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {39ec200d-7795-4ff8-b214-b24eda5526ae} + false + + + {54509728-928b-44d9-a118-a6f92f08b34f} + false + + + + + + + + + + + \ No newline at end of file diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj index ae4cb9ef3cd75991a3982093df42bbe8c7d7f108..5b5e5f30ccdc3697e60b72e2b74750fe06e90598 100644 --- a/Workspace_msvc/lib_util.vcxproj +++ b/Workspace_msvc/lib_util.vcxproj @@ -73,7 +73,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);ZLIB_WINAPI;%(PreprocessorDefinitions) false @@ -93,7 +93,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;..\lib_rend;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);ZLIB_WINAPI;%(PreprocessorDefinitions) false @@ -117,7 +117,7 @@ AnySuitable false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);ZLIB_WINAPI;%(PreprocessorDefinitions) true @@ -141,13 +141,16 @@ + + + @@ -161,13 +164,16 @@ + + + diff --git a/scripts/prerenderer/Workspace_msvc/prerenderer.vcxproj b/Workspace_msvc/renderer.vcxproj similarity index 58% rename from scripts/prerenderer/Workspace_msvc/prerenderer.vcxproj rename to Workspace_msvc/renderer.vcxproj index ed2ad4ff8582f1c09860287725d8087e8fc511b0..94ad9f774e7bd050c4e940eb9a47911f18d783ef 100644 --- a/scripts/prerenderer/Workspace_msvc/prerenderer.vcxproj +++ b/Workspace_msvc/renderer.vcxproj @@ -9,11 +9,15 @@ Release Win32 + + Unittests + Win32 + - prerenderer - {12b4c8a5-1e06-4e30-b443-d1f916f52b47} - prerenderer + renderer + {12B4C8A5-1E06-4E30-B443-D1F916F52B47} + renderer 10.0.17763.0 @@ -23,6 +27,12 @@ false MultiByte + + Application + v141 + false + MultiByte + Application v141 @@ -34,27 +44,40 @@ + + + + + + <_ProjectFileVersion>15.0.27428.2015 - .. + ..\ + .\Debug_$(ProjectName)\ + false + false + IVAS_rend + + + ..\ .\Debug_$(ProjectName)\ false false - IVAS_prerenderer + IVAS_rend - .. + ..\ .\Release_$(ProjectName)\ false false - IVAS_prerenderer + IVAS_rend @@ -63,8 +86,8 @@ Disabled - ..\..\..\lib_com;..\..\..\lib_debug;..\..\..\lib_dec;..\..\..\lib_enc;..\..\..\lib_util;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\lib_com;..\lib_dec;..\lib_enc;..\lib_debug;..\lib_util;..\lib_rend;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -76,7 +99,7 @@ true OldStyle Default - 4100;%(DisableSpecificWarnings) + %(DisableSpecificWarnings) _DEBUG;%(PreprocessorDefinitions) @@ -87,16 +110,64 @@ $(OutDir)$(TargetName).exe true - false true $(IntDir)$(ProjectName).pdb Console - false MachineX86 + + + + + + + $(IntDir)$(ProjectName).tlb + + + + + Disabled + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_util;..\lib_rend;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) + + + EnableFastChecks + MultiThreadedDebug + false + + + + + $(IntDir)$(ProjectName).pdb + Level4 + true + OldStyle + Default + %(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + + + $(OutDir)$(TargetName).exe + true + + + true + $(IntDir)$(ProjectName).pdb + Console + false + + + MachineX86 + + $(IntDir)$(ProjectName).tlb @@ -109,8 +180,8 @@ Neither false false - ..\..\..\lib_com;..\..\..\lib_debug;..\..\..\lib_dec;..\..\..\lib_enc;..\..\..\lib_util;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\lib_com;..\lib_dec;..\lib_enc;..\lib_debug;..\lib_util;..\lib_rend;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true Default @@ -125,7 +196,7 @@ true Default - 4100;%(DisableSpecificWarnings) + %(DisableSpecificWarnings) NDEBUG;%(PreprocessorDefinitions) @@ -141,43 +212,34 @@ false MachineX86 + libcmtd.lib - + + + + {54509728-928B-44D9-A118-A6F92F08B34F} false - + + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3} + false + + {2FA8F384-0775-F3B7-F8C3-85209222FC70} false - + {39ec200d-7795-4ff8-b214-b24eda5526ae} false - - {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3} + + {718DE063-A18B-BB72-9150-62B892E6FFA6} false - - - - - - - - - - - - - - - - - diff --git a/apps/decoder.c b/apps/decoder.c index 73ba2ab622307f2dbf519f30890a563429c572f9..d2260713c28f0b618033d3d2229c77794147b1dc 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,6 +30,9 @@ *******************************************************************************************************/ +#include +#include +#include #include "lib_dec.h" #include "cmdl_tools.h" #include "audio_file_writer.h" @@ -39,26 +42,18 @@ #include "ls_custom_file_reader.h" #include "hrtf_file_reader.h" #include "head_rotation_file_reader.h" +#include "vector3_pair_file_reader.h" #include "jbm_file_writer.h" #include "evs_rtp_payload.h" -#include -#include -#ifdef WMOPS -#include "PROM_Size_lib_com.h" -#include "PROM_Size_lib_dec.h" -#include "wmops.h" -#endif -#ifdef RAM_COUNTING_TOOL -#include "mem_count.h" -#else -#include -#endif #ifdef DEBUGGING #include "debug.h" #endif +#include "wmc_auto.h" #include "render_config_reader.h" +#include "hrtf_file_reader.h" + -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /*------------------------------------------------------------------------------------------* * Local constants, enums, structures @@ -70,18 +65,16 @@ static int32_t frame = 0; /* Counter of frames */ #define MIN_NUM_BITS_ACTIVE_FRAME 56 -#define NUM_BITS_SID_IVAS_4K4 88 -#define NUM_BITS_SID_IVAS_7K8 156 -#define NUM_BITS_SID_IVAS_9K3 186 -#define NUM_BITS_SID_IVAS_10K2 204 -#define META_LINE_LENGTH 200 +#define NUM_BITS_SID_IVAS_5K2 104 #define MAX_FRAME_SIZE ( 48000 / 50 ) #define MAX_NUM_OUTPUT_CHANNELS 16 #define MAX_OUTPUT_PCM_BUFFER_SIZE ( MAX_NUM_OUTPUT_CHANNELS * MAX_FRAME_SIZE ) -#define IVAS_PUBLIC_ORIENT_TRK_REF 0 -#define IVAS_PUBLIC_ORIENT_TRK_AVG 1 - +#define IVAS_PUBLIC_ORIENT_TRK_NONE ( 0 ) +#define IVAS_PUBLIC_ORIENT_TRK_REF ( 1 ) +#define IVAS_PUBLIC_ORIENT_TRK_AVG ( 2 ) +#define IVAS_PUBLIC_ORIENT_TRK_REF_VEC ( 3 ) +#define IVAS_PUBLIC_ORIENT_TRK_REF_VEC_LEV ( 4 ) typedef struct { @@ -95,6 +88,10 @@ typedef struct bool voipMode; bool enableHeadRotation; char *headrotTrajFileName; + bool enableReferenceRotation; + char *refrotTrajFileName; + bool enableReferenceVectorTracking; + char *referenceVectorTrajFileName; #ifdef SUPPORT_JBM_TRACEFILE char *jbmTraceFilename; #endif @@ -103,21 +100,24 @@ typedef struct float FER; bool hrtfReaderEnabled; char *hrtfFileName; + bool hrtfCRendReaderEnabled; + char *hrtfCRendFileName; IVAS_DEC_INPUT_FORMAT inputFormat; -#ifdef DEBUGGING - bool forceSubframeBinauralization; - IVAS_DEC_FORCED_REND_MODE forcedRendMode; -#endif bool customLsOutputEnabled; char *customLsSetupFilename; int16_t orientation_tracking; float no_diegetic_pan; bool renderConfigEnabled; char *renderConfigFilename; + +#ifdef DEBUGGING + IVAS_DEC_FORCED_REND_MODE forcedRendMode; #ifdef DEBUG_FOA_AGC FILE *agcBitstream; /* temporary */ #endif +#endif + } DecArguments; @@ -127,51 +127,15 @@ typedef struct static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg ); static void usage_dec( void ); -#ifdef DEBUGGING -static int16_t app_own_random( int16_t *seed ); -#endif -static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, HeadRotFileReader *headRotReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, HeadRotFileReader *headRotReader, HeadRotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); #ifdef DEBUGGING +static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); +static int16_t app_own_random( int16_t *seed ); static IVAS_DEC_FORCED_REND_MODE parseForcedRendModeDec( char *forcedRendModeChar ); #endif -#ifdef WMOPS -/*------------------------------------------------------------------------------------------* - * Function to print complexity & memory estimates at the decoder - *------------------------------------------------------------------------------------------*/ - -extern int16_t *ptr_base_stack; -extern int16_t *ptr_base_stack; -extern int16_t *ptr_max_stack; -extern int32_t wc_frame; -extern char location_max_stack[256]; -void print_stack_call_tree( void ); - -static void print_mem_dec( size_t SRAM_size ) -{ - fprintf( stdout, "\n\n --- Decoder memory usage --- \n\n" ); - - fprintf( stdout, "PROM size (decoder): %d words (or instructions)\n", PROM_Size_lib_dec ); - fprintf( stdout, "PROM size (common): %d words (or instructions)\n", PROM_Size_lib_com ); - fprintf( stdout, "Stack size (decoder): %ld words in %s() in frame #%d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) / sizeof( float ), location_max_stack, wc_frame ); - fprintf( stdout, "Table ROM size (decoder): %ld words\n", ( Const_Data_Size_rom_dec() + Const_Data_Size_ivas_rom_dec() ) / sizeof( float ) ); - fprintf( stdout, "Table ROM size (binaural renderer): %ld words\n", ( Const_Data_Size_ivas_rom_binauralRen() + Const_Data_Size_ivas_rom_TdBinauralR() + Const_Data_Size_ivas_rom_binaural_cr() ) / sizeof( float ) ); - fprintf( stdout, "Table ROM size (common): %ld words\n", ( Const_Data_Size_rom_com() + Const_Data_Size_ivas_rom_com() ) / sizeof( float ) ); -#ifdef RAM_COUNTING_TOOL - fprintf( stdout, "Static RAM size (decoder): %ld words\n\n", SRAM_size ); -#endif - print_stack_call_tree(); - - fprintf( stdout, "Note: this is an optimistic estimate of the memory consumption assuming\n" ); - fprintf( stdout, " that each variable (short, long or float) in the codec requires\n" ); - fprintf( stdout, " 32 bits of memory and may therefore be represented by 1 word.\n" ); - fprintf( stdout, " The following formula is used: sizeof('memory array')/sizeof(float)\n\n" ); -} -#endif - - /*------------------------------------------------------------------------------------------* * main() * @@ -189,26 +153,25 @@ int main( LsCustomFileReader *hLsCustomReader = NULL; hrtfFileReader *hrtfReader = NULL; HeadRotFileReader *headRotReader = NULL; + HeadRotFileReader *refRotReader = NULL; + Vector3PairFileReader *referenceVectorReader = NULL; ivas_error error = IVAS_ERR_UNKNOWN; int16_t pcmBuf[MAX_OUTPUT_PCM_BUFFER_SIZE]; RenderConfigReader *renderConfigReader = NULL; #ifdef DEBUGGING int32_t noClipping; int32_t cnt_frames_limited; +#ifdef DEBUG_SBA_AUDIO_DUMP + int16_t numOutChannels, numTransportChannels, pca_ingest_channels; #endif - -#ifdef WMOPS - size_t SRAM_size = 0; - reset_stack(); - reset_wmops(); #endif #ifdef DEBUGGING dbgargs( &argc, argv ); #endif - -#ifdef RAM_COUNTING_TOOL - mem_count_init( 0, USE_32BITS ); +#ifdef WMOPS + reset_wmops(); + reset_mem( USE_32BITS ); #endif /*------------------------------------------------------------------------------------------* @@ -265,8 +228,17 @@ int main( if ( arg.hrtfReaderEnabled ) { - if ( ( ( error = hrtfFileReader_open( arg.hrtfFileName, &hrtfReader ) ) != IVAS_ERR_OK ) ) + /* sanity check */ + if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL && arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM ) + { + arg.hrtfReaderEnabled = false; + fprintf( stderr, "\nError: HRTF binary file cannot be used in this output configuration.\n\n" ); + goto cleanup; + } + + if ( ( error = hrtfFileReader_open( arg.hrtfFileName, &hrtfReader ) ) != IVAS_ERR_OK ) { + arg.hrtfReaderEnabled = false; fprintf( stderr, "\nError: Can't open HRTF binary file %s \n\n", arg.hrtfFileName ); goto cleanup; } @@ -278,6 +250,13 @@ int main( if ( arg.enableHeadRotation ) { + /* sanity check */ + if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL && arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM ) + { + fprintf( stderr, "\nError: Head-rotation file file cannot be used in this output configuration.\n\n" ); + goto cleanup; + } + if ( ( error = HeadRotationFileReader_open( arg.headrotTrajFileName, &headRotReader ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError: Can't open head-rotation file %s \n\n", arg.headrotTrajFileName ); @@ -285,6 +264,60 @@ int main( } } + /*------------------------------------------------------------------------------------------* + * Open reference rotation file + *------------------------------------------------------------------------------------------*/ + + if ( arg.enableReferenceRotation ) + { + /* sanity check */ + if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL && arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM ) + { + fprintf( stderr, "\nError: Reference rotation file cannot be used in this output configuration.\n\n" ); + goto cleanup; + } + + /* sanity check */ + if ( arg.orientation_tracking != IVAS_PUBLIC_ORIENT_TRK_REF ) + { + fprintf( stderr, "\nError: Reference rotation file can be used in '-otr ref' mode only.\n\n" ); + goto cleanup; + } + + if ( ( error = HeadRotationFileReader_open( arg.refrotTrajFileName, &refRotReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Can't open reference rotation file %s \n\n", arg.refrotTrajFileName ); + goto cleanup; + } + } + + /*------------------------------------------------------------------------------------------* + * Open reference vector trajectory file + *------------------------------------------------------------------------------------------*/ + + if ( arg.enableReferenceVectorTracking ) + { + /* sanity check */ + if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL && arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM ) + { + fprintf( stderr, "\nError: Reference vector trajectory file cannot be used in this output configuration.\n\n" ); + goto cleanup; + } + + /* sanity check */ + if ( arg.orientation_tracking != IVAS_PUBLIC_ORIENT_TRK_REF_VEC && arg.orientation_tracking != IVAS_PUBLIC_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; + } + + if ( ( error = Vector3PairFileReader_open( arg.referenceVectorTrajFileName, &referenceVectorReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Can't open reference vector trajectory file %s \n\n", arg.referenceVectorTrajFileName ); + goto cleanup; + } + } + /*------------------------------------------------------------------------------------------* * Open custom loudspeaker layout file *------------------------------------------------------------------------------------------*/ @@ -304,6 +337,13 @@ int main( if ( arg.renderConfigEnabled ) { + /* sanity check */ + if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL && arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM ) + { + fprintf( stderr, "\nError: Renderer configuration file cannot be used in this output configuration.\n\n" ); + goto cleanup; + } + if ( ( error = RenderConfigReader_open( arg.renderConfigFilename, &renderConfigReader ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError: Can't open Renderer configuration file %s \n\n", arg.renderConfigFilename ); @@ -315,11 +355,7 @@ int main( * Configure the decoder *------------------------------------------------------------------------------------------*/ -#ifdef DEBUGGING - if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputFormat, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation, arg.forceSubframeBinauralization ) ) != IVAS_ERR_OK ) -#else - if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputFormat, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation ) ) != IVAS_ERR_OK ) -#endif + if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputFormat, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation, arg.renderConfigEnabled ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -332,7 +368,11 @@ int main( if ( arg.voipMode ) { - IVAS_DEC_PrintConfig( hIvasDec, arg.quietModeEnabled, arg.voipMode ); + if ( ( error = printBitstreamInfoVoip( arg, hBsReader, hIvasDec ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error while previewing VoIP bitstream: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } } else { @@ -346,7 +386,7 @@ int main( fprintf( stderr, "\nError: input bitstream file %s couldn't be read\n\n", arg.inputBitstreamFilename ); goto cleanup; } - } while ( bfi || num_bits < MIN_NUM_BITS_ACTIVE_FRAME || num_bits == NUM_BITS_SID_IVAS_4K4 || num_bits == NUM_BITS_SID_IVAS_7K8 || num_bits == NUM_BITS_SID_IVAS_9K3 || num_bits == NUM_BITS_SID_IVAS_10K2 ); + } while ( bfi || num_bits < MIN_NUM_BITS_ACTIVE_FRAME || num_bits == NUM_BITS_SID_IVAS_5K2 ); BS_Reader_Rewind( hBsReader ); @@ -389,6 +429,10 @@ int main( } } +#ifdef DEBUG_SBA_AUDIO_DUMP + ivas_open_sba_decoder_debug_files( arg.output_Fs, 1, 1 ); +#endif + /*-----------------------------------------------------------------* * Print information about FEC *-----------------------------------------------------------------*/ @@ -404,9 +448,9 @@ int main( fprintf( stdout, "FEC: %.2f %%\n", arg.FER ); } } -#else +#else /* DEBUGGING */ IVAS_DEC_PrintConfig( hIvasDec, 1, arg.voipMode ); -#endif +#endif /* DEBUGGING */ /*-------------------------------------------------------------------* * Load renderer configuration from file @@ -417,27 +461,27 @@ int main( IVAS_RENDER_CONFIG_DATA renderConfig; /* sanity check */ - if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM ) + if ( arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL_ROOM && arg.outputFormat != IVAS_DEC_OUTPUT_BINAURAL ) { - fprintf( stderr, "\nExternal Renderer Config is supported only when BINAURAL_ROOM is used as output. Exiting. \n" ); + fprintf( stderr, "\nExternal Renderer Config is supported only for BINAURAL and BINAURAL_ROOM. Exiting. \n\n" ); goto cleanup; } if ( ( error = IVAS_DEC_GetRenderConfig( hIvasDec, &renderConfig ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } if ( RenderConfigReader_read( renderConfigReader, &renderConfig ) != IVAS_ERR_OK ) { - fprintf( stderr, "Failed to read renderer configuration from file %s\n", arg.renderConfigFilename ); + fprintf( stderr, "Failed to read renderer configuration from file %s\n\n", arg.renderConfigFilename ); goto cleanup; } if ( ( error = IVAS_DEC_FeedRenderConfig( hIvasDec, renderConfig ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } } @@ -479,6 +523,30 @@ int main( fprintf( stderr, "\nError in loading HRTF binary file %s \n\n", arg.hrtfFileName ); goto cleanup; } + + + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF; + IVAS_DEC_GetHrtfCRendHandle( hIvasDec, &hSetOfHRTF ); + + if ( ( error = create_SetOfHRTF_from_binary( hSetOfHRTF, hrtfReader, arg.output_Fs ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in loading HRTF binary file %s for CRend \n\n", arg.hrtfCRendFileName ); + goto cleanup; + } + IVAS_DEC_HRTF_FASTCONV_HANDLE hHrtfFastConv; + IVAS_DEC_GetHrtfFastConvHandle( hIvasDec, &hHrtfFastConv ); + + if ( ( error = load_fastconv_HRTF_from_binary( hHrtfFastConv, hrtfReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in loading HRTF binary file %s for FastConv \n\n", arg.hrtfCRendFileName ); + } + IVAS_DEC_HRTF_PARAMBIN_HANDLE hHrtfParambin; + IVAS_DEC_GetHrtfParamBinHandle( hIvasDec, &hHrtfParambin ); + + if ( ( error = load_parambin_HRTF_from_binary( hHrtfParambin, hrtfReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in loading HRTF binary file %s for parametric binauralizer \n\n", arg.hrtfCRendFileName ); + } } /*-----------------------------------------------------------------* @@ -487,11 +555,6 @@ int main( if ( arg.voipMode ) { - if ( arg.decMode != IVAS_DEC_MODE_EVS ) - { - fprintf( stderr, "\nError: VoIP not yet supported for decMode: %d\n\n", arg.decMode ); - goto cleanup; - } if ( ( error = IVAS_DEC_EnableVoIP( hIvasDec, 60, arg.inputFormat ) ) != IVAS_ERR_OK ) { @@ -503,7 +566,7 @@ int main( } else { - error = decodeG192( arg, hBsReader, headRotReader, hIvasDec, pcmBuf ); + error = decodeG192( arg, hBsReader, headRotReader, refRotReader, referenceVectorReader, hIvasDec, pcmBuf ); } if ( error == IVAS_ERR_OK || error == IVAS_ERR_END_OF_FILE ) @@ -542,11 +605,25 @@ int main( cleanup: +#ifdef DEBUG_SBA_AUDIO_DUMP + IVAS_DEC_GetSbaDebugParams( hIvasDec, &numOutChannels, &numTransportChannels, &pca_ingest_channels ); +#endif + + if ( arg.hrtfReaderEnabled ) + { + IVAS_DEC_HRTF_HANDLE hHrtfTD; + IVAS_DEC_GetHrtfHandle( hIvasDec, &hHrtfTD ); + dealloc_HRTF_binary( hHrtfTD ); + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF; + IVAS_DEC_GetHrtfCRendHandle( hIvasDec, &hSetOfHRTF ); + destroy_SetOfHRTF( hSetOfHRTF ); + } IVAS_DEC_Close( &hIvasDec ); CustomLsReader_close( &hLsCustomReader ); hrtfFileReader_close( &hrtfReader ); HeadRotationFileReader_close( &headRotReader ); - + HeadRotationFileReader_close( &refRotReader ); + Vector3PairFileReader_close( &referenceVectorReader ); RenderConfigReader_close( &renderConfigReader ); if ( BS_Reader_Close( &hBsReader ) != IVAS_ERR_OK ) @@ -554,15 +631,9 @@ cleanup: fprintf( stderr, "\nError while closing file: %s\nContinuing...\n\n", arg.inputBitstreamFilename ); } -#ifdef RAM_COUNTING_TOOL -#ifdef WMOPS - SRAM_size = -#endif - mem_count_summary( USE_DEFAULT ); -#endif #ifdef WMOPS print_wmops(); - print_mem_dec( SRAM_size ); + print_mem( NULL ); #endif if ( !arg.quietModeEnabled ) @@ -571,6 +642,9 @@ cleanup: } #ifdef DEBUGGING +#ifdef DEBUG_SBA_AUDIO_DUMP + ivas_close_sba_decoder_debug_files( arg.output_Fs, numOutChannels, numTransportChannels, pca_ingest_channels ); +#endif dbgclose(); #endif @@ -592,6 +666,7 @@ static IVAS_DEC_AUDIO_CONFIG cmdline2config( char argv_to_upper[FILENAME_MAX]; strncpy( argv_to_upper, argv, sizeof( argv_to_upper ) - 1 ); + argv_to_upper[sizeof( argv_to_upper ) - 1] = '\0'; to_upper( argv_to_upper ); if ( strcmp( argv_to_upper, "EXT" ) == 0 ) /* external renderer */ @@ -670,10 +745,11 @@ static bool parseCmdlIVAS_dec( char argv_to_upper[FILENAME_MAX]; #ifdef DEBUGGING float ftmp; - char stmp[FILENAME_MAX]; arg->forcedRendMode = IVAS_DEC_FORCE_REND_UNFORCED; - arg->forceSubframeBinauralization = false; +#ifdef DEBUG_FOA_AGC + arg->agcBitstream = NULL; +#endif #endif arg->output_Fs = 48000; arg->outputFormat = IVAS_DEC_OUTPUT_MONO; @@ -684,7 +760,11 @@ static bool parseCmdlIVAS_dec( arg->enableHeadRotation = false; arg->headrotTrajFileName = NULL; - arg->orientation_tracking = IVAS_PUBLIC_ORIENT_TRK_REF; + arg->orientation_tracking = IVAS_PUBLIC_ORIENT_TRK_NONE; + arg->enableReferenceRotation = false; + arg->headrotTrajFileName = NULL; + arg->enableReferenceVectorTracking = false; + arg->referenceVectorTrajFileName = NULL; #ifdef SUPPORT_JBM_TRACEFILE arg->jbmTraceFilename = NULL; @@ -697,6 +777,9 @@ static bool parseCmdlIVAS_dec( arg->hrtfReaderEnabled = false; arg->hrtfFileName = NULL; + arg->hrtfCRendReaderEnabled = false; + arg->hrtfCRendFileName = NULL; + arg->customLsOutputEnabled = false; arg->customLsSetupFilename = NULL; @@ -705,9 +788,6 @@ static bool parseCmdlIVAS_dec( arg->inputFormat = IVAS_DEC_INPUT_FORMAT_G192; arg->no_diegetic_pan = 0.f; -#ifdef DEBUG_FOA_AGC - arg->agcBitstream = NULL; -#endif /*-----------------------------------------------------------------* * Initialization @@ -729,6 +809,7 @@ static bool parseCmdlIVAS_dec( while ( argv[i][0] == '-' ) { strncpy( argv_to_upper, argv[i], sizeof( argv_to_upper ) - 1 ); + argv_to_upper[sizeof( argv_to_upper ) - 1] = '\0'; to_upper( argv_to_upper ); if ( strcmp( argv_to_upper, "-VOIP" ) == 0 ) @@ -736,13 +817,13 @@ static bool parseCmdlIVAS_dec( arg->voipMode = 1; i++; } - else if ( strcmp( to_upper( argv[i] ), "-VOIP_HF_ONLY=0" ) == 0 ) + else if ( strcmp( argv_to_upper, "-VOIP_HF_ONLY=0" ) == 0 ) { arg->voipMode = 1; arg->inputFormat = IVAS_DEC_INPUT_FORMAT_RTPDUMP; i++; } - else if ( strcmp( to_upper( argv[i] ), "-VOIP_HF_ONLY=1" ) == 0 ) + else if ( strcmp( argv_to_upper, "-VOIP_HF_ONLY=1" ) == 0 ) { arg->voipMode = 1; arg->inputFormat = IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF; @@ -776,21 +857,6 @@ static bool parseCmdlIVAS_dec( arg->jbmOffsetFilename = argv[i]; i++; } -#ifdef DEBUGGING - else if ( strcmp( argv_to_upper, "-FEC" ) == 0 ) - { - ftmp = 0.0f; - if ( sscanf( argv[i + 1], "%f", &ftmp ) != 1 ) - { - arg->FEPatterFileName = argv[i + 1]; - } - else - { - arg->FER = ftmp; - } - i += 2; - } -#endif else if ( strcmp( argv_to_upper, "-Q" ) == 0 ) { arg->quietModeEnabled = true; @@ -812,21 +878,33 @@ static bool parseCmdlIVAS_dec( } } #ifdef DEBUGGING + else if ( strcmp( argv_to_upper, "-FEC" ) == 0 ) + { + ftmp = 0.0f; + if ( sscanf( argv[i + 1], "%f", &ftmp ) != 1 ) + { + arg->FEPatterFileName = argv[i + 1]; + } + else + { + arg->FER = ftmp; + } + i += 2; + } else if ( strcmp( argv_to_upper, "-FORCE" ) == 0 ) { i++; if ( i < argc - 3 ) { - strncpy( stmp, argv[i], sizeof( stmp ) ); - arg->forcedRendMode = parseForcedRendModeDec( stmp ); + strncpy( argv_to_upper, argv[i], sizeof( argv_to_upper ) - 1 ); + argv_to_upper[sizeof( argv_to_upper ) - 1] = '\0'; + arg->forcedRendMode = parseForcedRendModeDec( argv_to_upper ); i++; } } #ifdef DEBUG_MODE_INFO #ifdef DEBUG_MODE_INFO_TWEAK - /*-----------------------------------------------------------------* - * Define additional subfolder for debug info output in ./res - *-----------------------------------------------------------------*/ + /* Define additional subfolder for debug info output in ./res */ else if ( strcmp( argv_to_upper, "-INFO" ) == 0 ) { extern char infoFolder[FILENAME_MAX]; @@ -859,30 +937,69 @@ static bool parseCmdlIVAS_dec( } else if ( strcmp( argv_to_upper, "-OTR" ) == 0 ) { - if ( strlen( argv[i + 1] ) > 3 ) + + strncpy( argv_to_upper, argv[i + 1], sizeof( argv_to_upper ) - 1 ); + argv_to_upper[sizeof( argv_to_upper ) - 1] = '\0'; + to_upper( argv_to_upper ); + + if ( strcmp( argv_to_upper, "NONE" ) == 0 ) { - fprintf( stderr, "Error: Invalid orientation tracking type %s \n\n", argv[i + 1] ); - usage_dec(); - return false; + arg->orientation_tracking = IVAS_PUBLIC_ORIENT_TRK_NONE; } - char tmp[4]; - strcpy( tmp, argv[i + 1] ); - if ( strcmp( to_upper( tmp ), "REF" ) == 0 ) + else if ( strcmp( argv_to_upper, "REF" ) == 0 ) { arg->orientation_tracking = IVAS_PUBLIC_ORIENT_TRK_REF; } - else if ( strcmp( to_upper( tmp ), "AVG" ) == 0 ) + else if ( strcmp( argv_to_upper, "AVG" ) == 0 ) { arg->orientation_tracking = IVAS_PUBLIC_ORIENT_TRK_AVG; } + else if ( strcmp( argv_to_upper, "REF_VEC" ) == 0 ) + { + arg->orientation_tracking = IVAS_PUBLIC_ORIENT_TRK_REF_VEC; + } + else if ( strcmp( argv_to_upper, "REF_VEC_LEV" ) == 0 ) + { + arg->orientation_tracking = IVAS_PUBLIC_ORIENT_TRK_REF_VEC_LEV; + } else { - fprintf( stderr, "Error: Invalid orientation tracking type %s \n\n", tmp ); + fprintf( stderr, "Error: Invalid orientation tracking type %s \n\n", argv[i + 1] ); usage_dec(); return false; } i += 2; } + else if ( strcmp( argv_to_upper, "-RF" ) == 0 ) + { + arg->enableReferenceRotation = true; + i++; + + if ( argc - i <= 4 || argv[i][0] == '-' ) + { + fprintf( stderr, "Error: Reference rotation file name not specified!\n\n" ); + usage_dec(); + return false; + } + + arg->refrotTrajFileName = argv[i]; + i++; + } + else if ( strcmp( argv_to_upper, "-RVF" ) == 0 ) + { + arg->enableReferenceVectorTracking = true; + i++; + + if ( argc - i <= 4 || argv[i][0] == '-' ) + { + fprintf( stderr, "Error: reference vector trajectory file name not specified!\n\n" ); + usage_dec(); + return false; + } + + arg->referenceVectorTrajFileName = argv[i]; + i++; + } else if ( strcmp( argv_to_upper, "-RENDER_CONFIG" ) == 0 ) { arg->renderConfigEnabled = true; @@ -907,39 +1024,33 @@ static bool parseCmdlIVAS_dec( return false; } - char *param = to_upper( argv[i] ); - if ( ( strcmp( param, "CENTER" ) == 0 ) || ( strchr( param, 'C' ) != NULL ) ) + strncpy( argv_to_upper, argv[i], sizeof( argv_to_upper ) - 1 ); + argv_to_upper[sizeof( argv_to_upper ) - 1] = '\0'; + if ( ( strcmp( argv_to_upper, "CENTER" ) == 0 ) || ( strchr( argv_to_upper, 'C' ) != NULL ) ) { arg->no_diegetic_pan = 0.f; } - else if ( ( strcmp( param, "LEFT" ) == 0 ) || ( strchr( param, 'L' ) != NULL ) ) + else if ( ( strcmp( argv_to_upper, "LEFT" ) == 0 ) || ( strchr( argv_to_upper, 'L' ) != NULL ) ) { arg->no_diegetic_pan = -1.f; } - else if ( ( strcmp( param, "RIGHT" ) == 0 ) || ( strchr( param, 'R' ) != NULL ) ) + else if ( ( strcmp( argv_to_upper, "RIGHT" ) == 0 ) || ( strchr( argv_to_upper, 'R' ) != NULL ) ) { arg->no_diegetic_pan = 1.f; } else { - arg->no_diegetic_pan = (float) atof( param ); + arg->no_diegetic_pan = (float) atof( argv_to_upper ); if ( arg->no_diegetic_pan > 1.0f || arg->no_diegetic_pan < -1.0f ) { - fprintf( stderr, "Error: Incorrect value for panning option argument specified!\n\n" ); + fprintf( stderr, "Error: Incorrect value for panning option argument specified: %s\n\n", argv[i] ); usage_dec(); return false; } } i++; } -#ifdef DEBUGGING - else if ( strcmp( argv_to_upper, "-FORCE_SUBFRAME_BIN" ) == 0 ) /* Force binauralization to subframe (5 ms) resolution */ - { - arg->forceSubframeBinauralization = true; - i++; - } -#endif /*-----------------------------------------------------------------* * Option not recognized @@ -1071,11 +1182,20 @@ static void usage_dec( void ) fprintf( stdout, " Format files, the magic word in the mime file is used to determine\n" ); fprintf( stdout, " which of the two supported formats is in use.\n" ); fprintf( stdout, " default bitstream file format is G.192\n" ); + fprintf( stdout, "-hrtf File : HRTF filter File used in BINAURAL output configuration\n" ); fprintf( stdout, "-T File : Head rotation specified by external trajectory File\n" ); - fprintf( stdout, "-hrtf File : HRTF filter File used in ISm format and BINAURAL output configuration\n" ); + fprintf( stdout, "-otr tracking_type : Head orientation tracking type: 'none', 'ref', 'avg', 'ref_vec' \n" ); + fprintf( stdout, " or 'ref_vec_lev' (only for binaural rendering)\n" ); + fprintf( stdout, "-rf File : Reference rotation specified by external trajectory file\n" ); + fprintf( stdout, " works only in combination with '-otr ref' mode \n" ); + fprintf( stdout, "-rvf File : Reference vector specified by external trajectory file\n" ); + fprintf( stdout, " works only in combination with '-otr ref_vec' and 'ref_vec_lev' modes\n" ); + fprintf( stdout, "-render_config File : Renderer configuration File\n" ); + fprintf( stdout, "-no_diegetic_pan : panning mono non-diegetic sound to stereo -1<= pan <=1,\n" ); + fprintf( stdout, " left or l or 1->left, right or r or -1->right, center or c or 0->middle\n" ); + fprintf( stdout, "-q : Quiet mode, no frame counter\n" ); + fprintf( stdout, " default is deactivated\n" ); #ifdef DEBUGGING - fprintf( stdout, "-force_subframe_bin : Forces parametric binauralizer code to use 5 ms time resolution even when\n" ); - fprintf( stdout, " output time resolution is larger.\n" ); fprintf( stdout, "-FEC X : Insert frame erasures, X = 0-10 is the percentage\n" ); fprintf( stdout, " of erased frames, or X may be the name of binary file or \n" ); fprintf( stdout, " file with G192 headers indicating GOOD FRAME or BAD FRAME\n" ); @@ -1083,12 +1203,11 @@ static void usage_dec( void ) fprintf( stdout, " default is OFF, if this option is not used\n" ); fprintf( stdout, "-force R : Force specific binaural rendering mode, R = (TDREND, CLDFBREND),\n" ); #endif - fprintf( stdout, "-otr tracking_type : head orientation tracking type: 'ref' or 'avg' (only for binaural rendering)\n" ); - fprintf( stdout, "-render_config file : Renderer configuration file\n" ); - fprintf( stdout, "-no_diegetic_pan : panning mono no dietic sound to stereo -1<= pan <=1,\n" ); - fprintf( stdout, " left or l or 1->left, right or r or -1->right, center or c or 0->middle\n" ); - fprintf( stdout, "-q : Quiet mode, no frame counter\n" ); - fprintf( stdout, " default is deactivated\n" ); +#ifdef DEBUG_MODE_INFO +#ifdef DEBUG_MODE_INFO_TWEAK + fprintf( stdout, "-info : specify subfolder name for debug output\n" ); +#endif +#endif fprintf( stdout, "\n" ); return; @@ -1109,57 +1228,227 @@ static int16_t app_own_random( int16_t *seed ) } #endif -/*---------------------------------------------------------------------* - * decodeG192() - * - * Read G.192 bitstream and decode in regular decoder - *---------------------------------------------------------------------*/ - -static ivas_error decodeG192( - DecArguments arg, - BS_READER_HANDLE hBsReader, - HeadRotFileReader *headRotReader, - IVAS_DEC_HANDLE hIvasDec, - int16_t *pcmBuf ) - +static ivas_error initOnFirstGoodFrame( + IVAS_DEC_HANDLE hIvasDec, /* i/o: */ + const DecArguments arg, /* i : */ + const int16_t numInitialBadFrames, /* i : */ + const uint16_t numOutSamples, /* i : */ + int16_t *pFullDelayNumSamples, /* o : */ + int16_t *pRemainingDelayNumSamples, /* o : */ + int32_t *delayTimeScale, /* o : */ + IVAS_DEC_BS_FORMAT *pBsFormat, /* i/o: */ + AudioFileWriter **ppAfWriter, /* o : */ + MasaFileWriter **ppMasaWriter, /* o : */ + IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS], /* o : */ + int16_t *pNumOutChannels, /* o : */ + uint16_t *pNumObj /* o : */ +) { - bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */ - uint16_t bit_stream[IVAS_MAX_BITS_PER_FRAME + 4 * 8]; - int16_t i, j, num_bits; - int16_t bfi = 0; -#ifdef DEBUGGING - int16_t fec_seed = 12558; /* FEC_SEED */ -#endif - AudioFileWriter *afWriter = NULL; - MasaFileWriter *masaWriter = NULL; - bool decodedGoodFrame = false; - int16_t numInitialBadFrames = 0; /* Number of bad frames received until first good frame is decoded */ - int16_t nOutChannels = 0; - int16_t delayNumSamples = -1; - int16_t delayNumSamples_orig = 0; - int16_t zeroPad = 0; - int16_t nOutSamples = 0; - int32_t delayTimeScale = 0; ivas_error error = IVAS_ERR_UNKNOWN; - uint16_t numObj = 0; - IVAS_DEC_BS_FORMAT bsFormat = IVAS_DEC_BS_UNKOWN; - IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS]; - for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) + /* Now delay, number of output channels and frame size are known */ + if ( ( error = IVAS_DEC_GetDelay( hIvasDec, pFullDelayNumSamples, delayTimeScale ) ) != IVAS_ERR_OK ) { - ismWriters[i] = NULL; + fprintf( stderr, "\nUnable to get delay of decoder: %s\n", ivas_error_to_string( error ) ); + return error; } - if ( !arg.quietModeEnabled ) + if ( !arg.delayCompensationEnabled ) { - fprintf( stdout, "\n------ Running the decoder ------\n\n" ); - fprintf( stdout, "Frames processed: " ); + pFullDelayNumSamples[0] = 0; } - else + *pRemainingDelayNumSamples = pFullDelayNumSamples[0]; + + if ( ( error = IVAS_DEC_GetNumOutputChannels( hIvasDec, pNumOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetNumOutputChannels, code: %d\n", error ); + 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; + } + + /* Open audio writer and write all previously skipped bad frames now that frame size is known */ + if ( ( error = AudioFileWriter_open( ppAfWriter, arg.outputWavFilename, arg.output_Fs, *pNumOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); + return error; + } + + int16_t *zeroBuf = malloc( pcmFrameSize * sizeof( int16_t ) ); + memset( zeroBuf, 0, pcmFrameSize * sizeof( int16_t ) ); + + for ( int16_t i = 0; i < numInitialBadFrames; ++i ) + { + if ( *pRemainingDelayNumSamples < numOutSamples ) + { + if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + return error; + } + *pRemainingDelayNumSamples = 0; + } + else + { + *pRemainingDelayNumSamples -= numOutSamples; + } + } + + free( zeroBuf ); + + /* Open other output files if EXT output config - now details about ISM or MASA are known */ + if ( arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) + { + if ( ( error = IVAS_DEC_GetFormat( hIvasDec, pBsFormat ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetFormat, code: %d\n", error ); + return error; + } + + /* If outputting ISM, get number of objects, open output files and write zero metadata for initial bad frames */ + if ( *pBsFormat == IVAS_DEC_BS_OBJ ) + { + if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, pNumObj ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetNumObjects: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + + for ( int16_t i = 0; i < *pNumObj; ++i ) + { + if ( ( error = IsmFileWriter_open( arg.outputWavFilename, i, &ismWriters[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Error opening ISM decoded metadata file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); + return error; + } + } + + for ( int16_t j = 0; j < numInitialBadFrames; ++j ) + { + /* write zero metadata */ + for ( int16_t i = 0; i < *pNumObj; ++i ) + { + IVAS_ISM_METADATA IsmMetadata; + + if ( ( error = IVAS_DEC_GetObjectMetadata( hIvasDec, &IsmMetadata, 1, i ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetObjectMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + + if ( ( error = IsmFileWriter_writeFrame( IsmMetadata, ismWriters[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing ISM metadata to file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); + return error; + } + } + } + } + /* If outputting MASA, open output file and write metadata for initial bad frames */ + else if ( *pBsFormat == IVAS_DEC_BS_MASA ) + { +#ifdef FIX_350_MASA_DELAY_COMP + if ( ( error = MasaFileWriter_open( arg.outputWavFilename, arg.delayCompensationEnabled, ppMasaWriter ) ) != IVAS_ERR_OK ) +#else + if ( ( error = MasaFileWriter_open( arg.outputWavFilename, ppMasaWriter ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nError: Error opening MASA decoded metadata file %s\n", MasaFileWriter_getFilePath( *ppMasaWriter ) ); + return error; + } + + /* Duplicate good first frame metadata to fill the beginning of stream. */ +#ifdef FIX_350_MASA_DELAY_COMP + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta = NULL; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta ) ) != IVAS_ERR_OK ) +#else + IVAS_MASA_QMETADATA_HANDLE qMetadata = NULL; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &qMetadata ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + return error; + } + + for ( int16_t j = 0; j < numInitialBadFrames; ++j ) + { +#ifdef FIX_350_MASA_DELAY_COMP + if ( ( error = MasaFileWriter_writeFrame( *ppMasaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK ) +#else + if ( ( error = MasaFileWriter_writeFrame( *ppMasaWriter, qMetadata ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( *ppMasaWriter ) ); + return error; + } + } + } + } + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * decodeG192() + * + * Read G.192 bitstream and decode in regular decoder + *---------------------------------------------------------------------*/ + +static ivas_error decodeG192( + DecArguments arg, + BS_READER_HANDLE hBsReader, + HeadRotFileReader *headRotReader, + HeadRotFileReader *refRotReader, + Vector3PairFileReader *referenceVectorReader, + IVAS_DEC_HANDLE hIvasDec, + int16_t *pcmBuf ) + +{ + bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */ + uint16_t bit_stream[IVAS_MAX_BITS_PER_FRAME + 4 * 8]; + int16_t i, num_bits; + int16_t bfi = 0; +#ifdef DEBUGGING + int16_t fec_seed = 12558; /* FEC_SEED */ +#endif + AudioFileWriter *afWriter = NULL; + MasaFileWriter *masaWriter = NULL; + bool decodedGoodFrame = false; + int16_t numInitialBadFrames = 0; /* Number of bad frames received until first good frame is decoded */ + int16_t nOutChannels = 0; + int16_t delayNumSamples = -1; + int16_t delayNumSamples_orig[3]; /* stores: overall delay, dec+rend delay, and binauralization delay */ + int16_t nOutSamples = 0; + int32_t delayTimeScale = 0; + ivas_error error = IVAS_ERR_UNKNOWN; + uint16_t numObj = 0; + IVAS_DEC_BS_FORMAT bsFormat = IVAS_DEC_BS_UNKOWN; + IVAS_POSITION Pos[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; + + IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS]; + for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) + { + ismWriters[i] = NULL; + } + + if ( !arg.quietModeEnabled ) + { + fprintf( stdout, "\n------ Running the decoder ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else { fprintf( stdout, "\n-- Start the decoder (quiet mode) --\n\n" ); } + delayNumSamples_orig[0] = -1; + #ifdef WMOPS reset_stack(); reset_wmops(); @@ -1208,24 +1497,58 @@ static ivas_error decodeG192( goto cleanup; } + /* reference vector */ + if ( arg.enableReferenceVectorTracking ) + { + IVAS_VECTOR3 listenerPosition, referencePosition; + if ( ( error = Vector3PairFileReader_read( referenceVectorReader, &listenerPosition, &referencePosition ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading listener and reference positions from %s\n", IVAS_DEC_GetErrorMessage( error ), Vector3PairFileReader_getFilePath( referenceVectorReader ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_FeedRefVectorData( hIvasDec, listenerPosition, referencePosition ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRefVectorData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } + /* Reference rotation */ + if ( arg.enableReferenceRotation ) + { + IVAS_QUATERNION quaternion; + if ( ( error = HeadRotationFileReading( refRotReader, &quaternion, NULL ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading reference rotation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( refRotReader ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_FeedRefRotData( hIvasDec, quaternion ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRefRotData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } /* Head-tracking input simulation */ if ( arg.enableHeadRotation ) { IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; - if ( ( error = HeadRotationFileReading( headRotReader, Quaternions, frame ) ) != IVAS_ERR_OK ) + for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) { - fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) ); - goto cleanup; + if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), HeadRotationFileReader_getFilePath( headRotReader ) ); + goto cleanup; + } } - if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions, Pos ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_DEC_FeedHeadTrackData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } } - /* Run decoder for one frame (get rendered output) */ if ( ( error = IVAS_DEC_GetSamples( hIvasDec, pcmBuf, &nOutSamples ) ) != IVAS_ERR_OK ) { @@ -1245,125 +1568,24 @@ static ivas_error decodeG192( /* Once good frame decoded, catch up */ if ( decodedGoodFrame ) { - /* Now number of output channels and frame size are known */ - if ( ( error = IVAS_DEC_GetNumOutputChannels( hIvasDec, &nOutChannels ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_DEC_GetNumOutputChannels, code: %d\n", error ); - goto cleanup; - } - - 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 ); - goto cleanup; - } - - /* Open audio writer and write all previously skipped bad frames now that frame size is known */ - if ( ( error = AudioFileWriter_open( &afWriter, arg.outputWavFilename, arg.output_Fs, nOutChannels ) ) != IVAS_ERR_OK ) + error = initOnFirstGoodFrame( + hIvasDec, + arg, + numInitialBadFrames, + nOutSamples, + delayNumSamples_orig, + &delayNumSamples, + &delayTimeScale, + &bsFormat, + &afWriter, + &masaWriter, + ismWriters, + &nOutChannels, + &numObj ); + if ( error != IVAS_ERR_OK ) { - fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); goto cleanup; } - - int16_t *zeroBuf = malloc( pcmFrameSize * sizeof( int16_t ) ); - memset( zeroBuf, 0, pcmFrameSize * sizeof( int16_t ) ); - - for ( i = 0; i < numInitialBadFrames; ++i ) - { - if ( delayNumSamples < nOutSamples ) - { - if ( ( error = AudioFileWriter_write( afWriter, zeroBuf, nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nOutput audio file writer error\n" ); - goto cleanup; - } - delayNumSamples = 0; - } - else - { - delayNumSamples -= nOutSamples; - } - } - - free( zeroBuf ); - - /* Open other output files if EXT output config - now details about ISM or MASA are known */ - if ( arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) - { - if ( ( error = IVAS_DEC_GetFormat( hIvasDec, &bsFormat ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_DEC_GetFormat, code: %d\n", error ); - goto cleanup; - } - - /* If outputting ISM, get number of objects, open output files and write zero metadata for initial bad frames */ - if ( bsFormat == IVAS_DEC_BS_OBJ ) - { - if ( ( error = IVAS_DEC_GetNumObjects( hIvasDec, &numObj ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_DEC_GetNumObjects: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - goto cleanup; - } - - for ( i = 0; i < numObj; ++i ) - { - if ( ( error = IsmFileWriter_open( arg.outputWavFilename, i, &ismWriters[i] ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError: Error opening ISM decoded metadata file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); - goto cleanup; - } - } - - for ( j = 0; j < numInitialBadFrames; ++j ) - { - /* write zero metadata */ - for ( i = 0; i < numObj; ++i ) - { - IVAS_ISM_METADATA IsmMetadata; - - if ( ( error = IVAS_DEC_GetObjectMetadata( hIvasDec, &IsmMetadata, 1, i ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_DEC_GetObjectMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - goto cleanup; - } - - if ( ( IsmFileWriter_writeFrame( IsmMetadata, ismWriters[i] ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError writing ISM metadata to file %s\n", IsmFileWriter_getFilePath( ismWriters[i] ) ); - goto cleanup; - } - } - } - } - /* If outputting MASA, open output file and write metadata for initial bad frames */ - else if ( bsFormat == IVAS_DEC_BS_MASA ) - { - if ( ( error = MasaFileWriter_open( arg.outputWavFilename, &masaWriter ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError: Error opening MASA decoded metadata file %s\n", MasaFileWriter_getFilePath( masaWriter ) ); - goto cleanup; - } - - /* Duplicate good first frame metadata to fill the beginning of stream. */ - IVAS_MASA_QMETADATA_HANDLE qMetadata = NULL; - if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &qMetadata ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - goto cleanup; - } - - for ( j = 0; j < numInitialBadFrames; ++j ) - { - if ( ( MasaFileWriter_writeFrame( masaWriter, qMetadata ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); - goto cleanup; - } - } - } - } } else { @@ -1371,23 +1593,6 @@ static ivas_error decodeG192( } } - if ( delayNumSamples == -1 ) - { - if ( arg.delayCompensationEnabled ) - { - if ( ( error = IVAS_DEC_GetDelay( hIvasDec, &delayNumSamples, &delayTimeScale ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nUnable to get delay of decoder: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - goto cleanup; - } - delayNumSamples_orig = delayNumSamples; - } - else - { - delayNumSamples = 0; - } - zeroPad = delayNumSamples; - } /* Write current frame */ if ( decodedGoodFrame ) @@ -1407,7 +1612,7 @@ static ivas_error decodeG192( } } - /* Write ISm metadata to external file(s) */ + /* Write ISM metadata to external file(s) */ if ( decodedGoodFrame && arg.outputFormat == IVAS_DEC_OUTPUT_EXT ) { if ( bsFormat == IVAS_DEC_BS_OBJ ) @@ -1437,14 +1642,23 @@ static ivas_error decodeG192( } else if ( bsFormat == IVAS_DEC_BS_MASA ) { +#ifdef FIX_350_MASA_DELAY_COMP + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta ) ) != IVAS_ERR_OK ) +#else IVAS_MASA_QMETADATA_HANDLE qMetadata; if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &qMetadata ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } +#ifdef FIX_350_MASA_DELAY_COMP + if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK ) +#else if ( ( error = MasaFileWriter_writeFrame( masaWriter, qMetadata ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) ); goto cleanup; @@ -1464,17 +1678,35 @@ static ivas_error decodeG192( #endif } #ifdef WMOPS + update_mem(); update_wmops(); #endif } + /*------------------------------------------------------------------------------------------* + * Add zeros at the end to have equal length of synthesized signals + *------------------------------------------------------------------------------------------*/ + + memset( pcmBuf, 0, delayNumSamples_orig[0] * nOutChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig[0] * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + /*------------------------------------------------------------------------------------------* * Printouts after decoding has finished *------------------------------------------------------------------------------------------*/ if ( !arg.quietModeEnabled ) { - fprintf( stdout, "\nDecoder delay: %-5u [samples] - Timescale: %5u\n", delayNumSamples_orig, delayTimeScale ); + printf( "\n\nDecoder+renderer delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * delayNumSamples_orig[1] / (float) delayTimeScale, delayNumSamples_orig[1], delayTimeScale ); + + if ( delayNumSamples_orig[2] > 0 ) + { + printf( "HRIR/BRIR delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * delayNumSamples_orig[2] / (float) delayTimeScale, delayNumSamples_orig[2], delayTimeScale ); + printf( "Total delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * ( delayNumSamples_orig[1] + delayNumSamples_orig[2] ) / (float) delayTimeScale, delayNumSamples_orig[1] + delayNumSamples_orig[2], delayTimeScale ); + } } /* Print output metadata file name(s) */ @@ -1494,14 +1726,6 @@ static ivas_error decodeG192( } } - /* add zeros at the end to have equal length of synthesized signals */ - memset( pcmBuf, 0, zeroPad * nOutChannels * sizeof( int16_t ) ); - if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, zeroPad * nOutChannels ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nOutput audio file writer error\n" ); - goto cleanup; - } - /*------------------------------------------------------------------------------------------* * Close files and deallocate resources *------------------------------------------------------------------------------------------*/ @@ -1525,11 +1749,120 @@ cleanup: return error; } +#ifdef DEBUGGING +/*---------------------------------------------------------------------* + * printBitstreamInfoVoip() + * + * Print bitstream info of a VoIP G.192 or RTPDUMP bitstream. + *---------------------------------------------------------------------*/ +static ivas_error printBitstreamInfoVoip( + DecArguments arg, + BS_READER_HANDLE hBsReader, + IVAS_DEC_HANDLE hIvasDec ) +{ + bool previewFailed = true; + ivas_error error = IVAS_ERR_OK; + FILE *f_rtpstream = NULL; + EVS_RTPDUMP_DEPACKER rtpdumpDepacker; + EVS_RTPDUMP_DEPACKER_ERROR rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_NO_ERROR; + uint8_t au[( IVAS_MAX_BITS_PER_FRAME + 7 ) >> 3]; + int16_t auSizeBits; + uint8_t *auPtr = NULL; + bool isAMRWB_IOmode; + uint16_t frameTypeIndex; + bool qBit; + uint32_t nextPacketRcvTime_ms = 0; + uint16_t rtpSequenceNumber; + uint32_t rtpTimeStamp; + + rtpdumpDepacker.rtpdump = NULL; + switch ( arg.inputFormat ) + { + case IVAS_DEC_INPUT_FORMAT_RTPDUMP: + case IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF: + f_rtpstream = fopen( arg.inputBitstreamFilename, "r" ); + + if ( f_rtpstream == NULL ) + { + fprintf( stderr, "could not open: %s\n", arg.inputBitstreamFilename ); + goto cleanup; + } + + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_open( &rtpdumpDepacker, f_rtpstream, arg.inputFormat == IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF ); + if ( rtpdumpDepackerError != EVS_RTPDUMP_DEPACKER_NO_ERROR ) + { + fprintf( stderr, "error in EVS_RTPDUMP_DEPACKER_open(): %d\n", rtpdumpDepackerError ); + goto cleanup; + } + break; + case IVAS_DEC_INPUT_FORMAT_G192: + auPtr = au; + break; + default: + fprintf( stderr, "Unsupported format of input bitstream" ); + goto cleanup; + } + + /* Keep reading until full frame is found */ + do + { + if ( arg.inputFormat == IVAS_DEC_INPUT_FORMAT_G192 ) + { + error = BS_Reader_ReadVoipFrame_compact( hBsReader, au, &auSizeBits, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms ); + qBit = 1; /* good q_bit for INPUT_FORMAT_G192 */ + } + else + { + auPtr = au; /* might have been set to RTP packet in prev call */ + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame( &rtpdumpDepacker, &rtpSequenceNumber, &rtpTimeStamp, + &nextPacketRcvTime_ms, + &isAMRWB_IOmode, &frameTypeIndex, &qBit, + &auPtr, (uint16_t *) &auSizeBits ); + /* EVS RTP payload format has timescale 16000, JBM uses 1000 internally */ + rtpTimeStamp = rtpTimeStamp / 16; + } + if ( error != IVAS_ERR_OK || rtpdumpDepackerError != EVS_RTPDUMP_DEPACKER_NO_ERROR ) + { + fprintf( stderr, "failed to read first RTP packet\n" ); + goto cleanup; + } + } while ( !qBit || auSizeBits < MIN_NUM_BITS_ACTIVE_FRAME || auSizeBits == NUM_BITS_SID_IVAS_5K2 ); + + BS_Reader_Rewind( hBsReader ); + + IVAS_DEC_PrintConfigWithVoipBitstream( hIvasDec, arg.quietModeEnabled, au, auSizeBits ); + + /*------------------------------------------------------------------------------------------* + * Close fhandles and deallocate resources + *------------------------------------------------------------------------------------------*/ + + previewFailed = false; /* This will stay set to true if cleanup is reached via a goto due to an error */ + +cleanup: + + EVS_RTPDUMP_DEPACKER_close( &rtpdumpDepacker ); + + if ( previewFailed && error == IVAS_ERR_OK ) + { + return IVAS_ERR_UNKNOWN; + } + + return IVAS_ERR_OK; +} +#endif + +#ifdef SUPPORT_JBM_TRACEFILE +static ivas_error writeJbmTraceFileFrameWrapper( const void *data, void *writer ) +{ + return JbmTraceFileWriter_writeFrame( data, writer ); +} +#endif + /*---------------------------------------------------------------------* * decodeVoIP() * - * Read G.192 bitstream and decode in VOIP + * Read G.192 or RTPDUMP bitstream and decode in VOIP *---------------------------------------------------------------------*/ static ivas_error decodeVoIP( @@ -1549,23 +1882,22 @@ static ivas_error decodeVoIP( uint16_t rtpSequenceNumber; uint32_t rtpTimeStamp; - /* For now always assume output with one channel. When adding VoIP to IVAS, - * initialization of the memory for jitter buffer etc. needs to happen after - * first good frame has been decoded because for some configs (such as EXT - * renderer) only then the number of output channels is known.*/ - const int16_t nOutChannels = 1; + bool decodedGoodFrame = false; + int16_t numInitialBadFrames = 0; /* Number of bad frames received until first good frame is decoded */ + int16_t nOutChannels = 0; + 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; #endif JbmOffsetFileWriter *jbmOffsetWriter = NULL; - const uint32_t pcmBufSizeWithSampleBasedTimeScaling = 3 * MAX_FRAME_SIZE; - int16_t pcmBuf[3 * MAX_FRAME_SIZE]; - int16_t delayNumSamples_orig = -1; + int16_t delayNumSamples_orig[3]; /* stores: overall delay, dec+rend delay, and binauralization delay */ int16_t delayNumSamples = -1; int32_t delayTimeScale = -1; - int16_t zeroPad = 0; FILE *f_rtpstream = NULL; EVS_RTPDUMP_DEPACKER rtpdumpDepacker; @@ -1575,7 +1907,15 @@ static ivas_error decodeVoIP( uint16_t frameTypeIndex; bool qBit; - memset( pcmBuf, 0, pcmBufSizeWithSampleBasedTimeScaling ); + IVAS_DEC_BS_FORMAT bsFormat = IVAS_DEC_BS_UNKOWN; + IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS]; + + for ( int16_t i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) + { + ismWriters[i] = NULL; + } + + delayNumSamples_orig[0] = -1; rtpdumpDepacker.rtpdump = NULL; switch ( arg.inputFormat ) @@ -1605,11 +1945,6 @@ static ivas_error decodeVoIP( goto cleanup; } - if ( ( error = AudioFileWriter_open( &afWriter, arg.outputWavFilename, arg.output_Fs, nOutChannels ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); - goto cleanup; - } #ifdef SUPPORT_JBM_TRACEFILE if ( arg.jbmTraceFilename != NULL ) @@ -1637,10 +1972,6 @@ static ivas_error decodeVoIP( if ( arg.inputFormat == IVAS_DEC_INPUT_FORMAT_G192 ) { error = BS_Reader_ReadVoipFrame_compact( hBsReader, au, &auSize, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms ); - if ( !evsPayload_getFrameTypeFromSize( auSize, &isAMRWB_IOmode, &frameTypeIndex ) ) - { - error = IVAS_ERR_BITSTREAM_READER_INVALID_DATA; - } qBit = 1; /* good q_bit for INPUT_FORMAT_G192 */ } else @@ -1686,7 +2017,7 @@ static ivas_error decodeVoIP( while ( nextPacketRcvTime_ms <= systemTime_ms ) { /* feed the previous read packet into the receiver now */ - error = IVAS_DEC_VoIP_FeedFrame( hIvasDec, auPtr, auSize, rtpSequenceNumber, rtpTimeStamp, nextPacketRcvTime_ms, isAMRWB_IOmode, frameTypeIndex, qBit ); + error = IVAS_DEC_VoIP_FeedFrame( hIvasDec, auPtr, auSize, rtpSequenceNumber, rtpTimeStamp, nextPacketRcvTime_ms, qBit ); if ( error != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_FeedFrame: %s\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -1699,10 +2030,6 @@ static ivas_error decodeVoIP( { error = BS_Reader_ReadVoipFrame_compact( hBsReader, au, &auSize, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms ); - if ( !evsPayload_getFrameTypeFromSize( auSize, &isAMRWB_IOmode, &frameTypeIndex ) ) - { - error = IVAS_ERR_BITSTREAM_READER_INVALID_DATA; - } qBit = 1; /* good q_bit for VOIP_G192_RTP */ } else @@ -1734,32 +2061,21 @@ static ivas_error decodeVoIP( break; } + nOutSamples = (int16_t) ( arg.output_Fs / 50 ); + /* decode and get samples */ - if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, &nOutSamples, pcmBuf, pcmBufSizeWithSampleBasedTimeScaling, systemTime_ms ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms +#ifdef SUPPORT_JBM_TRACEFILE + , + writeJbmTraceFileFrameWrapper, + jbmTraceWriter +#endif + ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } -#ifdef SUPPORT_JBM_TRACEFILE - /* write JBM trace file entry - only done for EVS testing */ - if ( jbmTraceWriter != NULL ) - { - IVAS_JBM_TRACE_DATA JbmTraceData; - - if ( ( error = IVAS_DEC_GetJbmData( hIvasDec, &JbmTraceData ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_DEC_GetJbmData: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - goto cleanup; - } - - if ( ( JbmTraceFileWriter_writeFrame( &JbmTraceData, jbmTraceWriter ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError writing JBM Trace data to file %s\n", arg.jbmTraceFilename ); - goto cleanup; - } - } -#endif /* write JBM Offset file entry */ if ( jbmOffsetWriter != NULL ) @@ -1779,36 +2095,60 @@ static ivas_error decodeVoIP( } } - if ( delayNumSamples == -1 ) + /* Continue checking for first good frame until it is found */ + if ( !decodedGoodFrame ) { - if ( arg.delayCompensationEnabled ) + if ( ( error = IVAS_DEC_HasDecodedFirstGoodFrame( hIvasDec, &decodedGoodFrame ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in IVAS_DEC_HasDecodedFirstGoodFrame, code: %d\n", error ); + goto cleanup; + } + + /* Once good frame decoded, catch up */ + if ( decodedGoodFrame ) { - if ( ( error = IVAS_DEC_GetDelay( hIvasDec, &delayNumSamples, &delayTimeScale ) ) != IVAS_ERR_OK ) + error = initOnFirstGoodFrame( + hIvasDec, + arg, + numInitialBadFrames, + nOutSamples, + delayNumSamples_orig, + &delayNumSamples, + &delayTimeScale, + &bsFormat, + &afWriter, + &masaWriter, + ismWriters, + &nOutChannels, + &numObj ); + if ( error != IVAS_ERR_OK ) { - fprintf( stderr, "\nUnable to get delay of decoder: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } - delayNumSamples_orig = delayNumSamples; } else { - delayNumSamples = 0; + ++numInitialBadFrames; } - zeroPad = delayNumSamples; } - if ( delayNumSamples < nOutSamples ) + + /* Write current frame */ + if ( decodedGoodFrame ) { - if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) + if ( delayNumSamples < nOutSamples ) { - fprintf( stderr, "\nOutput audio file writer error\n" ); - goto cleanup; + if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + goto cleanup; + } + delayNumSamples = 0; + } + else + { + delayNumSamples -= nOutSamples; } - delayNumSamples = 0; - } - else - { - delayNumSamples -= nOutSamples; } if ( !arg.quietModeEnabled ) @@ -1820,14 +2160,21 @@ static ivas_error decodeVoIP( systemTime_ms += 20; #ifdef WMOPS + update_mem(); update_wmops(); #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 */ - memset( pcmBuf, 0, zeroPad * nOutChannels * sizeof( int16_t ) ); - AudioFileWriter_write( afWriter, pcmBuf, zeroPad * nOutChannels ); + memset( pcmBuf, 0, delayNumSamples_orig[0] * nOutChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig[0] * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } /*------------------------------------------------------------------------------------------* * Printouts after decoding has finished @@ -1835,7 +2182,13 @@ static ivas_error decodeVoIP( if ( !arg.quietModeEnabled ) { - printf( "\nDecoder delay: %5u [samples] - Timescale: %5u\n", delayNumSamples_orig, delayTimeScale ); + printf( "\n\nDecoder+renderer delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * delayNumSamples_orig[1] / (float) delayTimeScale, delayNumSamples_orig[1], delayTimeScale ); + + if ( delayNumSamples_orig[2] > 0 ) + { + printf( "HRIR/BRIR delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * delayNumSamples_orig[2] / (float) delayTimeScale, delayNumSamples_orig[2], delayTimeScale ); + printf( "Total delay: %4.2f ms (%3u samples at timescale %5u)\n", 1000.f * ( delayNumSamples_orig[1] + delayNumSamples_orig[2] ) / (float) delayTimeScale, delayNumSamples_orig[1] + delayNumSamples_orig[2], delayTimeScale ); + } } /*------------------------------------------------------------------------------------------* @@ -1846,6 +2199,7 @@ static ivas_error decodeVoIP( cleanup: + EVS_RTPDUMP_DEPACKER_close( &rtpdumpDepacker ); AudioFileWriter_close( &afWriter ); JbmOffsetFileWriter_close( &jbmOffsetWriter ); #ifdef SUPPORT_JBM_TRACEFILE diff --git a/apps/encoder.c b/apps/encoder.c index 205457858c9031fac515bff639ebc74412c6fd39..aae2e1e88e1766814bff4987d2b6aab8156d59a8 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,34 +30,22 @@ *******************************************************************************************************/ +#include +#include +#include #include "lib_enc.h" #include "cmdl_tools.h" #include "audio_file_reader.h" #include "bitstream_writer.h" +#include "jbm_file_reader.h" #include "masa_file_reader.h" #include "ism_file_reader.h" -#include -#include -#ifdef WMOPS -#include "PROM_Size_lib_com.h" -#include "PROM_Size_lib_enc.h" -#include "wmops.h" -#endif -#ifdef RAM_COUNTING_TOOL -#include "mem_count.h" -#else -#include -#endif #ifdef DEBUGGING #include "debug.h" -#ifdef DEBUG_SPAR_FOA -#include "ivas_cnst.h" -#include "spar_debug.h" -#endif #endif +#include "wmc_auto.h" - -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /*------------------------------------------------------------------------------------------* * Local constants, enums, structures @@ -75,6 +63,7 @@ typedef union _EncInputFormatConfig { /* MONO details */ bool stereoToMonoDownmix; + #ifdef DEBUGGING /* STEREO details */ IVAS_ENC_STEREO_MODE stereoMode; @@ -86,16 +75,20 @@ typedef union _EncInputFormatConfig int16_t numObjects; const char *metadataFiles[IVAS_MAX_NUM_OBJECTS]; } ism; + /* SBA details */ struct EncSbaConfig { IVAS_ENC_SBA_ORDER order; bool isPlanar; } sba; + /* MASA details */ IVAS_ENC_MASA_VARIANT masaVariant; + /* MC details */ IVAS_ENC_MC_LAYOUT mcLayout; + } EncInputFormatConfig; /* Struct for storing cmdln arguments */ @@ -115,22 +108,25 @@ typedef struct bool quietModeEnabled; bool delayCompensationEnabled; const char *masaMetadataFile; -#ifdef DEBUGGING - IVAS_ENC_FORCED_MODE forcedMode; - const char *forcedModeFile; -#endif IVAS_ENC_CHANNEL_AWARE_CONFIG caConfig; const char *ca_config_file; bool mimeOutput; - bool agc; - bool pca; +#ifdef DEBUGGING + IVAS_ENC_FORCED_MODE forcedMode; + const char *forcedModeFile; +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + IVAS_ENC_AGC agc; +#endif #ifdef DEBUG_FOA_AGC FILE *agcBitstream; /* temporary */ #endif -#ifdef DEBUG_SPAR_FOA +#ifdef DEBUG_SBA const char *dbg_file_tag; #endif +#endif + bool pca; + bool ism_extended_metadata; } EncArguments; @@ -142,7 +138,6 @@ typedef struct static void initArgStruct( EncArguments *arg ); static bool parseCmdlIVAS_enc( int16_t argc, char *argv[], EncArguments *arg ); static void usage_enc( void ); -static ivas_error readChannelAwareConfig( FILE *file, IVAS_ENC_CHANNEL_AWARE_CONFIG *caConfig ); static bool readBandwidth( FILE *file, IVAS_ENC_BANDWIDTH *bandwidth, int32_t *bandwidthFrameCounter ); static bool readBitrate( FILE *file, int32_t *bitrate ); #ifdef DEBUGGING @@ -151,40 +146,6 @@ static IVAS_ENC_FORCED_MODE parseForcedMode( char *forcedModeChar ); #endif -#ifdef WMOPS -/*------------------------------------------------------------------------------------------* - * Function to print complexity & memory estimates at the encoder - *------------------------------------------------------------------------------------------*/ - -extern int16_t *ptr_base_stack; -extern int16_t *ptr_base_stack; -extern int16_t *ptr_max_stack; -extern int32_t wc_frame; -extern char location_max_stack[256]; -void print_stack_call_tree( void ); - -static void print_mem_enc( size_t SRAM_size ) -{ - fprintf( stdout, "\n\n --- Encoder memory usage --- \n\n" ); - - fprintf( stdout, "PROM size (encoder): %d words (or instructions)\n", PROM_Size_lib_enc ); - fprintf( stdout, "PROM size (common): %d words (or instructions)\n", PROM_Size_lib_com ); - fprintf( stdout, "Stack size (encoder): %ld words in %s() in frame #%d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) / sizeof( float ), location_max_stack, wc_frame ); - fprintf( stdout, "Table ROM size (encoder): %ld words\n", ( Const_Data_Size_rom_enc() + Const_Data_Size_ivas_rom_enc() ) / sizeof( float ) ); - fprintf( stdout, "Table ROM size (common): %ld words\n", ( Const_Data_Size_rom_com() + Const_Data_Size_ivas_rom_com() ) / sizeof( float ) ); -#ifdef RAM_COUNTING_TOOL - fprintf( stdout, "Static RAM size (encoder): %ld words\n\n", SRAM_size ); -#endif - print_stack_call_tree(); - - fprintf( stdout, "Note: this is an optimistic estimate of the memory consumption assuming\n" ); - fprintf( stdout, " that each variable (short, long or float) in the codec requires\n" ); - fprintf( stdout, " 32 bits of memory and may therefore be represented by 1 word.\n" ); - fprintf( stdout, " The following formula is used: sizeof('memory array')/sizeof(float)\n\n" ); -} -#endif - - /*------------------------------------------------------------------------------------------* * main() * @@ -206,7 +167,7 @@ int main( AudioFileReader *audioReader = NULL; FILE *f_bitrateProfile = NULL; FILE *f_bwProfile = NULL; - FILE *f_caProfile = NULL; + JbmFileReader *jbmReader = NULL; MasaFileReader *masaReader = NULL; IsmFileReader *ismReaders[IVAS_MAX_NUM_OBJECTS]; for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) @@ -216,26 +177,17 @@ int main( int16_t *pcmBuf = NULL; #ifdef DEBUGGING FILE *f_forcedModeProfile = NULL; +#ifdef DEBUG_SBA + int16_t numTransportChannels = 1; #endif - -#ifdef DEBUG_SPAR_FOA - spar_debug_t dbg_params; -#endif -#ifdef WMOPS - size_t SRAM_size = 0; -#endif - -#ifdef WMOPS - reset_wmops(); - reset_stack(); #endif #ifdef DEBUGGING dbgargs( &argc, argv ); #endif - -#ifdef RAM_COUNTING_TOOL - mem_count_init( 0, USE_32BITS ); +#ifdef WMOPS + reset_wmops(); + reset_mem( USE_32BITS ); #endif initArgStruct( &arg ); @@ -252,18 +204,6 @@ int main( goto cleanup; } -#ifdef DEBUG_SPAR_FOA - dbg_params.agc = (int16_t) arg.agc; - dbg_params.dtx_on = (int16_t) arg.dtxConfig.enabled; - dbg_params.file_tag = arg.dbg_file_tag; - dbg_params.ivas_total_brate = arg.initBitrate; -#ifdef DEBUG_AGC - ivas_open_agc_debug_files( &dbg_params ); -#endif - ivas_open_debug_files( &dbg_params ); -#endif - - /*------------------------------------------------------------------------------------------* * Open and initialize IVAS encoder *------------------------------------------------------------------------------------------*/ @@ -274,15 +214,6 @@ int main( goto cleanup; } - /*------------------------------------------------------------------------------------------* - * Open input audio file - *------------------------------------------------------------------------------------------*/ - - if ( AudioFileReader_open( &audioReader, arg.inputWavFilename, arg.inputFs ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nCan't open %s\n\n", arg.inputWavFilename ); - goto cleanup; - } /*------------------------------------------------------------------------------------------* * Open output bitstream file @@ -366,50 +297,61 @@ int main( { if ( bandwidth == IVAS_ENC_BANDWIDTH_NB && arg.inputFormat != IVAS_ENC_INPUT_MONO ) { - fprintf( stdout, "\nNB coding not supported in IVAS. Switching to WB.\n" ); + fprintf( stdout, "\nNB coding not supported in IVAS. Switching to WB.\n\n" ); } - - switch ( bandwidth ) + else { - case IVAS_ENC_BANDWIDTH_UNDEFINED: - break; - case IVAS_ENC_BANDWIDTH_NB: - fprintf( stdout, "Max. encoded bandwidth: NB\n" ); - break; - case IVAS_ENC_BANDWIDTH_WB: - fprintf( stdout, "Max. encoded bandwidth: WB\n" ); - break; - case IVAS_ENC_BANDWIDTH_SWB: - fprintf( stdout, "Max. encoded bandwidth: SWB\n" ); - break; - case IVAS_ENC_BANDWIDTH_FB: - fprintf( stdout, "Max. encoded bandwidth: FB\n" ); - break; - default: - fprintf( stderr, "Error: Invalid bandwidth value\n" ); - usage_enc(); - goto cleanup; + switch ( bandwidth ) + { + case IVAS_ENC_BANDWIDTH_UNDEFINED: + break; + case IVAS_ENC_BANDWIDTH_NB: + fprintf( stdout, "Max. encoded bandwidth: NB\n" ); + break; + case IVAS_ENC_BANDWIDTH_WB: + fprintf( stdout, "Max. encoded bandwidth: WB\n" ); + break; + case IVAS_ENC_BANDWIDTH_SWB: + fprintf( stdout, "Max. encoded bandwidth: SWB\n" ); + break; + case IVAS_ENC_BANDWIDTH_FB: + fprintf( stdout, "Max. encoded bandwidth: FB\n" ); + break; + default: + fprintf( stderr, "Error: Invalid bandwidth value\n" ); + usage_enc(); + goto cleanup; + } } } + /*------------------------------------------------------------------------------------------* + * Handle Channel-aware mode + *------------------------------------------------------------------------------------------*/ + IVAS_ENC_CHANNEL_AWARE_CONFIG caConfig = arg.caConfig; if ( arg.ca_config_file ) { - if ( ( f_caProfile = fopen( arg.ca_config_file, "rb" ) ) == NULL ) + if ( ( jbmReader = JbmFileReader_open( arg.ca_config_file ) ) == NULL ) { fprintf( stderr, "\nError: Channel aware configuration file could not be opened: %s\n\n", arg.ca_config_file ); usage_enc(); goto cleanup; } - else - { - fprintf( stdout, "\nChannel-aware mode: ON, Channel-aware config file name: %s \n\n", arg.ca_config_file ); - } + + fprintf( stdout, "Channel-aware mode: ON, config file: %s \n", arg.ca_config_file ); } - else if ( arg.caConfig.channelAwareModeEnabled ) + else if ( caConfig.channelAwareModeEnabled ) { - fprintf( stdout, "\nChannel-aware mode: ON, FEC indicator : %s FEC offset: %d \n\n", ( caConfig.fec_indicator == IVAS_ENC_FEC_LO ) ? "LO" : "HI", caConfig.fec_offset ); + fprintf( stdout, "Channel-aware mode: ON, FEC indicator : %s FEC offset: %d \n\n", ( caConfig.fec_indicator == IVAS_ENC_FEC_LO ) ? "LO" : "HI", caConfig.fec_offset ); + } + + if ( arg.inputFormat != IVAS_ENC_INPUT_MONO && ( caConfig.channelAwareModeEnabled || arg.ca_config_file ) ) + { + fprintf( stderr, "Channel-aware mode is not supported in IVAS.\n\n" ); + usage_enc(); + goto cleanup; } /*------------------------------------------------------------------------------------------* @@ -437,14 +379,32 @@ int main( } break; case IVAS_ENC_INPUT_ISM: - if ( ( error = IVAS_ENC_ConfigureForObjects( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.ism.numObjects ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_ENC_ConfigureForObjects( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.ism.numObjects, arg.ism_extended_metadata ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_ENC_ConfigureForObjects failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); goto cleanup; } break; case IVAS_ENC_INPUT_SBA: - if ( ( error = IVAS_ENC_ConfigureForAmbisonics( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.sba.order, arg.inputFormatConfig.sba.isPlanar, arg.agc, arg.pca ) ) != IVAS_ERR_OK ) + if ( ( error = + IVAS_ENC_ConfigureForAmbisonics( + hIvasEnc, + arg.inputFs, + totalBitrate, + arg.max_bwidth_user, + bandwidth, + arg.dtxConfig, + arg.inputFormatConfig.sba.order, + arg.inputFormatConfig.sba.isPlanar, +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + arg.agc, +#endif + arg.pca +#ifdef DEBUG_SBA_AUDIO_DUMP + , + &numTransportChannels +#endif + ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_ENC_ConfigureForAmbisonics failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); goto cleanup; @@ -470,7 +430,70 @@ int main( goto cleanup; } - IVAS_ENC_PrintConfig( hIvasEnc ); + if ( ( error = IVAS_ENC_PrintConfig( hIvasEnc, caConfig.channelAwareModeEnabled ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\n IVAS_ENC_PrintConfig failed %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + + /*------------------------------------------------------------------------------------------* + * Open input audio file + *------------------------------------------------------------------------------------------*/ + + if ( AudioFileReader_open( &audioReader, arg.inputWavFilename ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nCan't open %s\n\n", arg.inputWavFilename ); + goto cleanup; + } + + /* Validate input sampling rate */ + int32_t inFileSampleRate = 0; + error = AudioFileReader_getSamplingRate( audioReader, &inFileSampleRate ); + switch ( error ) + { + case IVAS_ERR_OK: + if ( inFileSampleRate != arg.inputFs ) + { + fprintf( stderr, "\nSampling rate mismatch: %d Hz requested, but %d Hz found in file %s\n\n", arg.inputFs, inFileSampleRate, arg.inputWavFilename ); + goto cleanup; + } + break; + case IVAS_ERR_SAMPLING_RATE_UNKNOWN: + /* IVAS_ERR_SAMPLING_RATE_UNKNOWN will be returned for raw PCM files. + * Nothing to check here */ + break; + default: + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + + + /* Validate number of channels */ + int16_t encInNumChannels = 0; + if ( ( error = IVAS_ENC_GetNumInChannels( hIvasEnc, &encInNumChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + int16_t inFileNumChannels = 0; + error = AudioFileReader_getNumChannels( audioReader, &inFileNumChannels ); + switch ( error ) + { + case IVAS_ERR_OK: + if ( inFileNumChannels != encInNumChannels ) + { + fprintf( stderr, "\nNumber of input audio channels mismatch: %d accepted by encoder, but %d found in file %s\n\n", encInNumChannels, inFileNumChannels, arg.inputWavFilename ); + goto cleanup; + } + break; + case IVAS_ERR_NUM_CHANNELS_UNKNOWN: + /* IVAS_ERR_NUM_CHANNELS_UNKNOWN will be returned for raw PCM files. + * Nothing to check here */ + break; + default: + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } /*------------------------------------------------------------------------------------------* * Open input metadata files @@ -517,23 +540,9 @@ int main( #endif /*------------------------------------------------------------------------------------------* - * Compensate for encoder delay (bitstream aligned with input signal) + * Allocate input data buffer *------------------------------------------------------------------------------------------*/ - int16_t encDelayInSamples; - if ( ( error = IVAS_ENC_GetDelay( hIvasEnc, &encDelayInSamples ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nGetDelay failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); - goto cleanup; - } - - int16_t numInputChannels; - if ( ( error = IVAS_ENC_GetNumInputChannels( hIvasEnc, &numInputChannels ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nGetNumInputChannels failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); - goto cleanup; - } - int16_t pcmBufSize; if ( ( error = IVAS_ENC_GetInputBufferSize( hIvasEnc, &pcmBufSize ) ) != IVAS_ERR_OK ) { @@ -543,6 +552,17 @@ int main( pcmBuf = malloc( pcmBufSize * sizeof( int16_t ) ); + /*------------------------------------------------------------------------------------------* + * Compensate for encoder delay (bitstream aligned with input signal) + *------------------------------------------------------------------------------------------*/ + + int16_t encDelayInSamples; + if ( ( error = IVAS_ENC_GetDelay( hIvasEnc, &encDelayInSamples ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nGetDelay failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); + goto cleanup; + } + if ( arg.delayCompensationEnabled && encDelayInSamples ) { /* read samples and throw them away */ @@ -558,6 +578,13 @@ int main( uint16_t bitStream[IVAS_MAX_BITS_PER_FRAME]; uint16_t numBits = 0; +#ifdef DEBUG_SBA +#ifdef DEBUG_AGC + ivas_open_agc_debug_files( (int16_t) arg.agc ); +#endif + ivas_open_sba_encoder_debug_files( arg.inputFs, numTransportChannels, arg.dbg_file_tag, arg.initBitrate, (int16_t) arg.dtxConfig.enabled ); +#endif + if ( !arg.quietModeEnabled ) { fprintf( stdout, "\n------ Running the encoder ------\n\n" ); @@ -637,17 +664,17 @@ int main( } } - if ( f_caProfile ) + if ( jbmReader ) { - if ( ( error = readChannelAwareConfig( f_caProfile, &caConfig ) ) != IVAS_ERR_OK ) + if ( ( error = JbmFileReader_readCAconfig( jbmReader, &caConfig ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "readChannelAwareConfig failed: %s\n", IVAS_ENC_GetErrorMessage( error ) ); + fprintf( stderr, "JbmFileReader_readCAconfig() failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); goto cleanup; } if ( ( error = IVAS_ENC_SetChannelAwareConfig( hIvasEnc, caConfig ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "IVAS_ENC_SetChannelAwareConfig failed: %s\n", IVAS_ENC_GetErrorMessage( error ) ); + fprintf( stderr, "IVAS_ENC_SetChannelAwareConfig failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) ); goto cleanup; } } @@ -673,7 +700,7 @@ int main( } #endif - /* Read ISm input metadata */ + /* Read ISM input metadata */ for ( i = 0; i < numIsmInputs; ++i ) { if ( ismReaders[i] == NULL ) @@ -733,6 +760,7 @@ int main( } #ifdef WMOPS + update_mem(); update_wmops(); #endif } @@ -768,6 +796,11 @@ cleanup: AudioFileReader_close( &audioReader ); + if ( jbmReader ) + { + JbmFileReader_close( &jbmReader ); + } + for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) { if ( ismReaders[i] != NULL ) @@ -791,39 +824,26 @@ cleanup: fclose( f_bitrateProfile ); } - if ( f_caProfile ) - { - fclose( f_caProfile ); - } - -#ifdef DEBUGGING - if ( f_forcedModeProfile ) - { - fclose( f_forcedModeProfile ); - } -#endif - IVAS_ENC_Close( &hIvasEnc ); -#ifdef RAM_COUNTING_TOOL -#ifdef WMOPS - SRAM_size = -#endif - mem_count_summary( USE_DEFAULT ); -#endif #ifdef WMOPS print_wmops(); - print_mem_enc( SRAM_size ); + print_mem( NULL ); #endif #ifdef DEBUGGING dbgclose(); -#endif -#ifdef DEBUG_SPAR_FOA - ivas_close_remove_debug_files(); + if ( f_forcedModeProfile ) + { + fclose( f_forcedModeProfile ); + } + +#ifdef DEBUG_SBA + ivas_close_sba_encoder_debug_files(); #ifdef DEBUG_AGC - ivas_close_agc_debug_files( &io_params ); + ivas_close_agc_debug_files(); +#endif #endif #endif @@ -854,22 +874,25 @@ static void initArgStruct( EncArguments *arg ) arg->quietModeEnabled = false; arg->delayCompensationEnabled = true; arg->masaMetadataFile = NULL; -#ifdef DEBUGGING - arg->forcedMode = IVAS_ENC_FORCE_UNFORCED; - arg->forcedModeFile = NULL; -#endif arg->caConfig = IVAS_ENC_GetDefaultChannelAwareConfig(); arg->ca_config_file = NULL; arg->mimeOutput = false; + arg->ism_extended_metadata = false; - arg->agc = IVAS_DEFAULT_AGC; - arg->pca = false; +#ifdef DEBUGGING + arg->forcedMode = IVAS_ENC_FORCE_UNFORCED; + arg->forcedModeFile = NULL; +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + arg->agc = IVAS_ENC_AGC_UNDEFINED; +#endif #ifdef DEBUG_FOA_AGC arg->agcBitstream = NULL; #endif -#ifdef DEBUG_SPAR_FOA +#ifdef DEBUG_SBA arg->dbg_file_tag = NULL; #endif +#endif + arg->pca = false; return; } @@ -906,7 +929,9 @@ static bool parseCmdlIVAS_enc( while ( i < argc - 4 ) { strncpy( argv_to_upper, argv[i], sizeof( argv_to_upper ) - 1 ); + argv_to_upper[sizeof( argv_to_upper ) - 1] = '\0'; to_upper( argv_to_upper ); + /*-----------------------------------------------------------------* * Bandwidth limitation *-----------------------------------------------------------------*/ @@ -916,6 +941,7 @@ static bool parseCmdlIVAS_enc( arg->max_bwidth_user = true; strncpy( stmp, argv[i + 1], sizeof( stmp ) - 1 ); + stmp[sizeof( stmp ) - 1] = '\0'; to_upper( stmp ); if ( strcmp( stmp, "-NB" ) == 0 || strcmp( stmp, "NB" ) == 0 ) @@ -1031,6 +1057,54 @@ static bool parseCmdlIVAS_enc( } #endif /* #ifdef DEBUG_MODE_INFO_TWEAK */ #endif /* #ifdef DEBUG_MODE_INFO */ + +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + /*-----------------------------------------------------------------* + * IVAS SPAR AGC option + *-----------------------------------------------------------------*/ + else if ( strcmp( argv_to_upper, "-AGC" ) == 0 ) + { + i++; + if ( i < argc - 4 ) + { + arg->agc = ( atoi( argv[i] ) ) ? IVAS_ENC_AGC_ENABLED : IVAS_ENC_AGC_DISABLED; + if ( argv[i] == NULL || atoi( argv[i] ) < 0 || atoi( argv[i] ) > 1 ) + { + fprintf( stderr, "Error: wrong adaptive gain control option specified (%d), expected 0 or 1\n\n", (int32_t) atoi( argv[i] ) ); + usage_enc(); + return false; + } + i++; + } + else + { + fprintf( stderr, "Error: unspecified adaptive gain control option\n\n" ); + usage_enc(); + return false; + } + } +#endif + +#ifdef DEBUG_SBA + /*-----------------------------------------------------------------* + * IVAS SPAR debug files tag + *-----------------------------------------------------------------*/ + else if ( strcmp( argv_to_upper, "-TAG" ) == 0 ) + { + i++; + if ( i < argc - 4 ) + { + arg->dbg_file_tag = argv[i]; + ++i; + } + else + { + fprintf( stderr, "Error: [IVAS SPAR Encoder] unspecified tag value \n\n" ); + usage_enc(); + return false; + } + } +#endif #endif /* #ifdef DEBUGGING */ /*-----------------------------------------------------------------* @@ -1049,11 +1123,13 @@ static bool parseCmdlIVAS_enc( else if ( strcmp( argv_to_upper, "-RF" ) == 0 ) { - arg->caConfig.channelAwareModeEnabled = true; + arg->caConfig.channelAwareModeEnabled = 1; i++; if ( i < argc - 4 ) { + strncpy( stmp, argv[i], sizeof( stmp ) ); + stmp[sizeof( stmp ) - 1] = '\0'; to_upper( argv[i] ); if ( strcmp( argv[i], "LO" ) == 0 ) { @@ -1065,16 +1141,15 @@ static bool parseCmdlIVAS_enc( } else { - arg->ca_config_file = argv[i]; + arg->ca_config_file = stmp; } i++; - if ( ( sscanf( argv[i], "%d", &tmp ) == 1 ) && ( i < argc - 4 ) ) { if ( tmp == 0 ) { - arg->caConfig.channelAwareModeEnabled = false; + arg->caConfig.channelAwareModeEnabled = 0; arg->caConfig.fec_offset = 0; i++; } @@ -1188,8 +1263,20 @@ static bool parseCmdlIVAS_enc( arg->inputFormat = IVAS_ENC_INPUT_ISM; i++; - if ( i < argc - 5 ) + if ( i < argc - 4 ) { + if ( argv[i][0] == '+' ) + { + argv[i]++; + arg->ism_extended_metadata = true; + } + if ( !is_digits_only( argv[i] ) ) + { + fprintf( stderr, "Error: Number of ISM channels must be an integer number!\n\n" ); + usage_enc(); + return false; + } + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { i++; @@ -1201,6 +1288,12 @@ static bool parseCmdlIVAS_enc( usage_enc(); return false; } + else if ( tmp > IVAS_MAX_NUM_OBJECTS ) + { + fprintf( stderr, "Error: Too high number of ISM channels specified!\n\n" ); + usage_enc(); + return false; + } else { arg->inputFormatConfig.ism.numObjects = (int16_t) tmp; @@ -1232,7 +1325,7 @@ static bool parseCmdlIVAS_enc( } else { - fprintf( stderr, "Error: not enough arguments\n\n" ); + fprintf( stderr, "Error: not enough metadata arguments specified!\n\n" ); usage_enc(); return false; } @@ -1244,17 +1337,14 @@ static bool parseCmdlIVAS_enc( arg->inputFormat = IVAS_ENC_INPUT_SBA; /* SBA configuration */ - if ( i < argc - 4 ) + if ( i < argc - 4 && is_number( argv[i] ) && sscanf( argv[i], "%d", &tmp ) > 0 ) { - if ( sscanf( argv[i], "%d", &tmp ) > 0 ) - { - i++; - } + i++; } else { tmp = -1; /* this is to avoid a compilation warning */ - fprintf( stderr, "Error: SBA order not specified!\n\n" ); + fprintf( stderr, "Error: SBA order must be specified, expecting a number!\n\n" ); usage_enc(); return false; } @@ -1286,6 +1376,13 @@ static bool parseCmdlIVAS_enc( if ( i < argc - 4 ) { + if ( !is_digits_only( argv[i] ) ) + { + fprintf( stderr, "Error: Number of MASA channels must be an integer number!\n\n" ); + usage_enc(); + return false; + } + if ( sscanf( argv[i], "%d", &tmp ) > 0 ) { i++; @@ -1300,7 +1397,7 @@ static bool parseCmdlIVAS_enc( arg->inputFormatConfig.masaVariant = IVAS_ENC_MASA_2CH; break; default: - fprintf( stderr, "Error: MASA channels must for the moment be 1 or 2.\n\n" ); + fprintf( stderr, "Error: MASA channels must be 1 or 2.\n\n" ); usage_enc(); return false; } @@ -1325,24 +1422,23 @@ static bool parseCmdlIVAS_enc( if ( i < argc - 4 ) { - - if ( strcmp( to_upper( argv[i] ), "5_1" ) == 0 ) + if ( strcmp( argv[i], "5_1" ) == 0 ) { arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_5_1; } - else if ( strcmp( to_upper( argv[i] ), "7_1" ) == 0 ) + else if ( strcmp( argv[i], "7_1" ) == 0 ) { arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_7_1; } - else if ( strcmp( to_upper( argv[i] ), "5_1_2" ) == 0 ) + else if ( strcmp( argv[i], "5_1_2" ) == 0 ) { arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_5_1_2; } - else if ( strcmp( to_upper( argv[i] ), "5_1_4" ) == 0 ) + else if ( strcmp( argv[i], "5_1_4" ) == 0 ) { arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_5_1_4; } - else if ( strcmp( to_upper( argv[i] ), "7_1_4" ) == 0 ) + else if ( strcmp( argv[i], "7_1_4" ) == 0 ) { arg->inputFormatConfig.mcLayout = IVAS_ENC_MC_7_1_4; } @@ -1367,27 +1463,6 @@ static bool parseCmdlIVAS_enc( arg->inputFormatConfig.stereoToMonoDownmix = true; i++; } - else if ( strcmp( argv_to_upper, "-AGC" ) == 0 ) - { - i++; - if ( i < argc - 4 ) - { - arg->agc = (int16_t) atoi( argv[i] ); - if ( argv[i] == NULL || atoi( argv[i] ) < 0 || atoi( argv[i] ) > 1 ) - { - fprintf( stderr, "Error: wrong adaptive gain control option specified (%d), expected 0 or 1\n\n", (int32_t) atoi( argv[i] ) ); - usage_enc(); - return false; - } - i++; - } - else - { - fprintf( stderr, "Error: unspecified adaptive gain control option\n\n" ); - usage_enc(); - return false; - } - } else if ( strcmp( argv_to_upper, "-BYPASS" ) == 0 ) // VE: should be renamed to "-pca" { i++; @@ -1421,26 +1496,6 @@ static bool parseCmdlIVAS_enc( return false; } } -#ifdef DEBUG_SPAR_FOA - /*-----------------------------------------------------------------* - * IVAS SPAR debug files tag - *-----------------------------------------------------------------*/ - else if ( strcmp( argv_to_upper, "-TAG" ) == 0 ) - { - i++; - if ( i < argc - 4 ) - { - arg->dbg_file_tag = argv[i]; - ++i; - } - else - { - fprintf( stderr, "Error: [IVAS SPAR Encoder] unspecified tag value \n\n" ); - usage_enc(); - return false; - } - } -#endif /*-----------------------------------------------------------------* * Option not recognized @@ -1573,8 +1628,13 @@ static void usage_enc( void ) fprintf( stdout, " *VBR mode (average bitrate),\n" ); fprintf( stdout, " for AMR-WB IO modes R = (6600, 8850, 12650, 14250, 15850, 18250,\n" ); fprintf( stdout, " 19850, 23050, 23850) \n" ); - fprintf( stdout, " for IVAS stereo & ISm R =(13200, 16400, 24400, 32000, 48000, 64000, 80000, \n" ); + fprintf( stdout, " for IVAS stereo R = (13200, 16400, 24400, 32000, 48000, 64000, 80000, \n" ); fprintf( stdout, " 96000, 128000, 160000, 192000, 256000) \n" ); + fprintf( stdout, " for IVAS ISM R = 13200 for 1 ISM, 16400 for 1 ISM and 2 ISM, \n" ); + fprintf( stdout, " (24400, 32000, 48000, 64000, 80000, 96000, 128000) \n" ); + fprintf( stdout, " for 2 ISM, 3 ISM and 4 ISM also 160000, 192000, 256000) \n" ); + fprintf( stdout, " for 3 ISM and 4 ISM also 384000 \n" ); + fprintf( stdout, " for 4 ISM also 512000 \n" ); fprintf( stdout, " for IVAS SBA, MASA, MC R=(13200, 16400, 24400, 32000, 48000, 64000, 80000, \n" ); fprintf( stdout, " 96000, 128000, 160000, 192000, 256000, 384000, 512000) \n" ); fprintf( stdout, " Alternatively, R can be a bitrate switching file which consists of R values\n" ); @@ -1590,16 +1650,17 @@ static void usage_enc( void ) fprintf( stdout, "EVS mono is default, for IVAS choose one of the following: -stereo, -ism, -sba, -masa, -mc\n" ); fprintf( stdout, "-stereo [Mode] : Stereo format, default is unified stereo \n" ); fprintf( stdout, " optional for Mode: 1: DFT Stereo, 2: TD Stereo, 3: MDCT Stereo\n" ); - fprintf( stdout, "-ism Channels Files : ISm format \n" ); - fprintf( stdout, " where Channels specifies the number of ISms (1-4)\n" ); + fprintf( stdout, "-ism (+)Ch Files : ISM format \n" ); + fprintf( stdout, " where Ch specifies the number of ISMs (1-4)\n" ); + fprintf( stdout, " where positive (+) means extended metadata format is used (including orientation and radius) \n" ); fprintf( stdout, " and Files specify input files containing metadata, one file per object\n" ); fprintf( stdout, " (use NULL for no input metadata)\n" ); fprintf( stdout, "-sba +/-Order : Scene Based Audio input format (Ambisonics ACN/SN3D),\n" ); fprintf( stdout, " where Order specifies the Ambisionics order (1-3),\n" ); fprintf( stdout, " where positive (+) means full 3D and negative (-) only 2D/planar components to be coded\n" ); - fprintf( stdout, "-masa Ch File : MASA format \n" ); - fprintf( stdout, " where Ch specifies the number of input/transport channels (1 or 2): \n" ); - fprintf( stdout, " and File specifies input file containing parametric metadata \n" ); + fprintf( stdout, "-masa Channels File : MASA format \n" ); + fprintf( stdout, " where Channels specifies the number of input/transport channels (1 or 2): \n" ); + fprintf( stdout, " and File specifies input file containing parametric MASA metadata \n" ); fprintf( stdout, "-mc InputConf : Multi-channel format\n" ); fprintf( stdout, " where InputConf specifies the channel configuration: 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4\n" ); fprintf( stdout, " Loudspeaker positions are assumed to have azimuth and elevation as per \n" ); @@ -1609,8 +1670,7 @@ static void usage_enc( void ) fprintf( stdout, " where 0 = adaptive, 3-100 = fixed in number of frames,\n" ); fprintf( stdout, " default is deactivated\n" ); fprintf( stdout, "-dtx : Activate DTX mode with a SID update rate of 8 frames\n" ); - fprintf( stdout, " Note: DTX is currently supported in EVS, DFT/TD stereo, 1 ISm, \n" ); - fprintf( stdout, " SBA (up to 128kbps) and MASA (up to 128kbps)\n" ); + fprintf( stdout, " Note: DTX is supported in EVS, stereo, ISM, SBA up to 80kbps and MASA up to 128kbps \n" ); fprintf( stdout, "-rf p o : Activate channel-aware mode for WB and SWB signal at 13.2kbps, \n" ); fprintf( stdout, " where FEC indicator, p: LO or HI, and FEC offset, o: 2, 3, 5, or 7 in number of frames.\n" ); fprintf( stdout, " Alternatively p and o can be replaced by a rf configuration file with each line \n" ); @@ -1624,14 +1684,18 @@ static void usage_enc( void ) fprintf( stdout, " The encoder produces TS26.445 Annex.2.6 Mime Storage Format, (not RFC4867 Mime Format).\n" ); fprintf( stdout, " default output bitstream file format is G.192\n" ); -#ifdef DEBUG_SPAR_FOA - fprintf( stdout, "-tag : Tag name for intermediate debug files\n" ); -#endif - fprintf( stdout, "-agc op : SBA Adaptive gain control, op = (0, 1), by default op is 0 or deactivated\n" ); fprintf( stdout, "-bypass mode : SBA PCA by-pass, mode = (1, 2), 1 = PCA off, 2 = signal adaptive, default is 1\n" ); #ifdef DEBUGGING fprintf( stdout, "-force T : Force specific mode, T = (speech, music, ACELP, GSC, TCX, HQ),\n" ); fprintf( stdout, " alternatively, T can be a text file where each line contains \"nb_frames T\"\n" ); +#ifdef DEBUG_SBA + fprintf( stdout, "-tag : Tag name for intermediate debug files\n" ); +#endif +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + fprintf( stdout, "-agc op : SBA Adaptive gain control, op = (0, 1). \n" ); + fprintf( stdout, " By default op is 1 (activated) for bitrates between 24400 and 32000,\n" ); + fprintf( stdout, " otherwise it is 0 (deactivated) for all other bitrates\n" ); +#endif #ifdef DEBUG_MODE_INFO #ifdef DEBUG_MODE_INFO_TWEAK fprintf( stdout, "-info : specify subfolder name for debug output\n" ); @@ -1646,66 +1710,6 @@ static void usage_enc( void ) } -/*---------------------------------------------------------------------* - * readChannelAwareConfig() - * - * - *---------------------------------------------------------------------*/ - -static ivas_error readChannelAwareConfig( - FILE *file, - IVAS_ENC_CHANNEL_AWARE_CONFIG *caConfig ) -{ - char rline[10], str[4]; - int16_t tmp; - - /* Initialize */ - caConfig->fec_offset = 0; - caConfig->fec_indicator = IVAS_ENC_FEC_HI; - - while ( fgets( rline, 10, file ) == NULL && feof( file ) ) - { - rewind( file ); - } - - if ( sscanf( rline, "%s %hd", str, &tmp ) != 2 ) - { - fprintf( stderr, "Error in the RF configuration file. There is no proper configuration line.\n" ); - return IVAS_ERR_INVALID_FEC_CONFIG; - } - - /* Read RF FEC indicator */ - to_upper( str ); - - if ( strcmp( str, "HI" ) == 0 ) - { - caConfig->fec_indicator = IVAS_ENC_FEC_HI; - } - else if ( strcmp( str, "LO" ) == 0 ) - { - caConfig->fec_indicator = IVAS_ENC_FEC_LO; - } - else - { - fprintf( stderr, "Error: Incorrect FEC indicator string. Exiting the encoder.\n" ); - return IVAS_ERR_INVALID_FEC_CONFIG; - } - - /* Read RF FEC offset */ - if ( tmp == 0 || tmp == 2 || tmp == 3 || tmp == 5 || tmp == 7 ) - { - caConfig->fec_offset = tmp; - } - else - { - fprintf( stderr, "Error: incorrect FEC offset specified in the RF configuration file; RF offset can be 2, 3, 5, or 7. \n" ); - return IVAS_ERR_INVALID_FEC_CONFIG; - } - - return IVAS_ERR_OK; -} - - /*---------------------------------------------------------------------* * readBandwidth() * diff --git a/apps/renderer.c b/apps/renderer.c new file mode 100644 index 0000000000000000000000000000000000000000..726eeb237b13c1e6f6f7b3c9b391b17373e213d0 --- /dev/null +++ b/apps/renderer.c @@ -0,0 +1,2674 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "lib_rend.h" +#include +#include +#include +#include +#include +#include +#include "audio_file_reader.h" +#include "audio_file_writer.h" +#include "cmdl_tools.h" +#include "cmdln_parser.h" +#include "head_rotation_file_reader.h" +#include "vector3_pair_file_reader.h" +#include "hrtf_file_reader.h" +#include "ism_file_reader.h" +#include "ls_custom_file_reader.h" +#include "masa_file_reader.h" +#include "prot.h" +#include "render_config_reader.h" +#include "wmc_auto.h" + + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + +#define RENDERER_MAX_CLI_ARG_LENGTH ( FILENAME_MAX ) +#define RENDERER_MAX_METADATA_LENGTH 8192 +#define RENDERER_MAX_METADATA_LINE_LENGTH 1024 + +#if !defined( DEBUGGING ) && !defined( WMOPS ) +static +#endif + int32_t frame = 0; + +#ifdef _WIN32 +#define SEP_FOLDER '\\' +#else +#define SEP_FOLDER '/' +#endif + + +/*------------------------------------------------------------------------------------------* + * Local structures + *------------------------------------------------------------------------------------------*/ + +typedef struct +{ + uint32_t frameCounter; + uint16_t numObjects; + IsmFileReader *ismReaders[RENDERER_MAX_ISM_INPUTS]; + uint32_t numPositions[RENDERER_MAX_ISM_INPUTS]; + IVAS_REND_AudioObjectPosition *positions[RENDERER_MAX_ISM_INPUTS]; /* size: [RENDERER_MAX_ISM_INPUTS][numPositions[object_index]] */ + uint16_t *positionDurations[RENDERER_MAX_ISM_INPUTS]; /* size: [RENDERER_MAX_ISM_INPUTS][numPositions[object_index]] */ + uint32_t currentPositionIdxs[RENDERER_MAX_ISM_INPUTS]; /* Index of current position as listed in the metadata file */ + uint16_t durationCounters[RENDERER_MAX_ISM_INPUTS]; /* Number of frames spent at current position */ +} IsmPositionProvider; + +typedef struct +{ + IVAS_REND_AudioConfig audioConfig; + int32_t inputChannelIndex; + float gain_dB; +} RendererInput; + +typedef struct +{ + IVAS_REND_AudioObjectPosition positions[RENDERER_MAX_ISM_INPUTS]; + int16_t numObjects; +} ObjectPositionBuffer; + +typedef struct +{ + RendererInput audioObjects[RENDERER_MAX_ISM_INPUTS]; + uint16_t numAudioObjects; + RendererInput multiChannelBuses[RENDERER_MAX_MC_INPUTS]; + uint16_t numMultiChannelBuses; + RendererInput ambisonicsBuses[RENDERER_MAX_SBA_INPUTS]; + uint16_t numAmbisonicsBuses; + IVAS_CUSTOM_LS_DATA inSetupCustom; + RendererInput masaBuses[RENDERER_MAX_MASA_INPUTS]; + uint16_t numMasaBuses; +} InputConfig; + +typedef struct +{ + IVAS_REND_AudioConfig audioConfig; + IVAS_CUSTOM_LS_DATA outSetupCustom; +} OutputConfig; + +typedef struct +{ + char executableName[RENDERER_MAX_CLI_ARG_LENGTH]; + char inputFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; + char outputFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; + int32_t sampleRate; + InputConfig inConfig; + OutputConfig outConfig; + char inMetadataFilePaths[RENDERER_MAX_ISM_INPUTS][RENDERER_MAX_CLI_ARG_LENGTH]; + int16_t numInMetadataFiles; + char headRotationFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; + char referenceVectorFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; + char referenceRotationFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; + char customHrtfFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; + char renderConfigFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; + int8_t orientationTracking; + float noDiegeticPan; + bool delayCompensationEnabled; + bool quietModeEnabled; + bool sceneDescriptionInput; + float inputGainGlobal; /* Linear gain (not in dB) */ + bool lfePanningEnabled; + float lfeConfigGain; /* Linear gain (not in dB) */ + float lfeConfigAzimuth; + float lfeConfigElevation; + bool lfeCustomRoutingEnabled; + char inLfePanningMatrixFile[RENDERER_MAX_CLI_ARG_LENGTH]; +} CmdlnArgs; + +typedef enum +{ + CmdLnOptionId_inputFile = 1, + CmdLnOptionId_inputFormat, + CmdLnOptionId_outputFile, + CmdLnOptionId_outputFormat, + CmdLnOptionId_sampleRate, + CmdLnOptionId_trajFile, + CmdLnOptionId_refRotFile, + CmdLnOptionId_customHrtfFile, + CmdLnOptionId_renderConfigFile, + CmdLnOptionId_noDiegeticPan, + CmdLnOptionId_orientationTracking, + CmdlnOptionId_lfePosition, + CmdlnOptionId_lfeMatrix, + CmdLnOptionId_noDelayCmp, + CmdLnOptionId_quietModeEnabled, + CmdLnOptionId_inputMetadata, + CmdLnOptionId_listFormats, + CmdLnOptionId_inputGain, + CmdLnOptionId_referenceVectorFile, +} CmdLnOptionId; + +static const CmdLnParser_Option cliOptions[] = { + { + .id = CmdLnOptionId_inputFile, + .match = "input_file", + .matchShort = "i", + .description = "Path to the input file (WAV, raw PCM or scene description file)", + }, + { + .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)", + }, + { + .id = CmdLnOptionId_inputMetadata, + .match = "input_metadata", + .matchShort = "im", + .description = "Space-separated list of path to metadata files for ISM or MASA inputs", + }, + { + .id = CmdLnOptionId_outputFile, + .match = "output_file", + .matchShort = "o", + .description = "Path to the output file", + }, + { + .id = CmdLnOptionId_outputFormat, + .match = "output_format", + .matchShort = "of", + .description = "Output format to render.\nAlternatively, can be a custom loudspeaker layout file", + }, + { + .id = CmdLnOptionId_sampleRate, + .match = "sample_rate", + .matchShort = "fs", + .description = "Input sampling rate in kHz (16, 32, 48) - required only with raw PCM inputs", /* TODO(sgi): Add sampling rate to scene description files */ + }, + { + .id = CmdLnOptionId_trajFile, + .match = "trajectory_file", + .matchShort = "tf", + .description = "Head rotation trajectory file for simulation of head tracking (only for BINAURAL and BINAURAL_ROOM outputs)", + }, + { + .id = CmdLnOptionId_refRotFile, + .match = "reference_rotation_file", + .matchShort = "rf", + .description = "Reference rotation trajectory file for simulation of head tracking (only for BINAURAL and BINAURAL_ROOM outputs)", + }, + { + .id = CmdLnOptionId_customHrtfFile, + .match = "custom_hrtf", + .matchShort = "hrtf", + .description = "Custom HRTF file for binaural rendering (only for BINAURAL and BINAURAL_ROOM outputs)", + }, + { + .id = CmdLnOptionId_renderConfigFile, + .match = "render_config", + .matchShort = "rc", + .description = "Binaural renderer configuration file (only for BINAURAL and BINAURAL_ROOM outputs)", + }, + { + .id = CmdLnOptionId_noDiegeticPan, + .match = "no_diegetic_pan", + .matchShort = "ndp", + .description = "Panning mono no diegetic sound to stereo -1<= pan <= 1\nleft or l or 1->left, right or r or -1->right, center or c or 0 ->middle\n(todo: implementation)", + }, + { + .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 and BINAURAL_ROOM)", + }, + { + .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)", + }, + { .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)" }, + { + .id = CmdLnOptionId_noDelayCmp, + .match = "no_delay_cmp", + .matchShort = "ndc", + .description = "[flag] Turn off delay compensation", + }, + { + .id = CmdLnOptionId_quietModeEnabled, + .match = "quiet", + .matchShort = "q", + .description = "[flag] Limit printouts to terminal", + }, + { + .id = CmdLnOptionId_inputGain, + .match = "gain", + .matchShort = "g", + .description = "Input gain (linear, not in dB) to be applied to input audio file", + }, + { + .id = CmdLnOptionId_listFormats, + .match = "list", + .matchShort = "l", + .description = "List supported audio formats", + }, + { + .id = CmdLnOptionId_referenceVectorFile, + .match = "reference_vector_file", + .matchShort = "rvf", + .description = "Reference vector trajectory file for simulation of head tracking (only for BINAURAL and BINAURAL_ROOM outputs)", + }, +}; + + +/*------------------------------------------------------------------------------------------* + * Local function prototypes + *------------------------------------------------------------------------------------------*/ + +static const int32_t numCliOptions = sizeof( cliOptions ) / sizeof( CmdLnParser_Option ); + +static IVAS_REND_AudioConfig ambisonicsOrderToEnum( const int16_t order ); + +static void parseSceneDescriptionFile( char *path, char *audioFilePath, InputConfig *inConfig, IsmPositionProvider *positionProvider, MasaFileReader **masaReaders ); + +static ivas_error parseCustomLayoutFile( const char *filePath, IVAS_CUSTOM_LS_DATA *pLsSetupCustom ); + +static CmdlnArgs parseCmdlnArgs( const int argc, char **argv ); + +static IsmPositionProvider *IsmPositionProvider_open( void ); + +static void IsmPositionProvider_getNextFrame( IsmPositionProvider *positionProvider, ObjectPositionBuffer *objectMetadataBuffer ); + +static void IsmPositionProvider_close( IsmPositionProvider *positionProvider ); + +static void readFromShorthandMetadata( IsmPositionProvider *positionProvider, ObjectPositionBuffer *objectMetadataBuffer, const uint32_t objIdx ); + +void getMetadataFromFileReader( IsmFileReader *ismReader, ObjectPositionBuffer *objectMetadataBuffer, const uint32_t objIdx ); + +static void splitConfigFile( const char *mdfFilePath, char *metadataString, uint32_t *metadataStringLength, char *wavFileName, uint32_t *wavFileNameLength ); + +static char *readNextMetadataChunk( char *line, const char *delimiter ); + +static void parseUint8( const char *line, uint8_t *ret ); + +static void parseUint16( const char *line, uint16_t *ret ); + +static int8_t parseUint32( const char *line, uint32_t *ret ); + +static int8_t parseInt32( const char *line, int32_t *ret ); + +static void parseObjectPosition( char *line, IVAS_REND_AudioObjectPosition *position, uint16_t *positionDuration ); + +static void parseMetadata( char *metadataString, char *inDir, InputConfig *inConfig, IsmPositionProvider *positionProvider, MasaFileReader **masaReaders ); + +static ivas_error parseLfePanMtxFile( const char *lfeRoutingMatrixFilePath, IVAS_REND_LfePanMtx *lfePanMtx ); + +static void printSupportedAudioConfigs( void ); + +static IVAS_REND_AudioConfig parseAudioConfig( const char *configString ); + +static void convertInputBuffer( const int16_t *intBuffer, const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, float *floatBuffer ); + +static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, int16_t *intBuffer ); + + +/*------------------------------------------------------------------------------------------* + * Local functions + *------------------------------------------------------------------------------------------*/ + +static IVAS_REND_ReadOnlyAudioBuffer getReadOnlySubBuffer( + IVAS_REND_AudioBuffer buffer, + const int16_t chBeginIdx, + const int16_t numChannels ) +{ + IVAS_REND_ReadOnlyAudioBuffer subBuffer; + + subBuffer.config = buffer.config; + subBuffer.config.numChannels = numChannels; + subBuffer.data = buffer.data + subBuffer.config.numSamplesPerChannel * chBeginIdx; + + return subBuffer; +} + + +static int16_t getTotalNumInChannels( + IVAS_REND_HANDLE hIvasRend, + IVAS_REND_InputId mcIds[RENDERER_MAX_MC_INPUTS], + IVAS_REND_InputId ismIds[RENDERER_MAX_ISM_INPUTS], + IVAS_REND_InputId sbaIds[RENDERER_MAX_SBA_INPUTS], + IVAS_REND_InputId masaIds[RENDERER_MAX_MASA_INPUTS] ) +{ + int16_t totalNumInChannels = 0; + int16_t i, numInputChannels; + ivas_error error; + + for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) + { + if ( mcIds[i] == 0 ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, mcIds[i], &numInputChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + totalNumInChannels += numInputChannels; + } + + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + if ( ismIds[i] == 0 ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, ismIds[i], &numInputChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + totalNumInChannels += numInputChannels; + } + + for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i ) + { + if ( sbaIds[i] == 0 ) + { + /* Skip inactive inputs */ + continue; + } + + + if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, sbaIds[i], &numInputChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + totalNumInChannels += numInputChannels; + } + + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) + { + if ( masaIds[i] == 0 ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, masaIds[i], &numInputChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + totalNumInChannels += numInputChannels; + } + + return totalNumInChannels; +} + + +static void setupWithSingleFormatInput( + CmdlnArgs args, + char *audioFilePath, + IsmPositionProvider *positionProvider, + MasaFileReader **masaReaders ) +{ + /* With single-format input, inputFilePath is the path to input audio file. */ + strncpy( audioFilePath, args.inputFilePath, FILENAME_MAX - 1 ); + + /* Depending on input format, prepare metadata reading for ISM or MASA */ + if ( args.inConfig.numMasaBuses != 0 ) + { + if ( args.inConfig.numMasaBuses != args.numInMetadataFiles ) + { + fprintf( stderr, "Error: all MASA inputs must have a corresponding metadata file" ); + exit( -1 ); + } + + for ( int32_t i = 0; i < args.numInMetadataFiles; ++i ) + { + masaReaders[i] = MasaFileReader_open( args.inMetadataFilePaths[i] ); + if ( masaReaders[i] == NULL ) + { + fprintf( stderr, "Could not open MASA metadata file %s\n", args.inMetadataFilePaths[i] ); + exit( -1 ); + } + } + } + else if ( args.inConfig.numAudioObjects != 0 ) + { + 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" */ + 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 ) + { + continue; + } + + positionProvider->ismReaders[i] = IsmFileReader_open( args.inMetadataFilePaths[i] ); + if ( positionProvider->ismReaders[i] == NULL ) + { + fprintf( stderr, "Could not open object metadata file %s\n", args.inMetadataFilePaths[i] ); + exit( -1 ); + } + } + } +} + + +static float dBToLin( + const float gain_dB ) +{ + return powf( 10.0f, gain_dB / 20.0f ); +} + + +/*------------------------------------------------------------------------------------------* + * main() + * + * Main External renderer function for command-line interface + *------------------------------------------------------------------------------------------*/ + +int main( + int argc, + char **argv ) +{ + IVAS_REND_HANDLE hIvasRend; + HeadRotFileReader *headRotReader = NULL; + Vector3PairFileReader *referenceVectorReader = NULL; + HeadRotFileReader *referenceRotReader = NULL; + hrtfFileReader *hrtfFileReader = NULL; + IsmPositionProvider *positionProvider; + RenderConfigReader *renderConfigReader = NULL; + MasaFileReader *masaReaders[RENDERER_MAX_MASA_INPUTS]; + IVAS_MASA_METADATA_HANDLE hMasaMetadata[RENDERER_MAX_MASA_INPUTS]; + char audioFilePath[FILENAME_MAX]; + AudioFileReader *audioReader = NULL; + AudioFileWriter *audioWriter; + int32_t inBufferSize; + int32_t outBufferSize; + int16_t *inpInt16Buffer; + float *inFloatBuffer; + int16_t *outInt16Buffer; + float *outFloatBuffer; + IVAS_REND_AudioBuffer inBuffer; + IVAS_REND_AudioBuffer outBuffer; + int16_t numSamplesRead; + int16_t delayNumSamples = -1; + int16_t delayNumSamples_orig = 0; + int16_t zeroPad = 0; + int32_t delayTimeScale = 0; + int16_t i, numChannels; + ivas_error error = IVAS_ERR_OK; + IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME]; + +#ifdef WMOPS + reset_wmops(); + reset_mem( USE_32BITS ); +#endif + + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) + { + masaReaders[i] = NULL; + hMasaMetadata[i] = NULL; + } + + CmdlnArgs args = parseCmdlnArgs( argc, argv ); + + positionProvider = IsmPositionProvider_open(); + + convert_backslash( args.inputFilePath ); + convert_backslash( args.outputFilePath ); + convert_backslash( args.headRotationFilePath ); + convert_backslash( args.referenceVectorFilePath ); + convert_backslash( args.referenceRotationFilePath ); + convert_backslash( args.inLfePanningMatrixFile ); + + if ( !isEmptyString( args.headRotationFilePath ) ) + { + if ( HeadRotationFileReader_open( args.headRotationFilePath, &headRotReader ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", args.headRotationFilePath ); + exit( -1 ); + } + } + + if ( !isEmptyString( args.referenceRotationFilePath ) ) + { + if ( HeadRotationFileReader_open( args.referenceRotationFilePath, &referenceRotReader ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", args.referenceRotationFilePath ); + exit( -1 ); + } + } + if ( !isEmptyString( args.referenceVectorFilePath ) ) + { + if ( Vector3PairFileReader_open( args.referenceVectorFilePath, &referenceVectorReader ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", args.referenceVectorFilePath ); + exit( -1 ); + } + } + + if ( !isEmptyString( args.customHrtfFilePath ) ) + { + if ( hrtfFileReader_open( args.customHrtfFilePath, &hrtfFileReader ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", args.customHrtfFilePath ); + exit( -1 ); + } + } + + if ( !isEmptyString( args.renderConfigFilePath ) ) + { + if ( RenderConfigReader_open( args.renderConfigFilePath, &renderConfigReader ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", args.renderConfigFilePath ); + exit( -1 ); + } + } + + /* Initialize main input files, i.e. audio and metadata */ + if ( args.sceneDescriptionInput ) + { + /* With scene description input, inputFilePath is the path to the scene description file. Parse it. */ + parseSceneDescriptionFile( args.inputFilePath, audioFilePath, &args.inConfig, positionProvider, masaReaders ); + } + else + { + /* With single-format input, all information is given on command line. */ + setupWithSingleFormatInput( args, audioFilePath, positionProvider, masaReaders ); + } + + if ( AudioFileReader_open( &audioReader, audioFilePath ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", audioFilePath ); + exit( -1 ); + } + + int32_t inFileSampleRate = 0; + error = AudioFileReader_getSamplingRate( audioReader, &inFileSampleRate ); + switch ( error ) + { + case IVAS_ERR_OK: + /* If sampling rate not given on command line, use the one from wav file */ + if ( args.sampleRate == 0 ) + { + args.sampleRate = inFileSampleRate; + } + /* 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 ); + } + 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 ); + } +#ifndef FIX_389_EXT_REND_PCM_SR + args.sampleRate = inFileSampleRate; +#endif + break; + default: + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + 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 ); + } + const int16_t frameSize_smpls = (int16_t) ( 20 * args.sampleRate / 1000 ); + + IVAS_REND_InputId mcIds[RENDERER_MAX_MC_INPUTS] = { 0 }; + IVAS_REND_InputId ismIds[RENDERER_MAX_ISM_INPUTS] = { 0 }; + IVAS_REND_InputId sbaIds[RENDERER_MAX_SBA_INPUTS] = { 0 }; + IVAS_REND_InputId masaIds[RENDERER_MAX_MASA_INPUTS] = { 0 }; + + if ( ( error = IVAS_REND_Open( &hIvasRend, args.sampleRate, args.outConfig.audioConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening renderer handle: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + /* === Configure === */ +#ifdef FIX_392_LATE_REVERB + if ( ( error = IVAS_REND_InitConfig( hIvasRend, args.outConfig.audioConfig ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_REND_InitConfig( hIvasRend, ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) || ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL ) ) ) != IVAS_ERR_OK ) +#endif + { + fprintf( stderr, "Error in Renderer Config Init\n" ); + exit( -1 ); + } + + if ( args.renderConfigFilePath[0] != '\0' ) + { + IVAS_RENDER_CONFIG_DATA renderConfig; + + /* sanity check */ + if ( ( args.outConfig.audioConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) && ( args.outConfig.audioConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL ) ) + { + fprintf( stderr, "\nExternal Renderer Config is supported only when BINAURAL or BINAURAL_ROOM is used as output. Exiting. \n" ); + exit( -1 ); + } + + if ( ( error = IVAS_REND_GetRenderConfig( hIvasRend, &renderConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed\n" ); + exit( -1 ); + } + + if ( RenderConfigReader_read( renderConfigReader, &renderConfig ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to read renderer configuration from file %s\n", args.renderConfigFilePath ); + exit( -1 ); + } + + if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed\n" ); + exit( -1 ); + } + } + + if ( ( error = IVAS_REND_SetOrientationTrackingMode( hIvasRend, args.orientationTracking ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Set up output custom layout configuration */ + if ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = IVAS_REND_ConfigureCustomOutputLoudspeakerLayout( hIvasRend, args.outConfig.outSetupCustom ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + IVAS_REND_LfePanMtx lfePanMatrix; + + /* parse input LFE panning matrix */ + if ( args.lfeCustomRoutingEnabled && !isEmptyString( args.inLfePanningMatrixFile ) ) + { + /* TODO tmu: how should we handle this on CLI for multiple MC inputs? */ + if ( ( error = parseLfePanMtxFile( args.inLfePanningMatrixFile, &lfePanMatrix ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + for ( i = 0; i < args.inConfig.numMultiChannelBuses; ++i ) + { + 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 ); + } + + 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 ); + } + + /* TODO(sgi): Command line only supports one custom LS input for now, extend */ + if ( args.inConfig.multiChannelBuses[i].audioConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = IVAS_REND_ConfigureCustomInputLoudspeakerLayout( hIvasRend, mcIds[i], args.inConfig.inSetupCustom ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* set panning matrix for input LFE */ + if ( args.lfeCustomRoutingEnabled ) + { + if ( args.lfePanningEnabled ) + { + fprintf( stdout, "Warning 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 ); + } + } + /* set panning gains for input LFE */ + else if ( args.lfePanningEnabled ) + { + 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 ); + } + } + } + + for ( i = 0; i < args.inConfig.numAudioObjects; ++i ) + { + if ( ( error = IVAS_REND_AddInput( hIvasRend, IVAS_REND_AUDIO_CONFIG_OBJECT, &ismIds[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + 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 ); + } + } + + for ( i = 0; i < args.inConfig.numAmbisonicsBuses; ++i ) + { + 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 ); + } + + 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 ); + } + } + + for ( i = 0; i < args.inConfig.numMasaBuses; ++i ) + { + 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 ); + } + + 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 ); + } + } + + const int16_t totalNumInChannels = getTotalNumInChannels( hIvasRend, mcIds, ismIds, sbaIds, masaIds ); + + 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 ); + } + + for ( i = 0; i < args.inConfig.numMasaBuses; ++i ) + { + if ( masaReaders[i] != NULL ) + { + hMasaMetadata[i] = MasaFileReader_getMetadataHandle( masaReaders[i] ); + } + } + + int16_t numOutChannels; + if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); + exit( -1 ); + } + + inBufferSize = frameSize_smpls * totalNumInChannels; + outBufferSize = frameSize_smpls * numOutChannels; + inpInt16Buffer = malloc( inBufferSize * sizeof( int16_t ) ); + inFloatBuffer = malloc( inBufferSize * sizeof( float ) ); + outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); + outFloatBuffer = malloc( outBufferSize * sizeof( float ) ); + + inBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + inBuffer.config.numChannels = (int16_t) totalNumInChannels; + inBuffer.data = inFloatBuffer; + + outBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + outBuffer.config.numChannels = (int16_t) numOutChannels; + outBuffer.data = outFloatBuffer; + +#ifdef WMOPS + reset_stack(); + reset_wmops(); +#endif + + if ( !args.quietModeEnabled ) + { + fprintf( stdout, "\n------ Running the renderer ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else + { + fprintf( stdout, "\n\n-- Start the renderer (quiet mode) --\n\n" ); + } + + while ( 1 ) + { + int16_t num_in_channels; + num_in_channels = inBuffer.config.numChannels; + + /* Read the input data */ + if ( ( error = AudioFileReader_read( audioReader, inpInt16Buffer, (int16_t) inBufferSize, &numSamplesRead ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError reading from file %s\n", audioFilePath ); + exit( -1 ); + } + + if ( numSamplesRead == 0 ) + { + /* end of input data */ + break; + } + + /* Convert from int to float and from interleaved to packed */ + convertInputBuffer( inpInt16Buffer, numSamplesRead, frameSize_smpls, num_in_channels, inFloatBuffer ); + + + ObjectPositionBuffer mtdBuffer; + IsmPositionProvider_getNextFrame( positionProvider, &mtdBuffer ); + + if ( referenceVectorReader != NULL ) + { + 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 ); + } + if ( ( error = IVAS_REND_SetReferenceVector( hIvasRend, listenerPos, refPos ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + /* Read from reference rotation trajectory file if specified */ + if ( referenceRotReader != NULL ) + { + IVAS_QUATERNION quaternion; + if ( ( error = HeadRotationFileReading( referenceRotReader, &quaternion, NULL ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + if ( ( error = IVAS_REND_SetReferenceRotation( hIvasRend, quaternion ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error setting Reference Rotation: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + /* Read from head rotation trajectory file if specified */ + if ( headRotReader != NULL ) + { + IVAS_QUATERNION quatBuffer[RENDERER_HEAD_POSITIONS_PER_FRAME]; + + for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; i++ ) + { + if ( ( error = HeadRotationFileReading( headRotReader, &quatBuffer[i], &Pos[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + if ( ( error = IVAS_REND_SetHeadRotation( hIvasRend, quatBuffer, Pos ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error setting Head Rotation: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + else + { +#ifdef FIX_379_EXT_METADATA + error = IVAS_REND_SetHeadRotation( hIvasRend, NULL, NULL ); + if ( ( error != IVAS_ERR_OK ) && ( error != IVAS_ERR_INVALID_OUTPUT_FORMAT ) ) // VE: TBC +#else + if ( ( ( error = IVAS_REND_SetHeadRotation( hIvasRend, NULL, NULL ) ) != IVAS_ERR_OK ) && ( IVAS_REND_SetHeadRotation( hIvasRend, NULL, NULL ) != IVAS_ERR_INVALID_OUTPUT_FORMAT ) ) // VE: TBC +#endif + { + fprintf( stderr, "Error setting Head Rotation: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + 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 ); + } + 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 ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + for ( i = 0; i < args.inConfig.numAudioObjects; ++i ) + { + 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 ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + 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 ); + } + } + + for ( i = 0; i < args.inConfig.numAmbisonicsBuses; ++i ) + { + if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, sbaIds[i], &numChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + 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 ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + for ( i = 0; i < args.inConfig.numMasaBuses; ++i ) + { + if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, masaIds[i], &numChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + 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 ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + if ( masaReaders[i] != NULL ) + { + /* This will update data in hMasaMetadata[i] */ + MasaFileReader_readNextFrame( masaReaders[i] ); + + 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 ); + } + } + } + + if ( IVAS_REND_GetSamples( hIvasRend, outBuffer ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in getting samples\n" ); + exit( -1 ); + } + + int16_t num_out_channels; + num_out_channels = outBuffer.config.numChannels; + + /* Convert from float to int and from packed to interleaved. + * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ + convertOutputBuffer( outFloatBuffer, frameSize_smpls, num_out_channels, outInt16Buffer ); + + if ( delayNumSamples == -1 ) + { + if ( args.delayCompensationEnabled ) + { + if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples, &delayTimeScale ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to get delay of renderer!\n" ); + exit( -1 ); + } + delayNumSamples_orig = delayNumSamples; + } + else + { + delayNumSamples = 0; + } + zeroPad = delayNumSamples; + } + + if ( delayNumSamples < 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 ); + } + delayNumSamples = 0; + } + else + { + delayNumSamples -= (int16_t) outBufferSize; + } + + frame++; + if ( !args.quietModeEnabled ) + { + fprintf( stdout, "%-8d\b\b\b\b\b\b\b\b", frame ); + } + +#ifdef WMOPS + update_mem(); + update_wmops(); +#endif + } + + /* add zeros at the end to have equal length of synthesized signals */ + memset( outInt16Buffer, 0, zeroPad * outBuffer.config.numChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPad * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + exit( -1 ); + } + + if ( !args.quietModeEnabled && args.delayCompensationEnabled ) + { + fprintf( stdout, "\nRenderer delay: %-5u [samples] - Timescale: %5u\n", delayNumSamples_orig, delayTimeScale ); + } + + fprintf( stdout, "\n\nRendering of %d frames finished\n\n", frame ); + +#ifdef DEBUGGING + int32_t cnt_frames_limited, noClipping; + if ( ( cnt_frames_limited = IVAS_REND_GetCntFramesLimited( hIvasRend ) ) > 0 ) + { + fprintf( stdout, "Limiter applied in %d frames.\n\n", cnt_frames_limited ); + } + if ( ( noClipping = IVAS_REND_GetNoCLipping( hIvasRend ) ) > 0 ) + { + fprintf( stdout, "Clipping (saturation) detected: %d samples clipped!!!\n\n", noClipping ); + } +#endif + + /* === Close === */ + free( inpInt16Buffer ); + free( inFloatBuffer ); + free( outInt16Buffer ); + free( outFloatBuffer ); + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) + { + MasaFileReader_close( &masaReaders[i] ); + } + AudioFileReader_close( &audioReader ); + AudioFileWriter_close( &audioWriter ); + HeadRotationFileReader_close( &headRotReader ); + Vector3PairFileReader_close( &referenceVectorReader ); + HeadRotationFileReader_close( &referenceRotReader ); + hrtfFileReader_close( &hrtfFileReader ); + IVAS_REND_Close( &hIvasRend ); + IsmPositionProvider_close( positionProvider ); + RenderConfigReader_close( &renderConfigReader ); + +#ifdef WMOPS + print_wmops(); + print_mem( NULL ); +#endif + + return 0; +} + + +/*------------------------------------------------------------------------------------------* + * Local functions + *------------------------------------------------------------------------------------------*/ + +static IVAS_REND_AudioConfig ambisonicsOrderToEnum( + const int16_t order ) +{ + switch ( order ) + { + case 1: + return IVAS_REND_AUDIO_CONFIG_FOA; + case 2: + return IVAS_REND_AUDIO_CONFIG_HOA2; + case 3: + return IVAS_REND_AUDIO_CONFIG_HOA3; + } + + return IVAS_REND_AUDIO_CONFIG_UNKNOWN; +} + +static const CmdLnParser_Option *findOptionById( + const int32_t id ) +{ + for ( int32_t i = 0; i < numCliOptions; ++i ) + { + if ( cliOptions[i].id == id ) + { + return &cliOptions[i]; + } + } + + return NULL; +} + +static bool parseInConfig( + const char *inFormatStr, + InputConfig *inConfig, + bool *sceneDescriptionInput ) +{ + char charBuf[FILENAME_MAX]; + + /* Initialize input config struct */ + inConfig->numAudioObjects = 0; + inConfig->numAmbisonicsBuses = 0; + inConfig->numMultiChannelBuses = 0; + inConfig->numMasaBuses = 0; + + /* First check if input is being set to scene description file - this is not covered by parseAudioConfig(). */ + strncpy( charBuf, inFormatStr, sizeof( charBuf ) - 1 ); + charBuf[sizeof( charBuf ) - 1] = '\0'; + to_upper( charBuf ); + if ( strcmp( charBuf, "META" ) == 0 ) + { + *sceneDescriptionInput = true; + /* Parsing the file will be done later. At this point the actual file path + * may not be known as command line parameters are still being parsed. */ + return true; + } + + /* Check for single-format inputs. The given string should map to a member of IVAS_REND_AudioConfig enum. */ + IVAS_REND_AudioConfig audioConfig = parseAudioConfig( inFormatStr ); + switch ( audioConfig ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + case IVAS_REND_AUDIO_CONFIG_STEREO: + case IVAS_REND_AUDIO_CONFIG_5_1: + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_5_1_4: + case IVAS_REND_AUDIO_CONFIG_7_1_4: + inConfig->numMultiChannelBuses = 1; + inConfig->multiChannelBuses[0].audioConfig = audioConfig; + inConfig->multiChannelBuses[0].inputChannelIndex = 0; + inConfig->multiChannelBuses[0].gain_dB = 0.0f; + break; + case IVAS_REND_AUDIO_CONFIG_FOA: + case IVAS_REND_AUDIO_CONFIG_HOA2: + case IVAS_REND_AUDIO_CONFIG_HOA3: + inConfig->numAmbisonicsBuses = 1; + inConfig->ambisonicsBuses[0].audioConfig = audioConfig; + inConfig->ambisonicsBuses[0].inputChannelIndex = 0; + inConfig->ambisonicsBuses[0].gain_dB = 0.0f; + break; + case IVAS_REND_AUDIO_CONFIG_MASA1: + case IVAS_REND_AUDIO_CONFIG_MASA2: + inConfig->numMasaBuses = 1; + inConfig->masaBuses[0].audioConfig = audioConfig; + inConfig->masaBuses[0].inputChannelIndex = 0; + inConfig->masaBuses[0].gain_dB = 0.0f; + break; + case IVAS_REND_AUDIO_CONFIG_OBJECT: + /* If input format is objects, parse the characters after "ISM" to get number of objects */ + { + char *ptr = NULL; + inConfig->numAudioObjects = (uint16_t) strtol( inFormatStr + 3, &ptr, 10 ); + if ( ptr == NULL || *ptr != '\0' ) + { + /* Failed to parse string as a number */ + fprintf( stderr, "Cannot parse string \"%s\" as a valid input format", inFormatStr ); + return false; + } + if ( inConfig->numAudioObjects > RENDERER_MAX_ISM_INPUTS ) + { + fprintf( stderr, "Too many objects at input. Max %d supported.", RENDERER_MAX_ISM_INPUTS ); + return false; + } + for ( int16_t i = 0; i < inConfig->numAudioObjects; ++i ) + { + inConfig->audioObjects[i].audioConfig = audioConfig; + inConfig->audioObjects[i].inputChannelIndex = i; + inConfig->audioObjects[i].gain_dB = 0.0f; + } + } + break; + case IVAS_REND_AUDIO_CONFIG_UNKNOWN: + /* This case will be reached if parsing string to IVAS_REND_AudioConfig enum fails. + * Try to use the given string as a path to a custom loudspeaker layout file. */ + { + ivas_error error = parseCustomLayoutFile( inFormatStr, &inConfig->inSetupCustom ); + + if ( error == IVAS_ERR_FAILED_FILE_OPEN ) + { + /* Failed to open with given string - most likely wasn't a file path */ + const CmdLnParser_Option *listOption = findOptionById( CmdLnOptionId_listFormats ); + fprintf( stderr, "Unsupported input format: %s. To list valid formats, use option --%s.\n", inFormatStr, listOption->match ); + return false; + } + if ( error != IVAS_ERR_OK ) + { + fprintf( stderr, "Error while reading custom loudspeaker layout file %s\n", inFormatStr ); + return false; + } + inConfig->numMultiChannelBuses = 1; + inConfig->multiChannelBuses[0].audioConfig = IVAS_REND_AUDIO_CONFIG_LS_CUSTOM; + inConfig->multiChannelBuses[0].inputChannelIndex = 0; + inConfig->multiChannelBuses[0].gain_dB = 0.0f; + } + break; + default: + { + /* Default case covers formats that are defined in the IVAS_REND_AudioConfig enum, + * but cannot be used at input, e.g. BINAURAL */ + const CmdLnParser_Option *listOption = findOptionById( CmdLnOptionId_listFormats ); + fprintf( stderr, "Unsupported input format: %s. To list valid formats, use option --%s.\n", inFormatStr, listOption->match ); + return false; + } + } + + return true; +} + +static bool parseOutConfig( + const char *outputFormatStr, + OutputConfig *outConfig ) +{ + ivas_error error; + + outConfig->audioConfig = parseAudioConfig( outputFormatStr ); + /* If the string provided is not recognized as a valid output config, + * it's expected to be a path to a custom loudspeaker layout description file. */ + if ( outConfig->audioConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + outConfig->audioConfig = IVAS_REND_AUDIO_CONFIG_LS_CUSTOM; + if ( ( error = parseCustomLayoutFile( outputFormatStr, &outConfig->outSetupCustom ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error while parsing output format option\n" ); + return false; + } + } + + return true; +} + +static bool parseDiegeticPan( + char *value, + float *noDiegeticPan ) +{ + to_upper( value ); + + if ( ( strcmp( value, "CENTER" ) == 0 ) || ( strchr( value, 'C' ) != NULL ) ) + { + *noDiegeticPan = 0.f; + } + else if ( ( strcmp( value, "LEFT" ) == 0 ) || ( strchr( value, 'L' ) != NULL ) ) + { + *noDiegeticPan = -1.f; + } + else if ( ( strcmp( value, "RIGHT" ) == 0 ) || ( strchr( value, 'R' ) != NULL ) ) + { + *noDiegeticPan = 1.f; + } + else + { + *noDiegeticPan = (float) atof( value ); + + if ( *noDiegeticPan > 1.0f || *noDiegeticPan < -1.0f ) + { + fprintf( stderr, "Error: Incorrect value for panning option argument specified!\n\n" ); + return false; + } + } + return false; +} + +static bool parseOrientationTracking( + char *value, + int8_t *tracking_type ) +{ + + to_upper( value ); + + if ( strcmp( value, "NONE" ) == 0 ) + { + *tracking_type = IVAS_ORIENT_TRK_NONE; + } + else if ( strcmp( value, "REF" ) == 0 ) + { + *tracking_type = IVAS_ORIENT_TRK_REF; + } + else if ( strcmp( value, "AVG" ) == 0 ) + { + *tracking_type = IVAS_ORIENT_TRK_AVG; + } + else if ( strcmp( value, "REF_VEC" ) == 0 ) + { + *tracking_type = IVAS_ORIENT_TRK_REF_VEC; + } + else if ( strcmp( value, "REF_VEC_LEV" ) == 0 ) + { + *tracking_type = IVAS_ORIENT_TRK_REF_VEC_LEV; + } + else + { + fprintf( stderr, "Error: Invalid orientation tracking type %s \n\n", value ); + return false; + } + + return true; +} + +static IVAS_REND_AudioConfig parseAudioConfig( + const char *configString ) +{ + char charBuf[14]; + charBuf[13] = '\0'; + + strncpy( charBuf, configString, sizeof( charBuf ) - 1 ); + charBuf[sizeof( charBuf ) - 1] = '\0'; + to_upper( charBuf ); + + if ( ( strcmp( charBuf, "MONO" ) == 0 ) || ( strcmp( charBuf, "HOA0" ) == 0 ) || ( strcmp( charBuf, "SBA0" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_MONO; + } + if ( ( strcmp( charBuf, "STEREO" ) == 0 ) || ( strcmp( charBuf, "CICP2" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_STEREO; + } + if ( ( strcmp( charBuf, "FOA" ) == 0 ) || ( strcmp( charBuf, "SBA1" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_FOA; + } + if ( ( strcmp( charBuf, "HOA2" ) == 0 ) || ( strcmp( charBuf, "SBA2" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_HOA2; + } + if ( ( strcmp( charBuf, "HOA3" ) == 0 ) || ( strcmp( charBuf, "SBA3" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_HOA3; + } + if ( ( strcmp( charBuf, "5_1" ) == 0 ) || ( strcmp( charBuf, "CICP6" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_5_1; + } + if ( ( strcmp( charBuf, "7_1" ) == 0 ) || ( strcmp( charBuf, "CICP12" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_7_1; + } + if ( ( strcmp( charBuf, "5_1_2" ) == 0 ) || ( strcmp( charBuf, "CICP14" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_5_1_2; + } + if ( ( strcmp( charBuf, "5_1_4" ) == 0 ) || ( strcmp( charBuf, "CICP16" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_5_1_4; + } + if ( ( strcmp( charBuf, "7_1_4" ) == 0 ) || ( strcmp( charBuf, "CICP19" ) == 0 ) ) + { + return IVAS_REND_AUDIO_CONFIG_7_1_4; + } + if ( strncmp( charBuf, "ISM", 3 ) == 0 ) + { + /* Accept input config as ISM only if the 4th character is a number from 1 to 4. + * Otherwise, do nothing. Unknown audio config will be returned. */ + switch ( charBuf[3] ) + { + case '1': + case '2': + case '3': + case '4': + return IVAS_REND_AUDIO_CONFIG_OBJECT; + } + } + if ( strncmp( charBuf, "MASA", 4 ) == 0 ) + { + switch ( charBuf[4] ) + { + case '1': + fprintf( stderr, "1TC MASA support is not functional and is pending on DirAC renderer refactoring.\n" ); + exit( EXIT_FAILURE ); + /*return IVAS_REND_AUDIO_CONFIG_MASA1;*/ // ToDo: temporarily disabled to avoid compilation warnings + case '2': + return IVAS_REND_AUDIO_CONFIG_MASA2; + default: + return IVAS_REND_AUDIO_CONFIG_UNKNOWN; + } + } + if ( strcmp( charBuf, "BINAURAL_ROOM" ) == 0 ) + { + return IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM; + } + if ( strcmp( charBuf, "BINAURAL" ) == 0 ) + { + return IVAS_REND_AUDIO_CONFIG_BINAURAL; + } + + return IVAS_REND_AUDIO_CONFIG_UNKNOWN; +} + +static bool parseLfePositionConfig( + const char *value, + float *lfeGain, + float *lfeAzimuth, + float *lfeElevation ) +{ + uint8_t nvalues; + const char *tok; + float values[3]; + char config_string[RENDERER_MAX_METADATA_LINE_LENGTH]; + + strncpy( config_string, value, RENDERER_MAX_METADATA_LINE_LENGTH ); + nvalues = 0; + + for ( tok = strtok( config_string, "," ); tok && *tok; tok = strtok( NULL, ",\n" ) ) + { + while ( *tok == ' ' ) + { + tok++; + } + + if ( *tok == '\0' ) + { + continue; + } + values[nvalues] = (float) atof( tok ); + nvalues++; + + /* ignore any additionally specified values */ + if ( nvalues == 3 ) + { + break; + } + } + + if ( nvalues != 3 ) + { + return false; + } + + *lfeGain = values[0]; + *lfeAzimuth = values[1]; + *lfeElevation = values[2]; + return true; +} + + +static bool checkRequiredArgs( + CmdlnArgs args ) +{ + const CmdLnParser_Option *tmpOption; + + /* Check required arguments */ + bool missingRequiredArg = false; + if ( isEmptyString( args.inputFilePath ) ) + { + tmpOption = findOptionById( CmdLnOptionId_inputFile ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + const bool singleInputSpecified = args.inConfig.numAudioObjects != 0 || + args.inConfig.numAmbisonicsBuses != 0 || + args.inConfig.numMultiChannelBuses != 0 || + args.inConfig.numMasaBuses != 0; + if ( !args.sceneDescriptionInput && !singleInputSpecified ) + { + /* Neither scene description input nor single-type input was specified on command line */ + tmpOption = findOptionById( CmdLnOptionId_inputFormat ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + if ( isEmptyString( args.outputFilePath ) ) + { + tmpOption = findOptionById( CmdLnOptionId_outputFile ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + if ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + tmpOption = findOptionById( CmdLnOptionId_outputFormat ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + if ( missingRequiredArg ) + { + CmdLnParser_printUsage( args.executableName, cliOptions, numCliOptions ); + } + + return !missingRequiredArg; +} + +static CmdlnArgs defaultArgs( + const char *executableName ) +{ + CmdlnArgs args; + + strncpy( args.executableName, executableName, RENDERER_MAX_CLI_ARG_LENGTH ); + clearString( args.inputFilePath ); + clearString( args.outputFilePath ); + args.sampleRate = 0; + + args.inConfig.inSetupCustom.num_spk = 0; + args.inConfig.inSetupCustom.num_lfe = 0; + args.inConfig.numAudioObjects = 0; + args.inConfig.numAmbisonicsBuses = 0; + args.inConfig.numMultiChannelBuses = 0; + args.inConfig.numMasaBuses = 0; + + args.outConfig.audioConfig = IVAS_REND_AUDIO_CONFIG_UNKNOWN; + args.outConfig.outSetupCustom.num_spk = 0; + args.outConfig.outSetupCustom.num_lfe = 0; + + for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + clearString( args.inMetadataFilePaths[i] ); + } + args.numInMetadataFiles = 0; + + clearString( args.headRotationFilePath ); + clearString( args.referenceVectorFilePath ); + clearString( args.referenceRotationFilePath ); + clearString( args.customHrtfFilePath ); + clearString( args.renderConfigFilePath ); + + args.orientationTracking = IVAS_ORIENT_TRK_NONE; + args.noDiegeticPan = 0.0f; + + args.delayCompensationEnabled = true; + args.quietModeEnabled = false; + args.sceneDescriptionInput = false; + args.inputGainGlobal = 1.0f; + + args.lfePanningEnabled = false; + args.lfeConfigGain = 1.0f; + args.lfeConfigAzimuth = 0; + args.lfeConfigElevation = 0; + + args.lfeCustomRoutingEnabled = false; + clearString( args.inLfePanningMatrixFile ); + return args; +} + +static void parseOption( + const int32_t optionId, + char **optionValues, + const int16_t numOptionValues, + void *pOutputStruct ) +{ + CmdlnArgs *args = pOutputStruct; + + switch ( optionId ) + { + case CmdLnOptionId_listFormats: + assert( numOptionValues == 0 ); + printSupportedAudioConfigs(); + exit( 0 ); + case CmdLnOptionId_inputFile: + assert( numOptionValues == 1 ); + strncpy( args->inputFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_inputFormat: + assert( numOptionValues == 1 ); + if ( !parseInConfig( optionValues[0], &args->inConfig, &args->sceneDescriptionInput ) ) + { + exit( -1 ); /* Error printout handled by failing function */ + } + break; + case CmdLnOptionId_inputMetadata: + assert( numOptionValues <= RENDERER_MAX_ISM_INPUTS ); + for ( int16_t i = 0; i < numOptionValues; ++i ) + { + strncpy( args->inMetadataFilePaths[i], optionValues[i], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + } + args->numInMetadataFiles = numOptionValues; + break; + case CmdLnOptionId_outputFile: + assert( numOptionValues == 1 ); + strncpy( args->outputFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_outputFormat: + assert( numOptionValues == 1 ); + if ( !parseOutConfig( optionValues[0], &args->outConfig ) ) + { + exit( -1 ); /* Error printout handled by failing function */ + } + break; + case CmdLnOptionId_sampleRate: + assert( numOptionValues == 1 ); + args->sampleRate = (int32_t) ( strtol( optionValues[0], NULL, 10 ) * 1000 ); + if ( args->sampleRate == 0 ) + { + fprintf( stderr, "Invalid sampling rate specified\n" ); + exit( -1 ); + } + break; + case CmdLnOptionId_trajFile: + assert( numOptionValues == 1 ); + strncpy( args->headRotationFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_referenceVectorFile: + assert( numOptionValues == 1 ); + strncpy( args->referenceVectorFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_refRotFile: + assert( numOptionValues == 1 ); + strncpy( args->referenceRotationFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_customHrtfFile: + assert( numOptionValues == 1 ); + strncpy( args->customHrtfFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_renderConfigFile: + assert( numOptionValues == 1 ); + strncpy( args->renderConfigFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_noDiegeticPan: + assert( numOptionValues == 1 ); + if ( !parseDiegeticPan( optionValues[0], &args->noDiegeticPan ) ) + { + fprintf( stderr, "Unknown option for diegetic panning: %s\n", optionValues[0] ); + exit( -1 ); + } + break; + case CmdLnOptionId_orientationTracking: + assert( numOptionValues == 1 ); + if ( !parseOrientationTracking( optionValues[0], &args->orientationTracking ) ) + { + fprintf( stderr, "Unknown option for orientation tracking: %s\n", optionValues[0] ); + exit( -1 ); + } + break; + case CmdlnOptionId_lfePosition: + assert( numOptionValues == 1 ); + if ( !parseLfePositionConfig( optionValues[0], &args->lfeConfigGain, &args->lfeConfigAzimuth, &args->lfeConfigElevation ) ) + { + fprintf( stderr, "Unknown or invalid option for LFE position: %s\n", optionValues[0] ); + exit( -1 ); + } + args->lfePanningEnabled = true; + break; + break; + case CmdlnOptionId_lfeMatrix: + assert( numOptionValues == 1 ); + strncpy( args->inLfePanningMatrixFile, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + args->lfeCustomRoutingEnabled = true; + break; + case CmdLnOptionId_noDelayCmp: + assert( numOptionValues == 0 ); + args->delayCompensationEnabled = false; + break; + case CmdLnOptionId_quietModeEnabled: + assert( numOptionValues == 0 ); + args->quietModeEnabled = true; + break; + case CmdLnOptionId_inputGain: + assert( numOptionValues == 1 ); + args->inputGainGlobal = strtof( optionValues[0], NULL ); + if ( args->inputGainGlobal == 0.0f ) + { + fprintf( stderr, "Invalid input gain specified\n" ); + exit( -1 ); + } + break; + default: + assert( 0 && "This should be unreachable - all command line options should be explicitly handled." ); + break; + } + + return; +} + +static CmdlnArgs parseCmdlnArgs( + const int argc, + char **argv ) +{ + CmdlnArgs args = defaultArgs( argv[0] ); + + if ( CmdLnParser_parseArgs( argc, argv, cliOptions, numCliOptions, &args, parseOption ) != 0 ) + { + exit( -1 ); /* Error printout handled by failing function */ + } + + if ( !checkRequiredArgs( args ) ) + { + exit( -1 ); /* Error printout handled by failing function */ + } + + return args; +} + + +IsmPositionProvider *IsmPositionProvider_open( + void ) +{ + IsmPositionProvider *ipp; + uint16_t i; + + ipp = (IsmPositionProvider *) malloc_( sizeof( IsmPositionProvider ) ); + ipp->frameCounter = 0; + ipp->numObjects = 0; + + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + ipp->ismReaders[i] = NULL; + ipp->positions[i] = NULL; + ipp->positionDurations[i] = NULL; + ipp->currentPositionIdxs[i] = 0; + ipp->durationCounters[i] = 0; + } + + return ipp; +} + +void getMetadataFromFileReader( + IsmFileReader *ismReader, + ObjectPositionBuffer *objectMetadataBuffer, + const uint32_t objIdx ) +{ + IVAS_ISM_METADATA ismMetadata; + ivas_error error; + + if ( ( error = IsmFileReader_readNextFrame( ismReader, &ismMetadata ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError (%s) while reading ISM metadata from: %s\n\n", ivas_error_to_string( error ), IsmFileReader_getFilePath( ismReader ) ); + exit( -1 ); + } + + objectMetadataBuffer->positions[objIdx].azimuth = ismMetadata.azimuth; + objectMetadataBuffer->positions[objIdx].elevation = ismMetadata.elevation; + objectMetadataBuffer->positions[objIdx].radius = ismMetadata.radius; + objectMetadataBuffer->positions[objIdx].yaw = ismMetadata.yaw; + objectMetadataBuffer->positions[objIdx].pitch = ismMetadata.pitch; + + return; +} + +void readFromShorthandMetadata( + IsmPositionProvider *positionProvider, + ObjectPositionBuffer *objectMetadataBuffer, + const uint32_t objIdx ) +{ + uint32_t preUpdatePositionIdx; + uint32_t postUpdatePositionIdx; + + preUpdatePositionIdx = positionProvider->currentPositionIdxs[objIdx]; + + if ( positionProvider->durationCounters[objIdx] == positionProvider->positionDurations[objIdx][preUpdatePositionIdx] ) + { + positionProvider->durationCounters[objIdx] = 0; + positionProvider->currentPositionIdxs[objIdx] = ( positionProvider->currentPositionIdxs[objIdx] + 1 ) % positionProvider->numPositions[objIdx]; + } + + ++positionProvider->durationCounters[objIdx]; + + postUpdatePositionIdx = positionProvider->currentPositionIdxs[objIdx]; + + objectMetadataBuffer->positions[objIdx] = positionProvider->positions[objIdx][postUpdatePositionIdx]; + + return; +} + +static void IsmPositionProvider_getNextFrame( + IsmPositionProvider *positionProvider, + ObjectPositionBuffer *objectMetadataBuffer ) +{ + uint32_t objIdx; + + objectMetadataBuffer->numObjects = positionProvider->numObjects; + + for ( objIdx = 0; objIdx < positionProvider->numObjects; ++objIdx ) + { + /* If ISM metadata reader is open, read from metadata file */ + if ( positionProvider->ismReaders[objIdx] != NULL ) + { + getMetadataFromFileReader( positionProvider->ismReaders[objIdx], objectMetadataBuffer, objIdx ); + } + /* Otherwise, if positions were provided in a scene description file, use them */ + else if ( positionProvider->positions[objIdx] != NULL ) + { + readFromShorthandMetadata( positionProvider, objectMetadataBuffer, objIdx ); + } + /* Otherwise fall back to default position */ + else + { + objectMetadataBuffer->positions[objIdx].azimuth = 0.0f; + objectMetadataBuffer->positions[objIdx].elevation = 0.0f; + objectMetadataBuffer->positions[objIdx].radius = 1.0f; + objectMetadataBuffer->positions[objIdx].yaw = 0.0f; + objectMetadataBuffer->positions[objIdx].pitch = 0.0f; + } + + /* Wrap azimuth to lie within (-180, 180] range */ + while ( objectMetadataBuffer->positions[objIdx].azimuth < 0.0f ) + { + objectMetadataBuffer->positions[objIdx].azimuth += 360.0f; + } + while ( objectMetadataBuffer->positions[objIdx].azimuth >= 360.0f ) + { + objectMetadataBuffer->positions[objIdx].azimuth -= 360.0f; + } + + /* Clamp elevation to lie within [-90, 90] range (can't be wrapped easily) */ + objectMetadataBuffer->positions[objIdx].elevation = min( max( objectMetadataBuffer->positions[objIdx].elevation, -90 ), 90 ); + /* Wrap yaw to lie within (-180, 180] range */ + while ( objectMetadataBuffer->positions[objIdx].yaw < 0.0f ) + { + objectMetadataBuffer->positions[objIdx].yaw += 360.0f; + } + while ( objectMetadataBuffer->positions[objIdx].yaw >= 360.0f ) + { + objectMetadataBuffer->positions[objIdx].yaw -= 360.0f; + } + + /* Clamp pitch to lie within [-90, 90] range (can't be wrapped easily) */ + objectMetadataBuffer->positions[objIdx].pitch = min( max( objectMetadataBuffer->positions[objIdx].pitch, -90 ), 90 ); + } + + ++positionProvider->frameCounter; + + return; +} + +static void IsmPositionProvider_close( + IsmPositionProvider *positionProvider ) +{ + uint32_t i; + + if ( positionProvider == NULL ) + { + assert( !"Can't close IsmPositionProvider - pointer is NULL" ); + } + + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + if ( positionProvider->ismReaders[i] != NULL ) + { + IsmFileReader_close( &positionProvider->ismReaders[i] ); + } + + if ( positionProvider->positions[i] != NULL ) + { + free( positionProvider->positions[i] ); + } + + if ( positionProvider->positionDurations[i] != NULL ) + { + free( positionProvider->positionDurations[i] ); + } + } + + free( positionProvider ); + + return; +} + +static void splitConfigFile( + const char *mdfFilePath, + char *metadataString, + uint32_t *metadataStringLength, + char *wavFileName, + uint32_t *wavFileNameLength ) +{ + FILE *file; + uint32_t bufferlength; + char wavLine[FILENAME_MAX]; + uint32_t currentPositionIdxs; + uint32_t mdlength; + + memset( metadataString, 0, *metadataStringLength ); + memset( wavFileName, 0, (int16_t) *wavFileNameLength ); + + file = fopen( mdfFilePath, "rb" ); + if ( !file ) + { + fprintf( stderr, "Couldn't open metadata file %s\n", mdfFilePath ); + exit( -1 ); + } + + fseek( file, 0, SEEK_END ); + bufferlength = ftell( file ); + fseek( file, 0, SEEK_SET ); + + if ( fgets( wavLine, (int) *wavFileNameLength, file ) == NULL ) + { + fprintf( stderr, "Error reading metadata\n" ); + exit( -1 ); + } + currentPositionIdxs = ftell( file ); + if ( *wavFileNameLength < currentPositionIdxs ) + { + assert( !"Couldn't read wavFileName, string buffer too small" ); + } + if ( !sscanf( wavLine, "%s", wavFileName ) ) + { + fprintf( stderr, "Error reading metadata\n" ); + exit( -1 ); + } + *wavFileNameLength = (uint32_t) strlen( wavFileName ); + + mdlength = bufferlength - currentPositionIdxs; + /* "+1" for null termination */ + if ( *metadataStringLength + 1 < mdlength ) + { + assert( !"Couldn't read metadata string, string buffer too small" ); + } + + fread( metadataString, 1, mdlength, file ); + metadataString[mdlength] = '\0'; + *metadataStringLength = mdlength + 1; + + fclose( file ); + + return; +} + +/* r: pointer to character following last found delimiter */ +static char *readNextMetadataChunkFrom( + char *start_char, + char *line, + const char *delimiter ) +{ + char *token; + + /* start_char can be NULL - it's used to continue parsing with strtok */ + assert( line != NULL && delimiter != NULL && "unexpected NULL ptr given to readNextMetadataChunkFrom()" ); + + token = strtok( start_char, delimiter ); + + /* End of string reached */ + if ( token == NULL ) + { + /* Clear `line` from previous contents and return NULL */ + clearString( line ); + return NULL; + } + + strcpy( line, token ); + + return token + strlen( token ) + 1; +} + +/* r: pointer to character following last found delimiter */ +static char *readNextMetadataChunk( + char *line, + const char *delimiter ) +{ + return readNextMetadataChunkFrom( NULL, line, delimiter ); +} + +static void parseUint8( + const char *line, + uint8_t *ret ) +{ + char *ptr; + ptr = NULL; + + *ret = (uint8_t) strtol( line, &ptr, 10 ); + if ( ptr == NULL || *ptr != '\0' ) + { + fprintf( stderr, "Cannot parse string \"%s\" as an integer value\n", line ); + exit( -1 ); + } + + return; +} + +static int8_t parseUint32( + const char *line, + uint32_t *ret ) +{ + char *ptr; + ptr = NULL; + + *ret = strtol( line, &ptr, 10 ); + if ( ptr == NULL || *ptr != '\0' ) + { + return -1; + } + + return 0; +} + +static int8_t parseInt32( + const char *line, + int32_t *ret ) +{ + char *ptr; + ptr = NULL; + + *ret = strtol( line, &ptr, 10 ); + if ( ptr == NULL || *ptr != '\0' ) + { + return -1; + } + + return 0; +} + +static void parseOptionalInputValues( + char *line, + float *gain_dB ) +{ + char *parse_pos; + char *key; + char *value; + char *endptr; + + endptr = NULL; + + /* Set default values, in case some values are not specified */ + *gain_dB = 0.f; + + /* Save parsing position - will have to be passed to strtok to resume parsing after using strtok with non-NULL value below */ + parse_pos = readNextMetadataChunk( line, "\n" ); + + /* Look for optional metadata until end of string or next input identifier is found */ + while ( parse_pos != NULL && strcmp( line, "MC" ) != 0 && strcmp( line, "SBA" ) != 0 && strcmp( line, "ISM" ) != 0 && strcmp( line, "MASA" ) != 0 ) + { + key = strtok( line, ":" ); + value = strtok( NULL, "\n" ); + + if ( strcmp( key, "gain_dB" ) == 0 ) + { + *gain_dB = (float) strtod( value, &endptr ); + + if ( *endptr != '\0' ) + { + fprintf( stderr, "Cannot parse string string \"%s\" as a float value\n", value ); + exit( -1 ); + } + } + else + { + fprintf( stderr, "Unsupported optional key: %s\n", key ); + exit( -1 ); + } + + parse_pos = readNextMetadataChunkFrom( parse_pos, line, "\n" ); + } + + return; +} + +static void parseObjectPosition( + char *line, + IVAS_REND_AudioObjectPosition *position, + uint16_t *positionDuration ) +{ + char *endptr; + int16_t read_values; + float meta_prm[7] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + readNextMetadataChunk( line, "," ); + *positionDuration = (uint16_t) strtol( line, &endptr, 10 ); + readNextMetadataChunk( line, "\n" ); + + read_values = (int16_t) sscanf( line, "%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] ); + + if ( read_values < 2 ) + { + fprintf( stderr, "Error reading metadata\n" ); + exit( -1 ); + } + + position->azimuth = meta_prm[0]; + position->elevation = meta_prm[1]; + position->radius = meta_prm[2]; + position->yaw = meta_prm[5]; + position->pitch = meta_prm[6]; + return; +} + +static void parseIsm( + char *line, + char *inDir, + InputConfig *inConfig, + IsmPositionProvider *positionProvider, + const int32_t idx ) +{ + uint32_t numberOfObjectPositionsToRead; + uint32_t i; + + readNextMetadataChunk( line, "\n" ); + parseInt32( line, &inConfig->audioObjects[idx].inputChannelIndex ); + --inConfig->audioObjects[idx].inputChannelIndex; /* Convert from 1-indexing */ + + readNextMetadataChunk( line, "\n" ); + + /* Try to interpret line as number of positions to read */ + if ( parseUint32( line, &numberOfObjectPositionsToRead ) == 0 ) + { + positionProvider->numPositions[idx] = numberOfObjectPositionsToRead; + positionProvider->positions[idx] = malloc_( numberOfObjectPositionsToRead * sizeof( IVAS_REND_AudioObjectPosition ) ); + positionProvider->positionDurations[idx] = malloc_( numberOfObjectPositionsToRead * sizeof( uint16_t ) ); + + for ( i = 0; i < numberOfObjectPositionsToRead; ++i ) + { + parseObjectPosition( line, &positionProvider->positions[idx][i], &positionProvider->positionDurations[idx][i] ); + } + } + else /* If not a number, it is a relative path from main metadata file to a metadata file */ + { + char fullpath[FILENAME_MAX]; + fullpath[0] = '\0'; + strncat( fullpath, inDir, strlen( inDir ) ); + strncat( fullpath, line, sizeof( fullpath ) - strlen( fullpath ) - 1 ); + if ( ( positionProvider->ismReaders[idx] = IsmFileReader_open( fullpath ) ) == NULL ) + { + fprintf( stderr, "Error: ISM input metadata file %s could not be opened\n", fullpath ); + exit( -1 ); + } + } + + /* Read optional values */ + parseOptionalInputValues( line, &inConfig->audioObjects[idx].gain_dB ); + + return; +} + +static void parseSba( + char *line, + InputConfig *inConfig, + const int32_t idx ) +{ + uint8_t ambiOrder; + + readNextMetadataChunk( line, "\n" ); + parseInt32( line, &inConfig->ambisonicsBuses[idx].inputChannelIndex ); + --inConfig->ambisonicsBuses[idx].inputChannelIndex; /* Convert from 1-indexing */ + + readNextMetadataChunk( line, "\n" ); + parseUint8( line, &ambiOrder ); + inConfig->ambisonicsBuses[idx].audioConfig = ambisonicsOrderToEnum( ambiOrder ); + + /* Read optional values */ + parseOptionalInputValues( line, &inConfig->ambisonicsBuses[idx].gain_dB ); + + return; +} + +static void parseMc( + char *line, + InputConfig *inConfig, + const int32_t idx ) +{ + readNextMetadataChunk( line, "\n" ); + parseInt32( line, &inConfig->multiChannelBuses[idx].inputChannelIndex ); + --inConfig->multiChannelBuses[idx].inputChannelIndex; /* Convert from 1-indexing */ + + readNextMetadataChunk( line, "\n" ); + IVAS_REND_AudioConfig cfg = parseAudioConfig( line ); + if ( cfg == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + parseCustomLayoutFile( line, &inConfig->inSetupCustom ); + } + else + { + inConfig->multiChannelBuses[idx].audioConfig = cfg; + } + + /* Read optional values */ + parseOptionalInputValues( line, &inConfig->multiChannelBuses[idx].gain_dB ); + + return; +} + +static void parseMasa( + char *line, + char *inDir, + InputConfig *inConfig, + MasaFileReader **masaReaders, + const int32_t idx ) +{ + readNextMetadataChunk( line, "\n" ); + parseInt32( line, &inConfig->masaBuses[idx].inputChannelIndex ); + --inConfig->masaBuses[idx].inputChannelIndex; /* Convert from 1-indexing */ + + readNextMetadataChunk( line, "\n" ); + + /* Allow both just the number of TCs or MASAx. parseStrToAudioCfg() only accepts MASAx, so prepend if necessary. */ + if ( strncmp( line, "MASA", 4 ) != 0 ) + { + char numTcs = *line; + snprintf( line, 6 /* write at most 6 characters: MASAx + null termination */, "MASA%c", numTcs ); + } + + inConfig->masaBuses[idx].audioConfig = parseAudioConfig( line ); + + readNextMetadataChunk( line, "\n" ); + + char fullpath[FILENAME_MAX]; + fullpath[0] = '\0'; + strncat( fullpath, inDir, strlen( inDir ) ); + strncat( fullpath, line, sizeof( fullpath ) - strlen( fullpath ) - 1 ); + + if ( ( masaReaders[idx] = MasaFileReader_open( fullpath ) ) == NULL ) + { + fprintf( stderr, "Error: MASA metadata file %s could not be opened\n", fullpath ); + exit( -1 ); + } + + /* Read optional values */ + parseOptionalInputValues( line, &inConfig->masaBuses[idx].gain_dB ); + + return; +} + +static ivas_error parseCustomLayoutFile( + const char *filePath, + IVAS_CUSTOM_LS_DATA *pLsSetupCustom ) +{ + LsCustomFileReader *hLsCustomReader = NULL; + IVAS_CUSTOM_LS_DATA hLsCustomData; + ivas_error error; + + if ( ( error = CustomLsReader_open( filePath, &hLsCustomReader ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( CustomLsFileReading( hLsCustomReader, &hLsCustomData ) != LS_CUSTOM_FILEREADER_NO_ERROR ) + { + return error; + } + + pLsSetupCustom->num_spk = hLsCustomData.num_spk; + mvr2r( hLsCustomData.azimuth, pLsSetupCustom->azimuth, hLsCustomData.num_spk ); + mvr2r( hLsCustomData.elevation, pLsSetupCustom->elevation, hLsCustomData.num_spk ); + + /* Loudspeaker LFE */ + pLsSetupCustom->num_lfe = hLsCustomData.num_lfe; + mvs2s( hLsCustomData.lfe_idx, pLsSetupCustom->lfe_idx, hLsCustomData.num_lfe ); + + CustomLsReader_close( &hLsCustomReader ); + + return IVAS_ERR_OK; +} + +static void parseMetadata( + char *metadataString, + char *inDir, + InputConfig *inConfig, + IsmPositionProvider *positionProvider, + MasaFileReader **masaReaders ) +{ + char line[RENDERER_MAX_METADATA_LINE_LENGTH]; + char *delimiter; + char *token; + uint8_t totalNumberOfAudioObjects; + uint8_t counterChannelAudioObjects; + uint8_t counterAmbisonicsAudioObjects; + uint8_t counterMonoAudioObjects; + uint8_t counterMasaInputs; + uint8_t num_parsed_inputs; + + delimiter = "\n"; + + token = strtok( metadataString, delimiter ); + if ( token == NULL ) + { + fprintf( stderr, "Unexpected metadata format\n" ); + exit( -1 ); + } + if ( !sscanf( token, "%s", line ) ) + { + fprintf( stderr, "Unexpected metadata format\n" ); + exit( -1 ); + } + + parseUint8( line, &totalNumberOfAudioObjects ); + if ( totalNumberOfAudioObjects <= 0 ) + { + fprintf( stderr, "Invalid metadata: number of inputs should be > 0\n" ); + exit( -1 ); + } + + num_parsed_inputs = 0; + counterChannelAudioObjects = 0; + counterAmbisonicsAudioObjects = 0; + counterMonoAudioObjects = 0; + counterMasaInputs = 0; + + readNextMetadataChunk( line, delimiter ); + + while ( num_parsed_inputs < totalNumberOfAudioObjects ) + { + /* `line` will already contain the identifier ("MC", "SBA" or "ISM") after previous iteration */ + if ( strcmp( line, "MC" ) == 0 ) + { + ++counterChannelAudioObjects; + if ( counterChannelAudioObjects > RENDERER_MAX_MC_INPUTS ) + { + fprintf( stderr, "Metadata exceeds the supported number of MC inputs\n" ); + exit( -1 ); + } + parseMc( line, inConfig, counterChannelAudioObjects - 1 ); + } + else if ( strcmp( line, "SBA" ) == 0 ) + { + ++counterAmbisonicsAudioObjects; + if ( counterAmbisonicsAudioObjects > RENDERER_MAX_SBA_INPUTS ) + { + fprintf( stderr, "Metadata exceeds the supported number of SBA inputs\n" ); + exit( -1 ); + } + parseSba( line, inConfig, counterAmbisonicsAudioObjects - 1 ); + } + else if ( strcmp( line, "ISM" ) == 0 ) + { + ++counterMonoAudioObjects; + if ( counterMonoAudioObjects > RENDERER_MAX_ISM_INPUTS ) + { + fprintf( stderr, "Metadata exceeds the supported number of ISM inputs\n" ); + exit( -1 ); + } + parseIsm( line, inDir, inConfig, positionProvider, counterMonoAudioObjects - 1 ); + } + else if ( strcmp( line, "MASA" ) == 0 ) + { + ++counterMasaInputs; + if ( counterMasaInputs > RENDERER_MAX_MASA_INPUTS ) + { + fprintf( stderr, "Metadata exceeds the supported number of MASA inputs\n" ); + exit( -1 ); + } + parseMasa( line, inDir, inConfig, masaReaders, counterMasaInputs - 1 ); + } + else if ( isEmptyString( line ) ) + { + fprintf( stderr, "Metadata string too short - expected %d inputs, found %d.\n", totalNumberOfAudioObjects, num_parsed_inputs ); + exit( -1 ); + } + else + { + fprintf( stderr, "Unexpected metadata identifier\n" ); + exit( -1 ); + } + + ++num_parsed_inputs; + } + + inConfig->numAudioObjects = counterMonoAudioObjects; + inConfig->numAmbisonicsBuses = counterAmbisonicsAudioObjects; + inConfig->numMultiChannelBuses = counterChannelAudioObjects; + inConfig->numMasaBuses = counterMasaInputs; + positionProvider->numObjects = counterMonoAudioObjects; + + /* check for trailing text */ + token = strtok( NULL, delimiter ); + if ( token != NULL && sscanf( token, "%s", line ) ) + { + fprintf( stderr, "Trailing text in metadata file\n" ); + exit( -1 ); + } + + return; +} + +static void parseSceneDescriptionFile( + char *path, + char *audioFilePath, + InputConfig *inConfig, + IsmPositionProvider *positionProvider, + MasaFileReader **masaReaders ) +{ + uint32_t inAudioFilePathLen; + char inAudioFilePath[FILENAME_MAX]; + uint32_t mtdStrLen; + char mtdStr[RENDERER_MAX_METADATA_LENGTH]; + char inDir[FILENAME_MAX]; + char *lastSlash = NULL; + + inAudioFilePathLen = FILENAME_MAX; + mtdStrLen = RENDERER_MAX_METADATA_LENGTH; + splitConfigFile( path, mtdStr, &mtdStrLen, inAudioFilePath, &inAudioFilePathLen ); + + remove_cr( mtdStr ); + convert_backslash( inAudioFilePath ); + + /* Trim config file path to get path to the dir containing it */ + lastSlash = strrchr( path, SEP_FOLDER ); + inDir[0] = '\0'; + if ( lastSlash != NULL ) + { + strncat( inDir, path, ( lastSlash - path + 1 ) ); + } + + /* Append audio file path (relative to config file location) + * to config file location path to get full absolute path */ + strcpy( audioFilePath, inDir ); + strncat( audioFilePath, inAudioFilePath, inAudioFilePathLen ); + + parseMetadata( mtdStr, inDir, inConfig, positionProvider, masaReaders ); + + return; +} + +static void printSupportedAudioConfigs() +{ + uint16_t i; + const char *supportedFormats[] = { + "MONO", + "STEREO", + "5_1", + "5_1_2", + "5_1_4", + "7_1", + "7_1_4", + "Path to Custom Loudspeaker .txt file", + "FOA", + "HOA2", + "HOA3", + "ISMx (input only)", + "MASAx (input only)", + "BINAURAL (output only)", + "BINAURAL_ROOM (output only)", + }; + + fprintf( stdout, "Supported audio formats:\n" ); + for ( i = 0; i < sizeof( supportedFormats ) / sizeof( *supportedFormats ); i++ ) + { + fprintf( stdout, "%s\n", supportedFormats[i] ); + } + + return; +} + +static ivas_error parseLfePanMtxFile( + const char *lfeRoutingMatrixFilePath, + IVAS_REND_LfePanMtx *lfePanMtx ) +{ + int16_t lfe_in, ch_out; + const char *tok; + char line[200]; /* > (10 chars * IVAS_MAX_OUTPUT_CHANNELS) i.e. "-999, " */ + FILE *mtxFile; + + if ( strlen( lfeRoutingMatrixFilePath ) < 1 ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + mtxFile = fopen( lfeRoutingMatrixFilePath, "r" ); + + if ( !mtxFile ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + /* set default panning matrix to all zeros + any subsequent issue in file reading will gracefully exit the function */ + for ( lfe_in = 0; lfe_in < IVAS_MAX_INPUT_LFE_CHANNELS; lfe_in++ ) + { + set_zero( ( *lfePanMtx )[lfe_in], IVAS_MAX_OUTPUT_CHANNELS ); + } + + for ( lfe_in = 0, ch_out = 0; lfe_in < IVAS_MAX_INPUT_LFE_CHANNELS; lfe_in++ ) + { + /* if EOF or a blank line is encountered, simply return */ + if ( ( fgets( line, 200, mtxFile ) == NULL ) && ( strcmp( line, "\n" ) == 0 ) && ( strcmp( line, "\r\n" ) == 0 ) ) + { + fclose( mtxFile ); + return IVAS_ERR_OK; + } + + for ( tok = strtok( line, "," ); tok && *tok; tok = strtok( NULL, ",\n" ) ) + { + while ( *tok == ' ' ) + { + tok++; + } + + if ( *tok == '\0' ) + { + continue; + } + if ( ch_out > IVAS_MAX_OUTPUT_CHANNELS ) + { + break; + } + else + { + ( *lfePanMtx )[lfe_in][ch_out] = (float) atof( tok ); + ch_out++; + } + } + } + + fclose( mtxFile ); + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * convertInputBuffer() + * + * Convert input buffer from WAV/PCM file (int16_t, interleaved) to a format + * accepted by the renderer (float, packed) + *--------------------------------------------------------------------------*/ + +static void convertInputBuffer( + const int16_t *intBuffer, + const int16_t numIntSamplesPerChannel, + const int16_t numFloatSamplesPerChannel, + const int16_t numChannels, + float *floatBuffer ) +{ + int16_t chnl, smpl, i; + + i = 0; + + for ( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + if ( i < numIntSamplesPerChannel ) + { + floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = (float) intBuffer[i]; + } + else + { + floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = 0.f; + } + + ++i; + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * convertOutputBuffer() + * + * Convert output buffer from the renderer (float, packed) to a format ready + * for writing to a WAV/PCM file (int16_t, interleaved) + *--------------------------------------------------------------------------*/ + +static void convertOutputBuffer( + const float *floatBuffer, + const int16_t numSamplesPerChannel, + const int16_t numChannels, + int16_t *intBuffer ) +{ + int16_t chnl, smpl, i; + float temp; + + i = 0; + + for ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + temp = floatBuffer[chnl * numSamplesPerChannel + smpl]; + temp = (float) floor( temp + 0.5f ); + if ( temp > MAX16B_FLT ) + { + temp = MAX16B_FLT; + } + else if ( temp < MIN16B_FLT ) + { + temp = MIN16B_FLT; + } + intBuffer[i] = (int16_t) temp; + + ++i; + } + } + + return; +} diff --git a/scripts/ivas_pytests/tests/unit_tests/crend/.vs/ivas_crend_unit_test/v16/Solution.VC.db-wal b/ci/__init__.py similarity index 100% rename from scripts/ivas_pytests/tests/unit_tests/crend/.vs/ivas_crend_unit_test/v16/Solution.VC.db-wal rename to ci/__init__.py diff --git a/ci/build_all_linux.sh b/ci/build_all_linux.sh index 8a5c4add940549511dd244d1bfa25160d383158d..47ad54dc42e9bd43c46744a673915726b924b0db 100755 --- a/ci/build_all_linux.sh +++ b/ci/build_all_linux.sh @@ -1,16 +1,42 @@ #! /usr/bin/bash +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + if [ ! -d "lib_com" ]; then echo "not in root directory! - please run in IVAS root" exit 1 fi # first build codec, everything else needs this anyway -make clean all -j +make clean && make all -j # build unittests make unittests -j -# build prerenderer -make -C scripts/prerenderer -j # build standalone TD object renderer make -C scripts/td_object_renderer/object_renderer_standalone -j diff --git a/ci/build_codec_instrumented_linux.sh b/ci/build_codec_instrumented_linux.sh index e98547c5fa667f65fcf9380fba294784ebd6e6dd..7c4da0a7f5176ac155c746b1b30d2f472c4e07b7 100755 --- a/ci/build_codec_instrumented_linux.sh +++ b/ci/build_codec_instrumented_linux.sh @@ -1,5 +1,33 @@ #! /usr/bin/bash +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + if [ ! -d "lib_com" ]; then echo "not in root directory! - please run in IVAS root" exit 1 diff --git a/ci/build_codec_sanitizers_linux.sh b/ci/build_codec_sanitizers_linux.sh index 65c520d25a42a444b78ced332e076495d4d732f3..d352fa32ec1cd6d8d3283c4984ba428c117b5769 100755 --- a/ci/build_codec_sanitizers_linux.sh +++ b/ci/build_codec_sanitizers_linux.sh @@ -1,5 +1,33 @@ #! /usr/bin/bash +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + if [ ! -d "lib_com" ]; then echo "not in root directory! - please run in IVAS root" exit 1 diff --git a/lib_util/ivas_rom_prerenderer.h b/ci/check_for_warnings.py similarity index 64% rename from lib_util/ivas_rom_prerenderer.h rename to ci/check_for_warnings.py index 6be6ae9863aa5f0ae109633b6b30092786f3d3a5..f6b205e689af9ff65bc22cf309c709f6b5ff6d28 100644 --- a/lib_util/ivas_rom_prerenderer.h +++ b/ci/check_for_warnings.py @@ -1,6 +1,6 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +#!/usr/bin/env python3 +""" + (C) 2022-2023 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 @@ -27,27 +27,36 @@ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#ifndef IVAS_ROM_PRERENDERER_H -#define IVAS_ROM_PRERENDERER_H - -#include -#include "options.h" - -/*----------------------------------------------------------------------------------* - * Prerenderer SBA & MC enc/dec matrices - *----------------------------------------------------------------------------------*/ - -extern const float hoa_dec_mtx_CICP1[16]; -extern const float ls_azimuth_CICP1[1]; -extern const float ls_elevation_CICP1[1]; -extern const uint32_t ls_LFE_last_idx_CICP1[1]; -extern const uint32_t ls_LFE_last_idx_CICP2[2]; -extern const uint32_t ls_LFE_last_idx_CICP6[6]; -extern const uint32_t ls_LFE_last_idx_CICP12[8]; -extern const uint32_t ls_LFE_last_idx_CICP16[10]; -extern const uint32_t ls_LFE_last_idx_CICP19[12]; - -#endif /* IVAS_ROM_PRERENDERER_H */ +""" +import argparse +import sys + + +SEARCH_FOR = "warning" +RETURN_FOUND = 123 + + +def main(log_file): + with open(log_file) as f: + lines_with_warnings = [l for l in f.readlines() if SEARCH_FOR in l] + + n_warnings = len(lines_with_warnings) + if n_warnings > 0: + print(f"========== Found {n_warnings} warnings: =========") + for l in lines_with_warnings: + print(l) + return RETURN_FOUND + else: + return 0 + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "compilation-output", + type=str, + help="text output of compilation process to analyze", + ) + args = vars(parser.parse_args()) + ret_code = main(args[ "compilation-output" ]) + sys.exit(ret_code) diff --git a/ci/collect_artifacts.py b/ci/collect_artifacts.py new file mode 100644 index 0000000000000000000000000000000000000000..d3228ba2e85e224fa7fb9fdc6415036b6c77f982 --- /dev/null +++ b/ci/collect_artifacts.py @@ -0,0 +1,103 @@ +#! /usr/bin/env python3 +import pathlib +import argparse +import re + + +TEST_TYPES = ["sanitizers"] + + +def main(args): + + test = args.test + file = args.console_out_file + if test == "sanitizers": + collect_for_sanitizer_test(file) + + +def find_failed_files_for_sanitizer_test( + console_log: list, subfolder: str, which="LOGS" +) -> dict(): + + assert which in ["LOGS", "FILE_BASENAMES"] + + pattern_line = "(Encoding|Decoding) failed .*for \/.*(CLANG.|VALGRIND)\/(.*)" + pattern_file = "(.*_b[0-9]*_.*_rs|.*_b[0-9]*_.*_cbr).*" + + files_found = dict() + for line in console_log: + m_line = re.match(pattern_line, line) + + if m_line is not None: + _, test, filename = m_line.groups() + filename = pathlib.Path(filename).name + m_file = re.match(pattern_file, filename) + if m_file is None: + print(f"Unexpected: no match on {filename} with {pattern_file} - skip") + continue + filename_start = m_file.groups()[0] + + if which == "LOGS": + folder = pathlib.Path(f"{test}/{subfolder}/") + files = [ + f for f in folder.iterdir() if f.name.startswith(filename_start) + ] + elif which == "FILE_BASENAMES": + files = [filename_start] + if test in files_found: + files_found[test].extend(files) + else: + files_found[test] = files + + return files_found + + +def collect_for_sanitizer_test(file): + + with open(file) as f: + console_log = f.readlines() + + files_to_archive_noPLC = find_failed_files_for_sanitizer_test( + console_log, "logs_noPLC" + ) + files_to_archive = find_failed_files_for_sanitizer_test(console_log, "logs") + + log_folder = pathlib.Path("./LOGS_PLC") + log_folder.mkdir() + for test in files_to_archive.keys(): + log_folder.joinpath(test).mkdir() + for test, files in files_to_archive.items(): + folder = log_folder.joinpath(test) + for p in files: + source = pathlib.Path(p) + target = folder.joinpath(source.name) + source.rename(target) + + log_folder_noPLC = pathlib.Path("./LOGS_noPLC") + log_folder_noPLC.mkdir() + for test in files_to_archive_noPLC.keys(): + log_folder_noPLC.joinpath(test).mkdir() + for test, files in files_to_archive_noPLC.items(): + folder = log_folder_noPLC.joinpath(test) + for p in files: + source = pathlib.Path(p) + target = folder.joinpath(source.name) + source.rename(target) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "test", + type=str, + choices=TEST_TYPES, + help="for which test should artifacts be collected?", + ) + parser.add_argument( + "console_out_file", + type=str, + help="file with stdout from IvasBuildAndRunChecks.py", + ) + args = parser.parse_args() + + main(args) diff --git a/ci/complexity_measurements/ep_10pct_fer.g192 b/ci/complexity_measurements/ep_10pct_fer.g192 new file mode 100644 index 0000000000000000000000000000000000000000..ba6bfc78b30bed13fa038fadb24f81b4aa99c59e --- /dev/null +++ b/ci/complexity_measurements/ep_10pct_fer.g192 @@ -0,0 +1 @@ +!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k k!k!k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k k k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k!k k!k!k k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k k k!k!k k k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k k k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k k!k!k!k k k k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k k k!k k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k k!k!k!k k k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k k!k!k!k k k!k!k!k!k k!k k!k!k k!k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k k k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k k!k!k!k!k!k k k!k k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k k!k!k!k!k k!k k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k!k!k k!k k!k k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k k!k k k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k k k!k!k!k k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k k k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k!k k!k k!k!k k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k k!k!k!k k k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k k!k!k!k!k!k k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k k!k!k!k k!k!k!k!k!k k!k k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k k!k!k!k k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k k k!k!k!k k!k!k!k!k!k k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k k k!k!k!k!k!k k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k!k!k!k k!k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k k!k!k!k k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k!k!k k!k!k k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k k!k k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k k!k k!k k k!k!k!k!k!k!k!k k!k!k!k k k!k k k!k!k!k!k!k!k!k k!k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k k!k k!k k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k \ No newline at end of file diff --git a/ci/complexity_measurements/genWebpageData_Ram.csh b/ci/complexity_measurements/genWebpageData_Ram.csh new file mode 100644 index 0000000000000000000000000000000000000000..d6e5a842e3b04a5bde4735f6e2b6c197befe053c --- /dev/null +++ b/ci/complexity_measurements/genWebpageData_Ram.csh @@ -0,0 +1,504 @@ +#!/bin/tcsh + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + +set maxValues = 40 + +if (${#argv} != 3) then + echo usage: $0 \ \ \ + exit +endif + +set srcFile = $1 +set file_final = $2 +set file = ${file_final}_new_$$ +set graphName = $3 + + +set tmpBase = `basename $0` +set tmpFile = /tmp/${tmpBase}_$$ +rm -f ${tmpFile} +cat ${srcFile} | tail -n ${maxValues} > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +set maxNumWordsLine = 19 + +rm -f $file +touch $file + +echo "var $graphName = {" >> $file +echo ' ram_worstcase: {' >> $file +echo ' description: "Worst Case RAM",' >> $file +echo ' direction: -1,' >> $file +echo ' runs: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + @ i++ + set separator = "," + if ( $i == $nLines ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set revision = $tmp[1] + set shortDate = `echo $tmp[2] | sed -e "s/_/\ /g"` + set fullDate = `echo $tmp[3] | sed -e "s/_/\ /g"` + set maxTotalRamEnc = $tmp[5] + set maxTotalRamDec = $tmp[7] + set maxStackEnc = $tmp[10] + set maxStackDec = $tmp[12] + set maxHeapEnc = $tmp[15] + set maxHeapDec = $tmp[17] + set logFile = $tmp[19] + + echo ' {' >> $file + echo ' fullDate: "'${fullDate}'",' >> $file + echo ' shortDate: "'${shortDate}'",' >> $file + echo ' revision: "'${revision}'",' >> $file + echo ' maxTotalRamEnc: "'${maxTotalRamEnc}'",' >> $file + echo ' maxTotalRamDec: "'${maxTotalRamDec}'",' >> $file + echo ' maxStackEnc: "'${maxStackEnc}'",' >> $file + echo ' maxStackDec: "'${maxStackDec}'",' >> $file + echo ' maxHeapEnc: "'${maxHeapEnc}'",' >> $file + echo ' maxHeapDec: "'${maxHeapDec}'",' >> $file + echo ' logFile: "'${logFile}'"' >> $file + echo ' }'${separator} >> $file + +end +echo ' ],' >> $file + +# begin displays +echo ' displays: [' >> $file + +# requirement RAM +echo ' {' >> $file +echo ' lines: { show: false },' >> $file +echo ' points: { show: false, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#000000",' >> $file +echo ' id: "requirementRam",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + # TODO: add real requirement once decided on + set score = 0 + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# requirement RAM + +# maxTotalRamCodecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FF0000",' >> $file +echo ' id: "maxTotalRamCodecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[4] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxTotalRamCodecScore + +# maxTotalRamEncScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FF8000",' >> $file +echo ' id: "maxTotalRamEncScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[6] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxTotalRamEncScore + +# maxTotalRamDecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FFFF00",' >> $file +echo ' id: "maxTotalRamDecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[8] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxTotalRamDecScore + +# maxStackCodecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#004000",' >> $file +echo ' id: "maxStackCodecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[9] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxStackCodecScore + + +# maxStackEncScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#008000",' >> $file +echo ' id: "maxStackEncScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[11] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxStackEncScore + +# maxStackDecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#00FF00",' >> $file +echo ' id: "maxStackDecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[13] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxStackDecScore + +# maxHeapCodecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#800080",' >> $file +echo ' id: "maxHeapCodecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[14] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxHeapCodecScore + +# maxHeapEncScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#0000FF",' >> $file +echo ' id: "maxHeapEncScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[16] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxHeapEncScore + +# maxHeapDecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#0080C0",' >> $file +echo ' id: "maxHeapDecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[18] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' }' >> $file +# maxHeapDecScore + +echo ' ]' >> $file +# end displays + +echo ' }' >> $file +echo '};' >> $file + +mv -f $file $file_final +rm -f $tmpFile diff --git a/ci/complexity_measurements/genWebpageData_Rom.csh b/ci/complexity_measurements/genWebpageData_Rom.csh new file mode 100644 index 0000000000000000000000000000000000000000..801dfda724738bfbbfdcb4ddcef8b5107c66f66c --- /dev/null +++ b/ci/complexity_measurements/genWebpageData_Rom.csh @@ -0,0 +1,535 @@ +#!/bin/tcsh + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + +set maxValues = 40 + +if (${#argv} != 3) then + echo usage: $0 \ \ \ + exit +endif + +set srcFile = $1 +set file_final = $2 +set file = ${file_final}_new_$$ +set graphName = $3 + +set tmpBase = `basename $0` +set tmpFile = /tmp/${tmpBase}_$$ +rm -f ${tmpFile} +cat ${srcFile} | tail -n ${maxValues} > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +set maxNumWordsLine = 21 + +rm -f $file +touch $file + +echo "var $graphName = {" >> $file +echo ' rom_worstcase: {' >> $file +echo ' description: "ROM",' >> $file +echo ' direction: -1,' >> $file +echo ' runs: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + @ i++ + set separator = "," + if ( $i == $nLines ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + + # 1 revision, + # 2 shortDate, + # 3 fullDate, + + # 4 max_total_encdec[1], + + # 5 max_prom_enc[0], + # 6 max_prom_enc[1], + # 7 max_prom_dec[0], + # 8 max_prom_dec[1], + # 9 max_prom_com[0], + # 10 max_prom_com[1], + # 11 max_prom_rend[0], + # 12 max_prom_rend[1], + + # 13 max_trom_enc[0], + # 14 max_trom_enc[1], + # 15 max_trom_dec[0], + # 16 max_trom_dec[1], + # 17 max_trom_com[0], + # 18 max_trom_com[1], + # 19 max_trom_rend[0], + # 20 max_trom_rend[1], + + # 21 newsletterFilenameLast, + + + set revision = $tmp[1] + set shortDate = `echo $tmp[2] | sed -e "s/_/\ /g"` + set fullDate = `echo $tmp[3] | sed -e "s/_/\ /g"` + set PromEnc = $tmp[5] + set PromDec = $tmp[7] + set PromCom = $tmp[9] + set PromRend = $tmp[11] + set TromEnc = $tmp[13] + set TromDec = $tmp[15] + set TromCom = $tmp[17] + set TromRend = $tmp[19] + set logFile = $tmp[21] + + echo ' {' >> $file + echo ' fullDate: "'${fullDate}'",' >> $file + echo ' shortDate: "'${shortDate}'",' >> $file + echo ' revision: "'${revision}'",' >> $file + echo ' PromEnc: "'${PromEnc}'",' >> $file + echo ' PromDec: "'${PromDec}'",' >> $file + echo ' PromCom: "'${PromCom}'",' >> $file + echo ' PromRend: "'${PromRend}'",' >> $file + echo ' TromEnc: "'${TromEnc}'",' >> $file + echo ' TromDec: "'${TromDec}'",' >> $file + echo ' TromCom: "'${TromCom}'",' >> $file + echo ' TromRend: "'${TromRend}'",' >> $file + echo ' logFile: "'${logFile}'"' >> $file + echo ' }'${separator} >> $file + +end +echo ' ],' >> $file + +# begin displays +echo ' displays: [' >> $file + +# requirement ROM +echo ' {' >> $file +echo ' lines: { show: false },' >> $file +echo ' points: { show: false, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#000000",' >> $file +echo ' id: "requirementRom",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + # TODO: add real requirement once decided on + set score = 0 + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# requirement ROM + +# TotalRomCodecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FF0000",' >> $file +echo ' id: "TotalRomCodecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[4] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# TotalRomCodecScore + +# maxPROMEncScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FF8000",' >> $file +echo ' id: "maxPROMEncScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[6] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxPROMEncScore + +# maxPROMDecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FFFF00",' >> $file +echo ' id: "maxPROMDecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[8] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxPROMEncScore + +# maxPROMComScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#800080",' >> $file +echo ' id: "maxPROMComScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[10] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxPROMComScore + + +# maxPROMRendScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#0000FF",' >> $file +echo ' id: "maxPROMRendScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[12] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxPROMRendScore + +# maxTROMEncScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#0080C0",' >> $file +echo ' id: "maxTROMEncScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[14] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxTROMEncScore + +# maxTROMDecScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#004000",' >> $file +echo ' id: "maxTROMDecScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[16] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxTROMDecScore + +# maxTROMComScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#008000",' >> $file +echo ' id: "maxTROMComScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[18] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# maxTROMComScore + +# maxTROMRendScore +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#00FF00",' >> $file +echo ' id: "maxTROMRendScore",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLine ) then + continue + endif + + set score = $tmp[20] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' }' >> $file +# maxTROMRendScore + +echo ' ]' >> $file +# end displays + +echo ' }' >> $file +echo '};' >> $file + +mv -f $file $file_final +rm -f $tmpFile diff --git a/ci/complexity_measurements/genWebpageData_WMOPS.csh b/ci/complexity_measurements/genWebpageData_WMOPS.csh new file mode 100644 index 0000000000000000000000000000000000000000..4993ae81f219405d04e9634101ee0c5b2c8cfdb4 --- /dev/null +++ b/ci/complexity_measurements/genWebpageData_WMOPS.csh @@ -0,0 +1,500 @@ +#!/bin/tcsh + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + +set maxValues = 40 + +if (${#argv} != 3) then + echo usage: $0 \ \ \ + exit +endif + +set srcFile = $1 +set file_final = $2 +set file = ${file_final}_new_$$ +set graphName = $3 + + +set tmpBase = `basename $0` +set tmpFile = /tmp/${tmpBase}_$$ +rm -f ${tmpFile} +cat ${srcFile} | tail -n ${maxValues} > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +set maxNumWordsLineOld = 12 +set maxNumWordsLineNew = 19 + +rm -f $file +touch $file + +echo "var $graphName = {" >> $file +echo ' wmops_worstcase: {' >> $file +echo ' description: "Worst Case WMOPS",' >> $file +echo ' direction: -1,' >> $file +echo ' runs: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + @ i++ + set separator = "," + if ( $i == $nLines ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + set revision = $tmp[1] + set shortDate = `echo $tmp[2] | sed -e "s/_/\ /g"` + set fullDate = `echo $tmp[3] | sed -e "s/_/\ /g"` + set worstCaseEnc = $tmp[5] + set worstCaseDec = $tmp[7] + set worstCaseCodec = $tmp[9] + set fixpointScalingFac = $tmp[11] + if ( $numWords == $maxNumWordsLineOld ) then + set logFile = $tmp[12] + set worstCaseEncRs = "" + set worstCaseDecRs = "" + set worstCaseCodecRs = "" + else if ( $numWords < $maxNumWordsLineNew ) then + set logFile = "" + set worstCaseEncRs = "" + set worstCaseDecRs = "" + set worstCaseCodecRs = "" + else + set logFile = $tmp[19] + set worstCaseEncRs = $tmp[13] + set worstCaseDecRs = $tmp[15] + set worstCaseCodecRs = $tmp[17] + endif + + + echo ' {' >> $file + echo ' fullDate: "'${fullDate}'",' >> $file + echo ' shortDate: "'${shortDate}'",' >> $file + echo ' revision: "'${revision}'",' >> $file + echo ' worstCaseEnc: "'${worstCaseEnc}'",' >> $file + echo ' worstCaseDec: "'${worstCaseDec}'",' >> $file + echo ' worstCaseCodec: "'${worstCaseCodec}'",'>> $file + echo ' worstCaseEncRs: "'${worstCaseEncRs}'",' >> $file + echo ' worstCaseDecRs: "'${worstCaseDecRs}'",' >> $file + echo ' worstCaseCodecRs: "'${worstCaseCodecRs}'",'>> $file + echo ' fixpointScalingFac: "'${fixpointScalingFac}'",'>> $file + echo ' logFile: "'${logFile}'"' >> $file + echo ' }'${separator} >> $file + +end +echo ' ],' >> $file + +# begin displays +echo ' displays: [' >> $file + +# 135 WMOPS boundary +echo ' {' >> $file +echo ' lines: { show: false },' >> $file +echo ' points: { show: false, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: false,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#000000",' >> $file +echo ' id: "requirement",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + # TODO: add real requirement once decided on + set score = 0 + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# 135 WMOPS boundary + +# worst case codec +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#0080FF",' >> $file +echo ' id: "worst case codec",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + set score = $tmp[10] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# end worst case codec + +# worst case enc/dec +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FF8000",' >> $file +echo ' id: "worst case enc/dec",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + set score = $tmp[4] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# worst case enc/dec + +# worst case encoder +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#CF4B4B",' >> $file +echo ' id: "worst case enc",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + set score = $tmp[6] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# end worst case encoder + +# worst case decoder +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#008040",' >> $file +echo ' id: "worst case dec",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + set score = $tmp[8] + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# end worst case decoder + +########### rateswitching ############### + +# worst case codec rateswitching +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#40C4FF",' >> $file +echo ' id: "worst case codec rs",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + if ( $numWords < $maxNumWordsLineNew ) then + set score = 0 + else + set score = $tmp[18] + endif + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# end worst case codec rateswitching + +# worst case enc/dec rateswitching +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#FFC480",' >> $file +echo ' id: "worst case enc/dec rs",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + if ( $numWords < $maxNumWordsLineNew ) then + set score = 0 + else + set score = $tmp[12] + endif + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# worst case enc/dec rateswitching + +# worst case encoder rateswitching +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#CF8080",' >> $file +echo ' id: "worst case enc rs",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + if ( $numWords < $maxNumWordsLineNew ) then + set score = 0 + else + set score = $tmp[14] + endif + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' },' >> $file +# end worst case encoder rateswitching + +# worst case decoder rateswitching +echo ' {' >> $file +echo ' lines: { show: true },' >> $file +echo ' points: { show: true, fillColor: "#ffffff" },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: true,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#00F040",' >> $file +echo ' id: "worst case dec rs",' >> $file +echo ' data: [' >> $file + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + set separator = "," + if ( $i == $nLines - 1 ) then + set separator = "" + endif + + set tmp = ( $line ) + + set numWords = `echo $tmp | wc -w` + if ( $numWords < $maxNumWordsLineOld ) then + continue + endif + + if ( $numWords < $maxNumWordsLineNew ) then + set score = 0 + else + set score = $tmp[16] + endif + + echo ' ['"${i}, ${score}"']'${separator} >> $file + @ i++ + +end + +echo ' ]' >> $file +echo ' }' >> $file +# end worst case decoder rateswitching + +########### end rateswitching ############### + +echo ' ]' >> $file +# end displays + +echo ' }' >> $file +echo '};' >> $file + +mv -f $file $file_final +rm -f $tmpFile diff --git a/ci/complexity_measurements/genWebpageData_WmopPerOperatingpoint.csh b/ci/complexity_measurements/genWebpageData_WmopPerOperatingpoint.csh new file mode 100644 index 0000000000000000000000000000000000000000..3d9d9d448c27fdce30724273e633cdf3697fdc0d --- /dev/null +++ b/ci/complexity_measurements/genWebpageData_WmopPerOperatingpoint.csh @@ -0,0 +1,503 @@ +#!/bin/tcsh + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + +set srcFile = $1 +set file_final = $2 +set file = ${file_final}.new +set graphName = $3 + +set tmpBase = `basename $0` +set tmpFile = /tmp/${tmpBase}_$$ + +rm -f $file +touch $file + +set worstCaseCodec +set worstCaseEnc +set worstCaseDec +@ numEntries = 0; +@ offsetTicks = 0; + +echo "var $graphName = {" >> $file +echo ' wmops_worstcase_per_op: {' >> $file +echo ' description: "Worst Case WMOPS per OP",' >> $file +echo ' direction: -1,' >> $file +echo ' runs: [' >> $file + +# +# NB modes +# +if (0) then # don't use! +rm -f ${tmpFile} +cat ${srcFile} | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_NB_" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksNB = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "NB"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file + +# +# NB modes, rateswitching +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_NB_RS" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksNB_RS = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "NB RS"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file + +# +# AMR-WB IO modes +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_WB_" | grep "AMR" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksWBIO = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "AMR-WB IO"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file + +# +# AMR-WB IO modes rateswitching +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_WB_RS" | grep "AMR" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksWBIO_RS = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "AMR-WB IO RS"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file +endif + +# +# WB modes +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_WB_" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksWB = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "WB"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file + +# +# WB modes rateswitching +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_WB_RS" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksWB_RS = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "WB RS"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file + +# +# SWB modes +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_SWB_" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksSWB = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "SWB"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file + + +# +# SWB modes rateswitching +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_SWB_RS" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksSWB_RS = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "SWB RS"' >> $file + echo ' },' >> $file + +end + +# +# FB modes +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_FB_" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksFB = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +foreach line ( "`cat ${tmpFile}`" ) + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "FB"' >> $file + echo ' },' >> $file + +end + +set worstCaseCodec = ( $worstCaseCodec 0 ) +set worstCaseEnc = ( $worstCaseEnc 0 ) +set worstCaseDec = ( $worstCaseDec 0 ) +@ numEntries++ + +echo ' {' >> $file +echo ' operatingPoint: "",' >> $file +echo ' mode: ""' >> $file +echo ' },' >> $file + + +# +# FB modes rateswitching +# +rm -f ${tmpFile} +cat $srcFile | grep "[0-9]" | sed -e "s/\ /_/g" | sed -e "s/;/\ /g" | grep "_FB_RS" > ${tmpFile} +set nLines = `cat ${tmpFile} | wc -l` +@ ticksFB_RS = $offsetTicks + ( $nLines / 2 ) +@ offsetTicks += ($nLines + 1) + +@ i = 0 +foreach line ( "`cat ${tmpFile}`" ) + @ i++ + set separator = "," + if ( $i == $nLines ) then + set separator = "" + endif + + set tmp = `echo $line` + + set operatingPoint = $tmp[1] + set worstCaseCodec = ( $worstCaseCodec $tmp[4] ) + set worstCaseEnc = ( $worstCaseEnc $tmp[2] ) + set worstCaseDec = ( $worstCaseDec $tmp[3] ) + @ numEntries++ + + echo ' {' >> $file + echo ' operatingPoint: "'${operatingPoint}'",' >> $file + echo ' mode: "SWB RS"' >> $file + echo ' }'${separator} >> $file + +end + +echo ' ],' >> $file + +# +# ticks +# +echo ' ticks: [' >> $file +if (0) then +echo ' ['$ticksNB', "NB"],' >> $file +echo ' ['$ticksNB_RS', "NB RS"],' >> $file +echo ' ['$ticksWBIO', "AMR-WB IO"],' >> $file +endif +echo ' ['$ticksWB', "WB"],' >> $file +echo ' ['$ticksWB_RS', "WB RS"],' >> $file +echo ' ['$ticksSWB', "SWB"],' >> $file +echo ' ['$ticksSWB_RS', "SWB RS"],' >> $file +echo ' ['$ticksFB', "FB"],' >> $file +echo ' ['$ticksFB_RS', "FB RS"]' >> $file +echo ' ],' >> $file + + +# begin displays +echo ' displays: [' >> $file + +# Start: Worse case encoder +echo ' {' >> $file +echo ' lines: { show: false },' >> $file +echo ' points: { show: false },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: false,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#CF4B4B",' >> $file +echo ' id: "worstCaseEnc",' >> $file +echo ' label: "Encoder",' >> $file +echo ' data: [' >> $file + +@ i = 0 +while($i < $numEntries) + + set separator = "," + if ( $i == $numEntries - 1 ) then + set separator = "" + endif + + @ j = $i + 1 + + echo ' ['"${i}, $worstCaseEnc[$j]"']'${separator} >> $file + + @ i++ +end + +echo ' ]' >> $file +echo ' },' >> $file +# End: Worst case encoder + +# Start: Worse case decoder +echo ' {' >> $file +echo ' lines: { show: false },' >> $file +echo ' points: { show: false },' >> $file +echo ' borderWidth: 1.5,' >> $file +echo ' borderColor: "#BEBEBE",' >> $file +echo ' markingsLineWidth: .75,' >> $file +echo ' hoverable: true,' >> $file +echo ' clickable: false,' >> $file +echo ' shadowSize: 0,' >> $file +echo ' color: "#008040",' >> $file +echo ' id: "worstCaseDec",' >> $file +echo ' label: "Decoder",' >> $file +echo ' data: [' >> $file + +@ i = 0 +while($i < $numEntries) + + set separator = "," + if ( $i == $numEntries - 1 ) then + set separator = "" + endif + + @ j = $i + 1 + + echo ' ['"${i}, $worstCaseDec[$j]"']'${separator} >> $file + + @ i++ +end + +echo ' ]' >> $file +echo ' }' >> $file +# End: Worst case encoder + +echo ' ]' >> $file +# end displays + +echo ' }' >> $file +echo '};' >> $file + +mv -f $file $file_final +rm -f $tmpFile diff --git a/ci/complexity_measurements/getWmops.sh b/ci/complexity_measurements/getWmops.sh new file mode 100644 index 0000000000000000000000000000000000000000..baec52ab6f1e7064b3be60679d0d1aafc8f681ad --- /dev/null +++ b/ci/complexity_measurements/getWmops.sh @@ -0,0 +1,86 @@ +#! /bin/bash + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + +# get format from command line +if [ $# -ne 2 ]; then + echo "Usage: $0 \"ivas-format(s)\" \"output-format(s)\"" + exit 1 +fi + +ivas_format=$1 +output_format=$2 + +date=`date +%Y%m%d` # used for log-file file ending +shortDate=`date "+%b %d" | sed -e "s/\ /_/g"` # stored in the log-file +fullDate=`date "+%c" | sed -e "s/\ /_/g"` # stored in the log-file + +commit_sha=`git rev-parse --short HEAD` + +destDir="." +scriptDir="ci/complexity_measurements" +ep="${scriptDir}/ep_10pct_fer.g192" + +config_file="scripts/config/ci_linux_ltv.json" + +# get wmops newsletter +wmopsFilenameFlcLast=wmops_newsletter_stereo__${commit_sha}_${date} +wmopsFilenameFlc=${destDir}/wmops/logs/${wmopsFilenameFlcLast} + +# instrument and build +./scripts/IvasBuildAndRunChecks.py -p $config_file --checks COMPLEXITY --create_complexity_tables ${wmopsFilenameFlc} -C $ivas_format -f ${ep} --oc $output_format + +# get the info on worst-case operating point: WMOPS number, enc-operating mode, dec-operating mode +### WMOPS +${scriptDir}/parseNewsletterWmops.py ${wmopsFilenameFlc}_WMOPS.csv ${wmopsFilenameFlcLast}_WMOPS.csv ${commit_sha} ${shortDate} ${fullDate} >> ${destDir}/wmops/log_wmops_all.txt + +# now update the webpage +tcsh ${scriptDir}/genWebpageData_WMOPS.csh ${destDir}/wmops/log_wmops_all.txt ${destDir}/wmops/graphs_wmops_flc.js Graphs_WMOPS + +# per mode graph +tcsh ${scriptDir}/genWebpageData_WmopPerOperatingpoint.csh ${wmopsFilenameFlc}_WMOPS.csv ${destDir}/wmops/graphs_wmops_flc_perOP.js Graphs_WMOPS_perOP + + +# get memory info for webpage +### RAM +${scriptDir}/mergeNewsletterRam.py ${wmopsFilenameFlc}_HEAP.csv ${wmopsFilenameFlc}_STACK.csv > ${wmopsFilenameFlc}_RAM.csv +${scriptDir}/parseNewsletterRam.py ${wmopsFilenameFlc}_HEAP.csv ${wmopsFilenameFlc}_STACK.csv ${wmopsFilenameFlcLast}_RAM.csv ${commit_sha} ${shortDate} ${fullDate} >> ${destDir}/wmops/log_ram_all.txt + +# generate java script from database +tcsh ${scriptDir}/genWebpageData_Ram.csh ${destDir}/wmops/log_ram_all.txt ${destDir}/wmops/graphs_ram_flc.js Graphs_RAM + +### ROM + +${scriptDir}/mergeNewsletterRom.py ${wmopsFilenameFlc}_PROM.csv ${wmopsFilenameFlc}_TROM.csv > ${wmopsFilenameFlc}_ROM.csv +${scriptDir}/parseNewsletterRom.py ${wmopsFilenameFlc}_PROM.csv ${wmopsFilenameFlc}_TROM.csv ${wmopsFilenameFlcLast}_ROM.csv ${commit_sha} ${shortDate} ${fullDate} >> ${destDir}/wmops/log_rom_all.txt + +# generate java script from database +tcsh ${scriptDir}/genWebpageData_Rom.csh ${destDir}/wmops/log_rom_all.txt ${destDir}/wmops/graphs_rom_flc.js Graphs_ROM + + diff --git a/ci/complexity_measurements/index_complexity.html b/ci/complexity_measurements/index_complexity.html new file mode 100644 index 0000000000000000000000000000000000000000..de3d0975fcc69772aacacca3ef4529668869323b --- /dev/null +++ b/ci/complexity_measurements/index_complexity.html @@ -0,0 +1,1073 @@ + + + + + + + + + + + IVAS FORMAT - Worst Case WMOPS/Memory Performance + + + + + + + + + + + + + + + + + + + + + +
+

IVAS FORMAT - Worst Case WMOPS Performance (Float, native SR)

+ +
+
+
+ +
+
    +
  • Worst case encoder + decoder performance: Encoder and decoder mode might be different.
  • +
  • Worst case encoder + decoder performance (rateswitching): Encoder and decoder mode might be different.
  • +
  • Worst case codec performance: Encoder and decoder modes are identical.
  • +
  • Worst case codec performance (rateswitching): Encoder and decoder modes are identical.
  • +
  • Worst case encoder performance
  • +
  • Worst case encoder performance (rateswitching)
  • +
  • Worst case decoder performance
  • +
  • Worst case decoder performance (rateswitching)
  • +
+
+ +
+ +

IVAS FORMAT - Worst Case WMOPS Performance + per Operating Point (Float, native SR)

+ +
+
+
+ +
+
+
+ +
+ + + + +

IVAS FORMAT - Worst Case RAM Demand (Float)

+ +
+
+
+ +
+
    +
  • Max. total RAM Codec: + 32 bit words, Encoder + Decoder
  • +
  • Max. total RAM Encoder: + 32 bit words, Encoder only
  • +
  • Max. total RAM Decoder: + 32 bit words, Decoder only
  • + +
  • Max. HEAP Codec: + 32 bit words, Encoder + Decoder
  • +
  • Max. HEAP Encoder + 32 bit words, Encoder only
  • +
  • Max. HEAP Decoder + 32 bit words, Decoder only
  • + +
  • Max. STACK Codec: + 32 bit words, max(Encoder, Decoder)
  • +
  • Max. STACK Encoder: + 32 bit words, Encoder only
  • +
  • Max. STACK Decoder: + 32 bit words, Decoder only
  • +
+
+ +
+ + + +

IVAS FORMAT - Worst Case ROM Demand (Float)

+ +
+
+
+ +
+
    +
  • Max. total ROM Codec: Encoder + Decoder
  • + +
  • Max. max PROM Encoder Library: lib_enc only
  • +
  • Max. max PROM Decoder Library: lib_dec only
  • +
  • Max. max PROM Common Library: lib_com only/li> +
  • Max. max PROM Ext Renderer Library: lib_ren only
  • + +
  • Max. Table ROM Encoder Library: lib_enc only
  • +
  • Max. Table ROM Decoder Library: lib_dec only
  • +
  • Max. Table ROM Common Library: lib_com only
  • +
  • Max. Table ROM Ext Renderer Library: lib_rend only
  • +
+
+ + + +

FAQ

+
+
Q:
What is the meaning of these funny symbols in the navigation box, in the left upper corner of this page?
+
A:
+ 1) Traffic light , or : !!!CURRENTLY NOT WORKING CORRECTLY AS NO REQUIREMENTS DEFINED YET!!! The traffic light symbols show, whether the last datapoint matches the requirement (green) or not (red). A yellow traffic light means that the requirement is matched, but the score is very close (within a 3% margin) to the requirement.
+ 2) Arrow , , : The arrow indicates the trend of the last datapoint, compared to the last but one. An upwards arrow means that the score got higher (i.e. worse), downwards arrow arrow means that the score got lower (i.e. better), and a rightwards arrow means that the score was kept constant (within a 1% margin). +
+
Q:
Which input files are used for audio-input? What error pattern is used?
+
A:
The input files can be found here. The error pattern is here. +
+ + +
+

Legal notice

+
+ This webpage uses jQuery and Flot.js libraries for which the following licenses apply: +
+
jQuery:
+
+ Copyright OpenJS Foundation and other contributors, https://openjsf.org/ + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +
+
Flot.js:
+
+ Copyright (c) 2007-2014 IOLA and Ole Laursen + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +
+
+
+
+ + + + + diff --git a/ci/complexity_measurements/mergeNewsletterRam.py b/ci/complexity_measurements/mergeNewsletterRam.py new file mode 100644 index 0000000000000000000000000000000000000000..e11a754d38ed4465623f0fb548f0379a471bc5de --- /dev/null +++ b/ci/complexity_measurements/mergeNewsletterRam.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. +import csv +import sys +import re + +newsletterFilename = "" +newsletterFilenameLast = "" +revision = "" +shortDate = "" +fullDate = "" + +if __name__ == "__main__": + newsletterFilenameHEAP = sys.argv[1] + newsletterFilenameSTACK = sys.argv[2] + +ram_table = {} + +with open(newsletterFilenameHEAP, "r") as csvfile: + HEAP = csv.reader(csvfile, delimiter=";") + for row in HEAP: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + ram_table[key] = lst + +with open(newsletterFilenameSTACK, "r") as csvfile: + STACK = csv.reader(csvfile, delimiter=";") + for row in STACK: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + ram_table[key] += lst + +# now we have the following format +# HEAP enc, HEAP dec, HEAP total, STACK enc, STACK dec, STACK max(enc, dec) + +print("conf;HEAP enc;HEAP dec;HEAP total;STACK enc;STACK dec;STACK max;total") + +for key in ram_table: + ram = ram_table[key] + total = int(ram[0]) + int(ram[1]) + int(ram[5]) + print( + key, + ";", + ram[0], + ";", + ram[1], + ";", + ram[2], + ";", + ram[3], + ";", + ram[4], + ";", + ram[5], + ";", + total, + sep="", + ) diff --git a/ci/complexity_measurements/mergeNewsletterRom.py b/ci/complexity_measurements/mergeNewsletterRom.py new file mode 100644 index 0000000000000000000000000000000000000000..89efc4aeb2f8177e2e92b38c7b68f61d6255ebd8 --- /dev/null +++ b/ci/complexity_measurements/mergeNewsletterRom.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. +import csv +import sys +import re + +newsletterFilename = "" +newsletterFilenameLast = "" +revision = "" +shortDate = "" +fullDate = "" + +if __name__ == "__main__": + newsletterFilenamePROM = sys.argv[1] + newsletterFilenameTROM = sys.argv[2] + +rom_table = {} + +with open(newsletterFilenamePROM, "r") as csvfile: + PROM = csv.reader(csvfile, delimiter=";") + for row in PROM: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + rom_table[key] = lst + +with open(newsletterFilenameTROM, "r") as csvfile: + TROM = csv.reader(csvfile, delimiter=";") + for row in TROM: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + rom_table[key] += lst + +# now we have the following format +# PROM enc, PROM dec, PROM com, PROM rend, PROM total, TROM enc, TROM dec, TROM com, TROM rend, TROM total + +print("conf;PROM enc;PROM dec;PROM com;PROM rend;PROM total;TROM enc;TROM dec;TROM com;TROM rend;TROM total;total") + +for key in rom_table: + rom = rom_table[key] + total = int(rom[4]) + int(rom[9]) + print( + key, + ";", + rom[0], + ";", + rom[1], + ";", + rom[2], + ";", + rom[3], + ";", + rom[4], + ";", + rom[5], + ";", + rom[6], + ";", + rom[7], + ";", + rom[8], + ";", + rom[9], + ";", + total, + sep="", + ) diff --git a/ci/complexity_measurements/parseNewsletterRam.py b/ci/complexity_measurements/parseNewsletterRam.py new file mode 100644 index 0000000000000000000000000000000000000000..719d1581d8f6c5f79db8e81f081ad70b697a6062 --- /dev/null +++ b/ci/complexity_measurements/parseNewsletterRam.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 +# coding: utf-8 +""" + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import csv +import sys +import re + +newsletterFilename = "" +newsletterFilenameLast = "" +revision = "" +shortDate = "" +fullDate = "" + +if __name__ == "__main__": + newsletterFilenameHEAP = sys.argv[1] + newsletterFilenameSTACK = sys.argv[2] + newsletterFilenameLast = sys.argv[3] + revision = sys.argv[4] + shortDate = sys.argv[5] + fullDate = sys.argv[6] + +max_total_enc = ["", 0] +max_total_dec = ["", 0] +max_total_encdec = ["", 0] + +max_stack_enc = ["", 0] +max_stack_dec = ["", 0] +max_stack_encdec = ["", 0] + +max_heap_enc = ["", 0] +max_heap_dec = ["", 0] +max_heap_encdec = ["", 0] + +ram_table = {} + +with open(newsletterFilenameHEAP, "r") as csvfile: + HEAP = csv.reader(csvfile, delimiter=";") + for row in HEAP: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + ram_table[key] = lst + +with open(newsletterFilenameSTACK, "r") as csvfile: + STACK = csv.reader(csvfile, delimiter=";") + for row in STACK: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + ram_table[key] += lst + +# now we have the following format +# HEAP enc, HEAP dec, HEAP total, STACK enc, STACK dec, STACK max(enc, dec), total + +for key in ram_table: + ram = ram_table[key] + heap_enc = int(ram[0]) + heap_dec = int(ram[1]) + heap_encdec = heap_enc + heap_dec + + stack_enc = int(ram[3]) + stack_dec = int(ram[4]) + stack_encdec = int(ram[5]) + + total_enc = heap_enc + stack_enc + total_dec = heap_dec + stack_dec + total_encdec = heap_encdec + stack_encdec + + if heap_enc > max_heap_enc[1]: + max_heap_enc[0] = re.sub(" ", "_", key) + max_heap_enc[1] = heap_enc + + if heap_dec > max_heap_dec[1]: + max_heap_dec[0] = re.sub(" ", "_", key) + max_heap_dec[1] = heap_dec + + if heap_encdec > max_heap_encdec[1]: + max_heap_encdec[0] = re.sub(" ", "_", key) + max_heap_encdec[1] = heap_encdec + + if stack_enc > max_stack_enc[1]: + max_stack_enc[0] = re.sub(" ", "_", key) + max_stack_enc[1] = stack_enc + + if stack_dec > max_stack_dec[1]: + max_stack_dec[0] = re.sub(" ", "_", key) + max_stack_dec[1] = stack_dec + + if stack_encdec > max_stack_encdec[1]: + max_stack_encdec[0] = re.sub(" ", "_", key) + max_stack_encdec[1] = stack_encdec + + if total_enc > max_total_enc[1]: + max_total_enc[0] = re.sub(" ", "_", key) + max_total_enc[1] = total_enc + + if total_dec > max_total_dec[1]: + max_total_dec[0] = re.sub(" ", "_", key) + max_total_dec[1] = total_dec + + if total_encdec > max_total_encdec[1]: + max_total_encdec[0] = re.sub(" ", "_", key) + max_total_encdec[1] = total_encdec + + +print( + revision, # string revision $tmp[1] + shortDate, # string shortDate $tmp[2] + fullDate, # string fullDate $tmp[3] + + max_total_encdec[1], # value maxTotalRamCodecScore $tmp[4] + + max_total_enc[0], # string maxTotalRamEnc $tmp[5] + max_total_enc[1], # value maxTotalRamEnc $tmp[6] + max_total_dec[0], # string maxTotalRamDec $tmp[7] + max_total_dec[1], # value maxTotalRamDecScore $tmp[8] + + max_stack_encdec[1], # value maxStackCodecScore $tmp[9] + max_stack_enc[0], # string maxStackEnc $tmp[10] + max_stack_enc[1], # value maxStackEncScore $tmp[11] + max_stack_dec[0], # string maxStackDec $tmp[12] + max_stack_dec[1], # value maxStackDecScore $tmp[13] + + max_heap_encdec[1], # value maxHeapCodecScore $tmp[14] + max_heap_enc[0], # string maxHeapEnc $tmp[15] + max_heap_enc[1], # value maxHeapEncScore $tmp[16] + max_heap_dec[0], # string maxHeapDec $tmp[17] + max_heap_dec[1], # value maxHeapDecScore $tmp[19] + + newsletterFilenameLast, # string logFile $tmp[19] +) diff --git a/ci/complexity_measurements/parseNewsletterRom.py b/ci/complexity_measurements/parseNewsletterRom.py new file mode 100644 index 0000000000000000000000000000000000000000..e32051d91220f2e0947ae3590f8aa11fce2a6daa --- /dev/null +++ b/ci/complexity_measurements/parseNewsletterRom.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +""" + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import csv +import sys +import re + +newsletterFilename = "" +newsletterFilenameLast = "" +revision = "" +shortDate = "" +fullDate = "" + +if __name__ == "__main__": + newsletterFilenamePROM = sys.argv[1] + newsletterFilenameTROM = sys.argv[2] + newsletterFilenameLast = sys.argv[3] + revision = sys.argv[4] + shortDate = sys.argv[5] + fullDate = sys.argv[6] + +max_prom_enc = ["", 0] +max_prom_dec = ["", 0] +max_prom_com = ["", 0] +max_prom_rend = ["", 0] +max_prom_total = ["", 0] + +max_trom_enc = ["", 0] +max_trom_dec = ["", 0] +max_trom_com = ["", 0] +max_trom_rend = ["", 0] +max_trom_total = ["", 0] + +max_total_encdec = ["", 0] + +rom_table = {} + +with open(newsletterFilenamePROM, "r") as csvfile: + PROM = csv.reader(csvfile, delimiter=";") + for row in PROM: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + rom_table[key] = lst + +with open(newsletterFilenameTROM, "r") as csvfile: + TROM = csv.reader(csvfile, delimiter=";") + for row in TROM: + if row[0] == "conf": + continue + key = row[0] + lst = row[1:] + rom_table[key] += lst + +# now we have the following format +# PROM enc, PROM dec, PROM com, PROM rend, PROM total, TROM enc, TROM dec, TROM com, TROM rend, TROM total, total + +for key in rom_table: + rom = rom_table[key] + prom_enc = int(rom[0]) + prom_dec = int(rom[1]) + prom_com = int(rom[2]) + prom_rend = int(rom[3]) + prom_total = int(rom[4]) + + trom_enc = int(rom[5]) + trom_dec = int(rom[6]) + trom_com = int(rom[7]) + trom_rend = int(rom[8]) + trom_total = int(rom[9]) + + total_encdec = prom_total + trom_total + + if prom_enc > max_prom_enc[1]: + max_prom_enc[0] = re.sub(" ", "_", key) + max_prom_enc[1] = prom_enc + + if prom_dec > max_prom_dec[1]: + max_prom_dec[0] = re.sub(" ", "_", key) + max_prom_dec[1] = prom_dec + + if prom_com > max_prom_com[1]: + max_prom_com[0] = re.sub(" ", "_", key) + max_prom_com[1] = prom_com + + if prom_rend > max_prom_rend[1]: + max_prom_rend[0] = re.sub(" ", "_", key) + max_prom_rend[1] = prom_rend + + if trom_enc > max_trom_enc[1]: + max_trom_enc[0] = re.sub(" ", "_", key) + max_trom_enc[1] = trom_enc + + if trom_dec > max_trom_dec[1]: + max_trom_dec[0] = re.sub(" ", "_", key) + max_trom_dec[1] = trom_dec + + if trom_com > max_trom_com[1]: + max_trom_com[0] = re.sub(" ", "_", key) + max_trom_com[1] = trom_com + + if trom_rend > max_trom_rend[1]: + max_trom_rend[0] = re.sub(" ", "_", key) + max_trom_rend[1] = trom_rend + + if total_encdec > max_total_encdec[1]: + max_total_encdec[0] = re.sub(" ", "_", key) + max_total_encdec[1] = total_encdec + + +print( + revision, # string revision $tmp[1] + shortDate, # string shortDate $tmp[2] + fullDate, # string fullDate $tmp[3] + + max_total_encdec[1], # value maxTotalRomCodecScore $tmp[4] + + max_prom_enc[0], # string maxPROMEnc $tmp[5] + max_prom_enc[1], # value maxPROMEncScore $tmp[6] + max_prom_dec[0], # string maxPROMDec $tmp[7] + max_prom_dec[1], # value maxPROMDecScore $tmp[8] + max_prom_com[0], # string maxPROMCom $tmp[9] + max_prom_com[1], # value maxPROMComScore $tmp[10] + max_prom_rend[0], # string maxPROMRend $tmp[11] + max_prom_rend[1], # value maxPROMRendScore $tmp[12] + + max_trom_enc[0], # string maxTROMEnc $tmp[13] + max_trom_enc[1], # value maxTROMEncScore $tmp[14] + max_trom_dec[0], # string maxTROMDec $tmp[15] + max_trom_dec[1], # value maxTROMDecScore $tmp[16] + max_trom_com[0], # string maxTROMCom $tmp[17] + max_trom_com[1], # value maxTROMComScore $tmp[18] + max_trom_rend[0], # string maxTROMRend $tmp[19] + max_trom_rend[1], # value maxTROMRendScore $tmp[20] + + newsletterFilenameLast, # string logFile $tmp[21] +) diff --git a/scripts/pyaudio3dtools/rotateISM.py b/ci/complexity_measurements/parseNewsletterWmops.py similarity index 58% rename from scripts/pyaudio3dtools/rotateISM.py rename to ci/complexity_measurements/parseNewsletterWmops.py index 37cbfd5eaf5aa88957084ffd14cd80c5b6b6d809..3328d4ca1662771e83a81a2fc3480dca6b2aa357 100644 --- a/scripts/pyaudio3dtools/rotateISM.py +++ b/ci/complexity_measurements/parseNewsletterWmops.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 - +# coding: utf-8 """ - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,50 +30,61 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -import numpy as np - -from pyaudio3dtools.quaternions.functions import Quat2RotMat - - -def rotateISM( - azi: np.array, - ele: np.array, - trajectory: str = None, -) -> tuple: - - if trajectory is None: - return azi, ele - - trj_data = np.genfromtxt(trajectory, delimiter=",") - trj_frames = trj_data.shape[0] - - N_frames = azi.shape[0] - if ele.shape[0] != azi.shape[0]: - raise ValueError("Inconsistent input in azi and ele") - - azi_rot = np.zeros([N_frames]) - ele_rot = np.zeros([N_frames]) - - R_r = np.zeros([3, 3]) - for i_frame in range(N_frames): - - azi1 = azi[i_frame] - ele1 = ele[i_frame] - - r = np.array( - [-np.sin(azi1) * np.cos(ele1), np.cos(azi1) * np.cos(ele1), np.sin(ele1)] - ) - - q1 = trj_data[i_frame % trj_frames, 1:] - R_r[:, :] = Quat2RotMat(q1) - - r = np.matmul(R_r, r) - - r_xy = np.sqrt(r[0] * r[0] + r[1] * r[1]) - azi_rot1 = np.arctan2(-r[0], r[1]) / np.pi * 180.0 - ele_rot1 = np.arctan2(r[2], r_xy) / np.pi * 180.0 - - azi_rot[i_frame] = azi_rot1 - ele_rot[i_frame] = ele_rot1 - - return azi_rot, ele_rot +import csv +import sys +import re + +newsletterFilename = "" +newsletterFilenameLast = "" +revision = "" +shortDate = "" +fullDate = "" + +if __name__ == "__main__": + newsletterFilename = sys.argv[1] + newsletterFilenameLast = sys.argv[2] + revision = sys.argv[3] + shortDate = sys.argv[4] + fullDate = sys.argv[5] + +max_enc = ["", 0] +max_dec = ["", 0] +max_total = ["", 0] +fixedpointScalingFac = 1.0 + +with open(newsletterFilename, "r") as csvfile: + wmops = csv.reader(csvfile, delimiter=";") + for row in wmops: + if row[0] == "conf": + continue + if float(row[1]) > max_enc[1]: + max_enc[0] = re.sub(" ", "_", row[0]) + max_enc[1] = float(row[1]) + if float(row[2]) > max_dec[1]: + max_dec[0] = re.sub(" ", "_", row[0]) + max_dec[1] = float(row[2]) + if float(row[3]) > max_total[1]: + max_total[0] = re.sub(" ", "_", row[0]) + max_total[1] = float(row[3]) + +print( + revision, + shortDate, + fullDate, + max_enc[1] + max_dec[1], + max_enc[0], + max_enc[1], + max_dec[0], + max_dec[1], + max_total[0], + max_total[1], + fixedpointScalingFac, + max_enc[1] + max_dec[1], + max_enc[0], + max_enc[1], + max_dec[0], + max_dec[1], + max_total[0], + max_total[1], + newsletterFilenameLast, +) diff --git a/ci/complexity_measurements/style.css b/ci/complexity_measurements/style.css new file mode 100644 index 0000000000000000000000000000000000000000..44fb55de46125fbad0e32bceb11b3395f355fbd1 --- /dev/null +++ b/ci/complexity_measurements/style.css @@ -0,0 +1,220 @@ +body { + background-color:#FFF; + font:.6875em Verdana, Arial, Helvetica, sans-serif; + color:#000; +} +a { + color:#000; + text-decoration:underline; +} +a:hover { + text-decoration:none; +} +h1 { + font-size:2.265em; + font-weight:700; + text-align: center; +} +em { + font-style: normal; + font-weight: bold; +} +hr { + margin-top: 30px; + margin-bottom: 30px; + margin-left: 150px; + margin-right:150px; + height: 0px; + border-top-width: 2px; + border-bottom-width: 0px; + border-left-width: 0px; + border-right-width: 0px; + border-top-style: solid; + color: #606060; +} +.graph { + width: 800px; + height: 350px; +} +.graph-container { + margin: 0 auto; + width:800px; +} +.message-box { + margin-top: 2em; + padding: 1em; + background-color: #FF8000; + border-radius: 20px; +} +#wmops-graph { + height:500px; + width:800px; + float:left; +} +#wmops_per_op-graph { + height:500px; + width:800px; + float:left; +} +#wmops-48kHz-graph { + height:500px; + width:800px; + float:left; +} +#wmops_per_op-48kHz-graph { + height:500px; + width:800px; + float:left; +} +#wmops_basop_per_op-graph { + height:500px; + width:800px; + float:left; +} +#wmops-graph-basop { + height:500px; + width:800px; + float:left; +} +#conversion_factors_basop_flc { + height:500px; + width:800px; + float:left; +} +#ram-graph { + height:500px; + width:800px; + float:left; +} +#ram-graph-basop { + height:500px; + width:800px; + float:left; +} +#rom-graph { + height:500px; + width:800px; + float:left; +} +#rom-graph-basop{ + height:500px; + width:800px; + float:left; +} +#prom-graph { + height:500px; + width:800px; + float:left; +} +#tooltip { + border-radius:.35em; + border-radius:.35em; + background-color:#000; + color:#FFF; + display:none; + opacity:0.8; + padding:.25em; + position:absolute; + box-shadow: 6px 6px 6px #666; +} +#tooltip a:link, #tooltip a:active, #tooltip a:visited { + color:#FFF; + text-decoration: underline; +} +#tooltip a:hover { + color:#FFF; + text-decoration: none; +} +.legend { + display: inline; +} +.legend li { + border-left: 1.2em solid #FFF; + margin-right: 2em; + padding-left: .3em; + margin-bottom: .2em; + list-style-type: none; +} + +#menu { + color: #FFFFFF; +} + +#menu ul { + color: #FFFFFF; + list-style: none; + margin-left: -1em; + position: relative; + margin-top: 1.5em; + margin-bottom: 1.5em; +} + +#menu li { + margin-left: -1em; + margin-bottom: 1.0em; + margin-top: 1.0em; +} + +#menu a { + color: #FFFFFF; +} + +dt { + font-weight: bold; +} + +dd hr { + margin-top: 0.1em; + margin-bottom: 0.1em; + margin-left: 48%; + margin-right: 48%; +} + +#menu { + float: left; + margin-left: 1em; + margin-top: 1em; + width: 22em; + border-radius: 1em; + position: fixed; + background-color: #000000; + opacity: 0.8; + box-shadow: 6px 6px 6px #666; +} + +#content { + margin-left: 17em; +} + +.symbols { + float: right; + font-weight: bolder; + font-size: 2em; + margin-top: -0.4em; +} + +.trafficlight { + margin-right: 0px; + margin-left: 0px; + position: absolute; + right: 2em; + color: #202020; +} + +.trend { + margin-right: 0.5em; + margin-left: 0.2em; +} + +th, td { + padding: 0.5em 2em; + border: 1px solid #606060; +} + +th { + text-align: left; +} + +td#number { + text-align: right; +} diff --git a/ci/disable_ram_counting.py b/ci/disable_ram_counting.py new file mode 100644 index 0000000000000000000000000000000000000000..3c891535081528a249751eed987d88f589e55f9d --- /dev/null +++ b/ci/disable_ram_counting.py @@ -0,0 +1,20 @@ +import re +import os + +FILE_PATH = os.path.join(os.path.dirname(__file__), "..", "lib_com", "options.h") +RE_TO_COMMENT_OUT = re.compile(r"#define\s+RAM_COUNTING_TOOL") + + +def main(): + with open(FILE_PATH, "r", encoding="utf-8") as file: + lines = file.readlines() + + for i, line in enumerate(lines): + lines[i] = RE_TO_COMMENT_OUT.sub(lambda x: f"/* {x.group(0)} */", line) + + with open(FILE_PATH, "w", encoding="utf-8") as file: + file.writelines(lines) + + +if __name__ == "__main__": + main() diff --git a/scripts/ivas_pytests/tests/il2mm.py b/ci/get_id_of_last_job_occurence.py similarity index 54% rename from scripts/ivas_pytests/tests/il2mm.py rename to ci/get_id_of_last_job_occurence.py index eb09593bdbed9b7f347c5107f368c4d2d5410a5d..12294cf9f558da52c5d21ca1319219d03c665d94 100644 --- a/scripts/ivas_pytests/tests/il2mm.py +++ b/ci/get_id_of_last_job_occurence.py @@ -1,5 +1,7 @@ +#!/usr/bin/env python3 + """ - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -28,34 +30,53 @@ the United Nations Convention on Contracts on the International Sales of Goods. """ -import os - - -def il2mm(file_in, num_ch, b_delete=True): - """ - Convert interleaved input file to multiple mono output files. - """ - num_bytes_per_sample = 2 - num_bytes_per_frame = num_bytes_per_sample * num_ch - num_bytes_per_channel = os.path.getsize(file_in) / num_ch - - with open(file_in, "rb") as fid_in: - out_path = os.path.splitext(file_in)[0] - for chan in range(num_ch): - file_out = out_path + str(chan + 1) + "ch.raw" - with open(file_out, "wb") as fid_out: - bytes_written = 0 - offset = chan * num_bytes_per_sample - fid_in.seek(offset, 0) - while bytes_written < num_bytes_per_channel: - data = fid_in.read(num_bytes_per_sample) - fid_in.seek(num_bytes_per_frame - num_bytes_per_sample, 1) - written = fid_out.write(bytes(data)) - assert ( - written == num_bytes_per_sample - ), f"Error writing data: {written} != {num_bytes_per_sample}" - bytes_written += num_bytes_per_sample - - # delete interleaved input file - if b_delete: - os.remove(file_in) +import argparse +import requests + +PER_PAGE_SUFFIX = "?per_page=50" +PAGE_SUFFIX = "&page={}" +API_BASE_URL = "https://forge.3gpp.org/rep/api/v4/projects/49" + + +def get_job_id(branch_name, job_name): + job_id = -1 + # check last 500 pipelines max + for page in range(100): + url_pls = API_BASE_URL + "/pipelines" + + # need both suffixes here to descend through the pages and get also older pipelines + suffix = PER_PAGE_SUFFIX + PAGE_SUFFIX.format(page) + resp_pls = requests.get(url_pls + suffix) + for pl in resp_pls.json(): + if pl["ref"] == branch_name: + url_jobs = url_pls + f"/{pl['id']}/jobs" + + # only one of the suffixes here - this assumes only max of 50 jobs per pipeline + # so only one page needed + resp_jobs = requests.get(url_jobs + PER_PAGE_SUFFIX) + + if job_name not in resp_jobs.text: + continue + + # find actual job by name + for job in resp_jobs.json(): + if job["name"] == job_name and job["status"] == "success": + job_id = job["id"] + break + if job_id >= 0: + break + + if job_id >= 0: + break + + return job_id + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("branch_name") + parser.add_argument("job_name") + + args = parser.parse_args() + + job_id = get_job_id(args.branch_name, args.job_name) + print(job_id) \ No newline at end of file diff --git a/ci/index-pages.html b/ci/index-pages.html new file mode 100644 index 0000000000000000000000000000000000000000..9d60155e8fa9399e35cd4ff862cb99b780909309 --- /dev/null +++ b/ci/index-pages.html @@ -0,0 +1,25 @@ + + + + + +

Ivas Codec Development

+ +

Complexity Reports

+ + + +

Test Coverage

+ + + + diff --git a/ci/ivas_voip_be_test.sh b/ci/ivas_voip_be_test.sh new file mode 100644 index 0000000000000000000000000000000000000000..592451c345541b0e3c2d57424a4171bdbb40d460 --- /dev/null +++ b/ci/ivas_voip_be_test.sh @@ -0,0 +1,144 @@ +#! /usr/bin/bash + +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + +function usage { + echo + echo "Usage:" + echo " ivas_voip_be_test.sh [MODE]" + echo + echo " MODE - test (default) or coverage" + exit +} + +if [ ! -d "lib_com" ]; then + echo "not in root directory! - please run in IVAS root" + exit 1 +fi + +if [ -z "$1" ] || [ "$1" == "test" ]; then + WORKERS="" + BUILD=1 + COVERAGE=0 +elif [ "$1" == "coverage" ]; then + WORKERS="-t 1" + BUILD=0 + COVERAGE=1 +else + usage +fi + +if [ $BUILD -eq 1 ];then + make clean + make all -j +fi + +# Configuration +modes=('SBA_b128_wb_cbr' 'MC_7_1_b96_fb_cbr' 'ISM2_b48_fb_cbr') +output_formats=('STEREO' 'FOA' '7_1' 'HOA3') +limit_input_to_x_seconds=30 + +cfg=./scripts/config/ci_linux.json +dly_profile=./scripts/dly_error_profiles/dly_error_profile_0.dat + +output_dir_default="out" +output_dir_voip="out_voip" + +# Run the same modes in VoIP and non-VoIP mode with a neutral delay profile +./scripts/runIvasCodec.py -p $cfg $WORKERS -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_default | tee voip_be_test_output.txt +./scripts/runIvasCodec.py -p $cfg $WORKERS -U $limit_input_to_x_seconds -m "${modes[@]}" --oc "${output_formats[@]}" -o $output_dir_voip -J "$dly_profile" | tee -a voip_be_test_output.txt + +# Check if Python scripts above failed. They return status 0 even when running a mode fails, so we have to parse log file +if grep -iq failed voip_be_test_output.txt ; then + echo "Run errors in runIvasCodec.py" + exit 1 +fi + +if [ $COVERAGE -eq 1 ];then + # Coverage analysis requires only running the codec and may exit before the comparison part + exit 0 +fi + +# Set up Python path +python_audio_module_path=$(pwd)/scripts +export PYTHONPATH=$python_audio_module_path:$PYTHONPATH +python_audiofile_script_path=$python_audio_module_path/pyaudio3dtools/audiofile.py + +# Trim JBM delay from VoIP output files +output_dir_voip_dec="$output_dir_voip"/dec +output_dir_voip_dec_trimmed="$output_dir_voip"/dec_trimmed + +if [[ ! -d $output_dir_voip_dec_trimmed ]]; then + mkdir $output_dir_voip_dec_trimmed +fi + +for cut in "$output_dir_voip_dec"/*.wav; do + output_path=${cut/$output_dir_voip_dec/$output_dir_voip_dec_trimmed} + output_path=${output_path/".wav"/".raw"} + python3 "$python_audiofile_script_path" pre-trim 60 "$cut" "$output_path" | tee -a voip_be_test_output.txt +done + +# Convert non-VoIP output from wav to pcm (comparison script doesn't support wav) +output_dir_default_dec="$output_dir_default"/dec +output_dir_default_dec_pcm="$output_dir_default"/dec_pcm + +if [[ ! -d $output_dir_default_dec_pcm ]]; then + mkdir $output_dir_default_dec_pcm +fi + +for ref in "$output_dir_default_dec"/*.wav; do + output_path=${ref/$output_dir_default_dec/$output_dir_default_dec_pcm} + output_path=${output_path/".wav"/".raw"} + python3 "$python_audiofile_script_path" convert "$ref" "$output_path" | tee -a voip_be_test_output.txt +done + +# Assert BE between non-VoIP and VoIP modes +all_be=1 + +cmp_tool_path=$(pwd)/tests/cmp_pcm.py + +for ref in "$output_dir_default_dec_pcm"/*; do + cut=${ref/$output_dir_default_dec_pcm/$output_dir_voip_dec_trimmed} + cut=${cut/".dec."/"_jbm_dly_error_profile_0_dat.dec."} + + # Print paths of compared files, since the script doesn't do it + printf "\nComparing %s and %s\n" "$ref" "$cut" | tee -a voip_be_test_output.txt + printout=$($cmp_tool_path "$ref" "$cut") + if [ $? -ne 0 ]; then + all_be=0 + fi + printf "%s\n" "$printout" | tee -a voip_be_test_output.txt +done + +if [ $all_be -eq 1 ]; then + printf "\n\nAll tested conditions are bit-exact\n" | tee -a voip_be_test_output.txt +else + printf "\n\nBitexactness problems found!\n" | tee -a voip_be_test_output.txt + exit 1; +fi diff --git a/ci/run_evs_be_test.py b/ci/run_evs_be_test.py new file mode 100644 index 0000000000000000000000000000000000000000..f7b705b0f47e100ead67786d6730f7024461ebc9 --- /dev/null +++ b/ci/run_evs_be_test.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +""" + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. +""" +import subprocess +import pathlib +import sys +import concurrent.futures +from threading import Lock + + +README_FILES_PARALLEL = [ + "Readme_AMRWB_IO_enc.txt", + "Readme_AMRWB_IO_dec.txt", + "Readme_EVS_enc.txt", + "Readme_EVS_dec.txt", +] +README_FILES_JBM = ["Readme_JBM_dec.txt"] +README_FILES = README_FILES_PARALLEL + README_FILES_JBM +BINARY_PATHS = ["./bin/EVS_cod", "./bin/EVS_dec"] +FOLDER_PATHS = ["testv"] +BIN_PATHS = BINARY_PATHS * 2 + +def main(): + + if not environment_is_correct(): + return 1 + + result_dict = dict() + # run first part in parallel + with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor: + executor.map( + run_file, README_FILES_PARALLEL, BIN_PATHS, [result_dict] * len(README_FILES_PARALLEL) + ) + + # JBM test can not run concurrently with the others + run_file(README_FILES_JBM[0], BINARY_PATHS[1], result_dict) + + return analyze_results(result_dict) + + +def analyze_results(result_dict): + ret = 0 + + for filename, ret_code in result_dict.items(): + if ret_code != 0: + print(f"========= Test for {filename} failed! See log below: ==========") + with open(filename.replace("Readme", "Log")) as f: + print(f.read()) + ret = 1 + + return ret + + +def run_file(filename: str, bin_path: str, result_dict: dict): + ret_code = subprocess.call(["bash", filename, bin_path]) + with Lock(): + result_dict[filename] = ret_code + + +def environment_is_correct(): + """ + Check that the folder with the test resources is set up correctly: + - all Readme files there + - EVS binaries available in bin/ + - testv and switchPaths folder exist - Content is not checked, though + """ + ret = True + + for path in README_FILES + BINARY_PATHS + FOLDER_PATHS: + if not pathlib.Path(path).exists(): + print(f"Environment setup is incorrect - {path} not found.") + ret = False + + return ret + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/ci/run_scheduled_sanitizer_test.py b/ci/run_scheduled_sanitizer_test.py new file mode 100644 index 0000000000000000000000000000000000000000..aa6f2636a44848c9505034aac8f2511961bfc66a --- /dev/null +++ b/ci/run_scheduled_sanitizer_test.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python3 +""" + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import argparse +import sys +import subprocess +import pathlib + +CI_SCRIPT_DIR = "./ci" +sys.path.append(CI_SCRIPT_DIR) +from collect_artifacts import ( + find_failed_files_for_sanitizer_test, + collect_for_sanitizer_test, +) + + +DURATION = "120" +CFG = "ci_linux_ltv.json" +SUPPORTED_TESTS = ["CLANG1", "CLANG2", "CLANG3", "VALGRIND"] +EP_FILE = "ep_015.g192" +GENPATT_CMD = f"gen-patt -tailstat -fer -g192 -gamma 0 -rate 0.15 -tol 0.001 -reset -n {int(DURATION) * 50} {EP_FILE}" +EIDXOR_CMD = "eid-xor -vbr -fer {bitstream} {ep_file} {out_file}" +MC_MODES = ["5_1", "5_1_2", "5_1_4", "7_1", "7_1_4"] + +SCRIPT_DIR = pathlib.Path("./scripts").resolve() + +CONSOLE_OUT_FILE = "output_san.txt" + + +def main(args): + in_format = args.in_format + out_formats = args.out_formats + tests = args.tests + run_fec = not args.skip_fec + + assert all([t in SUPPORTED_TESTS for t in tests]) + + modes = get_modes(in_format) + returncode = run_check(modes, out_formats, tests, run_fec=run_fec) + + collect_for_sanitizer_test(CONSOLE_OUT_FILE) + + sys.exit(returncode) + + +def get_modes(in_format: str) -> list: + + cmd = [ + SCRIPT_DIR.joinpath("runIvasCodec.py"), + "-C", + "MC" if in_format in MC_MODES else in_format, + "-l", + ] + list_process = subprocess.run(cmd, capture_output=True) + + output = list_process.stdout.decode("utf8") + mode_list = output.splitlines() + + # correction for multichannel modes to avoid selecting some mono modes... + if in_format in MC_MODES: + in_format = "MC_" + in_format + "_b" + mode_list = [m for m in mode_list if in_format in m] + + return mode_list + + +def run_check(modes: list, out_formats: list, tests: list, run_fec: bool = True): + + ### always run encoder and decoder with no frameloss + cmd_no_fec = [ + str(SCRIPT_DIR.joinpath("IvasBuildAndRunChecks.py")), + "-U", + DURATION, + "-p", + CFG, + "--checks", + *tests, + "-m", + *modes, + "--oc", + *out_formats, + ] + + print( + "======== Script command line WITHOUT plc: ========\n{}".format( + " ".join(cmd_no_fec) + ) + ) + + with open(CONSOLE_OUT_FILE, "w") as f: + proc = subprocess.Popen( + cmd_no_fec, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + for c in iter(lambda: proc.stdout.read(1), b""): + sys.stdout.buffer.write(c) + f.write(c.decode("utf8")) + proc.wait() + + returncode_no_fec = proc.returncode + print("returncode_no_fec:", returncode_no_fec) + if returncode_no_fec not in [0, 101]: + raise IvasBuildAndRunFailed("Failed at first run (no PLC)") + + if not run_fec: + return returncode_no_fec + + # delete bitstream files for all failed modes to prevent follow-up errors in decoder-only run + with open(CONSOLE_OUT_FILE) as f: + console_log = f.readlines() + failed_files = find_failed_files_for_sanitizer_test( + console_log, "logs", "FILE_BASENAMES" + ) + for t in failed_files.keys(): + bs_folder = pathlib.Path(f"{t}/enc") + file_starts = failed_files[t] + for f in bs_folder.iterdir(): + for fs in file_starts: + if f.name.startswith(fs): + f.unlink() + + ### second run: decoder only with disturbed bitstream + + # generate error pattern + subprocess.call(GENPATT_CMD.split()) + + # cleanup to avoid script errors + # we want "logs" and "dec" subfolders to be empty -> delete "dec" and rename "log" + # to keep the log files from the first run with no frame losses + folders_to_delete = ["dec"] + folders_to_backup = ["logs"] + for t in tests: + for fol in folders_to_delete: + for fi in pathlib.Path(t).joinpath(fol).iterdir(): + fi.unlink() + for fol in folders_to_backup: + path = pathlib.Path(t).joinpath(fol) + new_name = pathlib.Path(str(path) + "_noPLC") + path.rename(new_name) + # need empty log folder to avoid crashes + path.mkdir() + + cmd_fec = cmd_no_fec + ["--decoder_only", "-f", EP_FILE] + print( + "======== Script command line WITH plc: ========\n{}".format( + " ".join(cmd_no_fec) + ) + ) + + with open(CONSOLE_OUT_FILE, "a") as f: + proc = subprocess.Popen( + cmd_fec, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + for c in iter(lambda: proc.stdout.read(1), b""): + sys.stdout.buffer.write(c) + f.write(c.decode("utf8")) + proc.wait() + + returncode_fec = proc.returncode + print("returncode_fec:", returncode_fec) + + if returncode_fec not in [0, 101]: + raise IvasBuildAndRunFailed("failed at second run (PLC)") + + return 101 if 101 in [returncode_no_fec, returncode_fec] else 0 + + +class IvasBuildAndRunFailed(Exception): + pass + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("in_format", type=str) + parser.add_argument("out_formats", type=str, nargs="+") + parser.add_argument("--tests", type=str, nargs="+", default=["CLANG1", "CLANG2"]) + parser.add_argument("--skip_fec", action="store_true") + + sys.exit(main(parser.parse_args())) diff --git a/ci/setup_pages.py b/ci/setup_pages.py new file mode 100644 index 0000000000000000000000000000000000000000..a8dffafa1387f1b770cc783420fe1b444c2a7249 --- /dev/null +++ b/ci/setup_pages.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +import os +import sys +import pathlib +import subprocess +from get_id_of_last_job_occurence import get_job_id + +JOBS = [ + "complexity-stereo-in-stereo-out", + "complexity-ism-in-binaural-out", + "complexity-sba-hoa3-in-hoa3-out", + "complexity-mc-in-7_1_4-out", + "complexity-masa-in-7_1_4-out", + "complexity-StereoDmxEVS-stereo-in-mono-out", + "coverage-test-on-main-scheduled", +] +ARTIFACTS = "artifacts.zip" +API_URL_BASE = "https://forge.3gpp.org/rep/api/v4/projects/{}/jobs" +PUBLIC = "./public" + + +def main(): + + public_folder = pathlib.Path(PUBLIC) + public_folder.mkdir() + + failed_count = 0 + for job in JOBS: + job_id = get_job_id(os.environ["CI_COMMIT_REF_NAME"], job) + print(f"{job_id} - {job}") + try: + curl_for_artifacts(job_id) + + job_public = job + "-public" + if job == "coverage-test-on-main-scheduled": + job_public = "coverage" + + pathlib.Path(job_public).rename(public_folder.joinpath(job_public)) + + except subprocess.CalledProcessError: + print(f"Could not get artifacts for {job}") + failed_count += 1 + + if failed_count == len(JOBS): + sys.exit(1) + + pathlib.Path("ci/index-pages.html").rename(public_folder.joinpath("index.html")) + sys.exit(0) + + +def curl_for_artifacts(job_id): + cmd = [ + "curl", + "--request", + "GET", + API_URL_BASE.format(os.environ["CI_PROJECT_ID"]) + f"/{job_id}/artifacts", + "--output", + ARTIFACTS, + ] + subprocess.run(cmd, check=True) + + # check for valid archive (if not, it is likely a 404 page, then display that) + cmd = ["unzip", "-t", ARTIFACTS] + try: + subprocess.run(cmd, check=True) + except subprocess.CalledProcessError: + with open(ARTIFACTS, "r") as f: + print(f.read()) + raise subprocess.CalledProcessError(-1, "Unzip check failed") + + # do the actual unzipping + cmd = ["unzip", ARTIFACTS] + subprocess.run(cmd, check=True) + + +if __name__ == "__main__": + main() diff --git a/ci/smoke_test.sh b/ci/smoke_test.sh index 9c423d4eece0ddba6716fcab32562d800a627a29..2062ff5080ff142aefd158454b14ab349387f3c0 100755 --- a/ci/smoke_test.sh +++ b/ci/smoke_test.sh @@ -1,13 +1,100 @@ #! /usr/bin/bash +# (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository. All Rights Reserved. + +# This software is protected by copyright law and by international treaties. +# The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +# Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +# Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +# Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +# contributors to this repository retain full ownership rights in their respective contributions in +# the software. This notice grants no license of any kind, including but not limited to patent +# license, nor is any license granted by implication, estoppel or otherwise. + +# Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +# contributions. + +# This software is provided "AS IS", without any express or implied warranties. The software is in the +# development stage. It is intended exclusively for experts who have experience with such software and +# solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +# and fitness for a particular purpose are hereby disclaimed and excluded. + +# Any dispute, controversy or claim arising under or in relation to providing this software shall be +# submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +# accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +# the United Nations Convention on Contracts on the International Sales of Goods. + +function usage { + echo + echo "Usage:" + echo " smoke_test.sh [MODE]" + echo + echo " MODE - test (default) or coverage" + exit +} + if [ ! -d "lib_com" ]; then echo "not in root directory! - please run in IVAS root" exit 1 fi -make clean -make all -j +if [ -z "$1" ] || [ "$1" == "test" ]; then + WORKERS="" + BUILD=1 +elif [ "$1" == "coverage" ]; then + WORKERS="-t 1" + BUILD=0 +else + usage +fi + + +cfg=./scripts/config/ci_linux.json +dly_profile=./scripts/dly_error_profiles/dly_error_profile_10.dat + +if [ $BUILD -eq 1 ];then + # Enable memory macros to find unbalanced memory allocations/deallocations + # Does not implement full memory analysis + make clean + + # Replace free -> free_, malloc -> malloc_, calloc -> calloc_ + ./scripts/prepare_mem_dryrun.py + + # Enable WMOPS and disable DEBUGGING + sed -i.bak -e "s/\/\*\s*\(#define\s*WMOPS\)\s*\*\//\1/g" lib_com/options.h + sed -i.bak -e "s/\/\/\s*\(#define\s*WMOPS\)/\1/g" lib_com/options.h +# sed -i.bak -e "s/\s*\(#define\s*DEBUGGING\)/\/\*\1*\//g" lib_com/options.h + + make all -j + +fi + +# run all modes vanilla-fashion +./scripts/runIvasCodec.py -p $cfg -U 1 $WORKERS | tee smoke_test_output.txt +# run the decoding again, but with 15% frame loss +./scripts/runIvasCodec.py -p $cfg -U 1 $WORKERS -D="-fec 15" --decoder_only | tee smoke_test_output_plc.txt + +# run JBM modes - EXT is excluded as not supported yet +modes_with_no_ext_out=$(./scripts/runIvasCodec.py -l | grep -v MASA | grep -v ISM) +./scripts/runIvasCodec.py -m $modes_with_no_ext_out -p $cfg -U 1 $WORKERS --decoder_only --jbm_file $dly_profile | tee smoke_test_output_jbm_noEXT.txt +./scripts/runIvasCodec.py -C MASA ISM1 ISM2 ISM3 ISM4 -p $cfg -U 1 $WORKERS --decoder_only --jbm_file $dly_profile --oc BINAURAL BINAURAL_ROOM mono stereo FOA HOA3 5_1 7_1_4 | tee -a smoke_test_output_jbm_noEXT.txt + +# run all modes with binaural output using external files +modes_with_bin_out="SBA PlanarSBA MASA MC ISM1 ISM2 ISM3 ISM4" +bin_out_modes="BINAURAL BINAURAL_ROOM" + +wb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _wb_) +hrtf_wb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_16kHz.bin" +./scripts/runIvasCodec.py -p $cfg -m $wb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_wb}" --decoder_only --oc $bin_out_modes | tee -a smoke_test_output_hrtf.txt + +swb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _swb_) +hrtf_swb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_32kHz.bin" +./scripts/runIvasCodec.py -p $cfg -m $swb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_swb}" --decoder_only --oc $bin_out_modes | tee -a smoke_test_output_hrtf.txt -# get all modes except SBA rate switching (which is broken currently) -list=$(./scripts/runIvasCodec.py -l | grep -v "SBA.*rs") -./scripts/runIvasCodec.py -p ./scripts/config/ci_linux.json -m $list -U 1 +fb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _fb_) +hrtf_fb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_48kHz.bin" +./scripts/runIvasCodec.py -p $cfg -m $fb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_fb}" --decoder_only --oc $bin_out_modes | tee -a smoke_test_output_hrtf.txt diff --git a/lib_com/ACcontextMapping.c b/lib_com/ACcontextMapping.c index 27c51eb17920d51fee780f4f08c09838b6e38a51..1705a3f7d353a66d075e8aedba7e096bbf8e241f 100644 --- a/lib_com/ACcontextMapping.c +++ b/lib_com/ACcontextMapping.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * get_next_coeff_mapped() diff --git a/lib_com/ari.c b/lib_com/ari.c index 3b7ccfd9a41b3688e587d3237e0d04f7f1b48d05..2ee0be62310edc98d315593d6f269ca2529a6423 100644 --- a/lib_com/ari.c +++ b/lib_com/ari.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "prot.h" #include "basop_util.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- diff --git a/lib_com/ari_hm.c b/lib_com/ari_hm.c index 78e639ea91d95dbcfe2904ff15a2722d6f957659..f1f9d5a42b213ddeb1a4050607d530af740a1236 100644 --- a/lib_com/ari_hm.c +++ b/lib_com/ari_hm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "basop_util.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * UnmapIndex() @@ -196,7 +196,7 @@ int16_t CountIndexBits( return 8; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /*-------------------------------------------------------------------* * tcx_hm_render() @@ -301,3 +301,5 @@ void tcx_hm_modify_envelope( return; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/arith_coder.c b/lib_com/arith_coder.c index e534a23e04a7b57ddcac4d93293daf4ad812c59d..1912b4cbf279d6130a558a8486542b2702272ace 100644 --- a/lib_com/arith_coder.c +++ b/lib_com/arith_coder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,10 +45,11 @@ #include "prot.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP + /*-------------------------------------------------------* * expfp() * @@ -573,3 +574,5 @@ void tcx_arith_render_envelope( return; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop32.c b/lib_com/basop32.c index b12e336e9c7aff2c033587ac3294198520160919..1f28351c7922a05a9c5c2ef2d48db2d2ec969161 100644 --- a/lib_com/basop32.c +++ b/lib_com/basop32.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,7 +30,6 @@ *******************************************************************************************************/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ /* v.2.3 - 30.Nov.2009 ============================================================================= @@ -167,6 +166,8 @@ HISTORY: #include "ivas_error.h" #include "ivas_error_utils.h" +#define WMC_TOOL_SKIP + #ifdef _MSC_VER #pragma warning( disable : 4310 ) #endif @@ -3203,4 +3204,4 @@ Word32 L_msu0( Word32 L_var3, Word16 var1, Word16 var2 ) #endif /* ! BASOP_NOGLOB */ -/* end of file */ +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop32.h b/lib_com/basop32.h index f1bd65bc8e1c2b871ccb6f3adf15008867f47a93..ff41a1d81da38fc2da042eb48464986c3ae76ae8 100644 --- a/lib_com/basop32.h +++ b/lib_com/basop32.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/basop_com_lpc.c b/lib_com/basop_com_lpc.c index a24c100d54194aea6d1e68ffa944180ed912fa50..442afe554c1e02eeaa23c7b5e5370018c806ce8f 100644 --- a/lib_com/basop_com_lpc.c +++ b/lib_com/basop_com_lpc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ #include #include @@ -41,10 +40,11 @@ #include "typedef.h" #include "basop_proto_func.h" #include "cnst.h" - #include "basop_util.h" #include "stl.h" +#define WMC_TOOL_SKIP + #define UNROLL_CHEBYSHEV_INNER_LOOP #define NC_MAX 8 #define GUESS_TBL_SZ 256 @@ -259,3 +259,5 @@ void basop_lsf2lsp( const Word16 lsf[], Word16 lsp[] ) return; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_lsf_tools.c b/lib_com/basop_lsf_tools.c index 7a7e655f8105b17a8fc431af6a03010356774dfa..eddce99e83929a2ae105b6117512512f20fd1880 100644 --- a/lib_com/basop_lsf_tools.c +++ b/lib_com/basop_lsf_tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ #include #include @@ -42,6 +41,8 @@ #include "control.h" #include "basop_util.h" +#define WMC_TOOL_SKIP + #define NC_MAX 8 static Word16 E_LPC_f_lsp_pol_get( const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1 ); @@ -309,3 +310,5 @@ static Word16 E_LPC_f_lsp_pol_get( } return Ovf; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_mpy.c b/lib_com/basop_mpy.c index 478dff4cfe26010a55d055919b511f43f72b34d5..db2a14c0b08d33792d79ebb389e3f6ac468c54e5 100644 --- a/lib_com/basop_mpy.c +++ b/lib_com/basop_mpy.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ #include "basop_mpy.h" #include @@ -42,6 +41,8 @@ #include "debug.h" #endif +#define WMC_TOOL_SKIP + Word32 Mpy_32_16_1( Word32 x, Word16 y ) { Word32 mh; @@ -87,3 +88,5 @@ Word32 Mpy_32_32( Word32 x, Word32 y ) return ( mh ); } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_mpy.h b/lib_com/basop_mpy.h index 699039dd1564b181880b73a7f709a4f0c5a0313e..4a8d4473c65b7d2df22393ac2f75de4c1479101f 100644 --- a/lib_com/basop_mpy.h +++ b/lib_com/basop_mpy.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/basop_proto_func.h b/lib_com/basop_proto_func.h index 19337e9a5284d07bafd27d96ee1965854515d4a0..0c514475f324d6a587142fb07f75d6648a816986 100644 --- a/lib_com/basop_proto_func.h +++ b/lib_com/basop_proto_func.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -57,7 +57,7 @@ void basop_lsf2lsp( const Word16 lsf[], Word16 lsp[] ); void basop_weight_a( const Word16 *a, Word16 *ap, const Word16 gamma ); void basop_weight_a_inv( const Word16 *a, Word16 *ap, const Word16 inv_gamma ); void basop_E_LPC_a_add_tilt( const Word16 *a, Word16 *ap, Word16 gamma ); -void basop_reorder_lsf( Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 fs ); +void basop_reorder_lsf( Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 Fs ); void basop_E_LPC_f_lsp_a_conversion( const Word16 *lsp, Word16 *a, const Word16 m ); /* tcx_utils.c */ diff --git a/lib_com/basop_settings.h b/lib_com/basop_settings.h index 0689fa419ddaf03563fb4541bfccad9db505e3c4..758a99650cea4a0a7c0fc7ca59c4bab70953dbf0 100644 --- a/lib_com/basop_settings.h +++ b/lib_com/basop_settings.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/basop_tcx_utils.c b/lib_com/basop_tcx_utils.c index ea306d34b28018d647bfd7d523711e814f9641ff..6d2c80f6b74c3cc635e40226eeb756e676faee0c 100644 --- a/lib_com/basop_tcx_utils.c +++ b/lib_com/basop_tcx_utils.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ #include #include @@ -47,6 +46,8 @@ #include "prot.h" #include "rom_com.h" +#define WMC_TOOL_SKIP + /* compare two positive normalized 16 bit mantissa/exponent values */ /* return value: positive if first value greater, negative if second value greater, zero if equal */ static Word16 compMantExp16Unorm( Word16 m1, Word16 e1, Word16 m2, Word16 e2 ) @@ -436,3 +437,5 @@ void basop_PsychAdaptLowFreqDeemph( Word32 x[], const Word16 lpcGains[], const W } } } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c index 71feed1276a96d36445669b05d6d1f4b4ac1f541..bfd05e09e2b7c2d942d3dee75965eabcfb071a89 100644 --- a/lib_com/basop_util.c +++ b/lib_com/basop_util.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ #include #include @@ -48,6 +47,8 @@ #include "control.h" #include "cnst.h" +#define WMC_TOOL_SKIP + extern const Word32 SqrtTable[32]; extern const Word16 SqrtDiffTable[32]; @@ -1107,3 +1108,5 @@ Word32 Sqrt_l( return ( L_y ); } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h index 3ab56150344db60810211d51e3975a67ec1d5d64..c09b8ea62ca4e8321ef2227978afb9df7aac680d 100644 --- a/lib_com/basop_util.h +++ b/lib_com/basop_util.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/bitalloc.c b/lib_com/bitalloc.c index 97acd28c58324406a85e835da7b3b30ff6159b23..e8db20d13373e10b69cec977df5eeb4f2708cb71 100644 --- a/lib_com/bitalloc.c +++ b/lib_com/bitalloc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * bitalloc() @@ -221,7 +221,8 @@ void bitalloc( } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP + /*-------------------------------------------------------------------* * BitAllocF() * @@ -1020,3 +1021,5 @@ int16_t BitAllocWB( return (Word16) t_fx; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/bitallocsum.c b/lib_com/bitallocsum.c index 124bf69fe5119fce2093c315560956749d49017a..d3f880752d9bb05ef5a823cd574835946bdf5b42 100644 --- a/lib_com/bitallocsum.c +++ b/lib_com/bitallocsum.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * bitallocsum() diff --git a/lib_com/bits_alloc.c b/lib_com/bits_alloc.c index 3673a4f5fefbc211c31734bfe2bfa41c54f39591..41acc25b48329646c859750c26c8ff86a9f049a4 100644 --- a/lib_com/bits_alloc.c +++ b/lib_com/bits_alloc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -525,7 +525,7 @@ ivas_error config_acelp1( const int16_t L_frame, /* i : frame length at internal Fs */ const int16_t GSC_noisy_speech, /* i : GSC on SWB noisy speech flag */ ACELP_config *acelp_cfg, /* i : ACELP bit-allocation */ - const int16_t signalling_bits, /* i : number of signalling bits */ + const int16_t signaling_bits, /* i : number of signaling bits */ const int16_t coder_type, /* i : coder type */ const int16_t tc_subfr, /* i : TC subfr ID */ const int16_t tc_call, /* i : TC call number (0,1,2,3,5(DEC)) */ @@ -663,7 +663,7 @@ ivas_error config_acelp1( bits += *nBits_es_Pred; /* equalize for 4th signaling bit estimated at the encoder in TC_0_192 */ } - /* Subtract signalling bits */ + /* Subtract signaling bits */ if ( enc_dec == DEC && idchan == 1 && element_mode > EVS_MONO ) { bits -= TDM_SIGNAL_BITS_READ_FROM_THE_END_OF_BS; @@ -681,13 +681,13 @@ ivas_error config_acelp1( } else { - /* Subtract signalling bits */ - bits -= signalling_bits; + /* Subtract signaling bits */ + bits -= signaling_bits; } if ( extl_brate > 0 && ( extl == WB_TBE || extl == SWB_TBE || extl == FB_TBE || extl == WB_BWE || extl == SWB_BWE || extl == FB_BWE ) ) { - /* extension layer signalling bit is counted in the extension layer bitbudget */ + /* extension layer signaling bit is counted in the extension layer bitbudget */ bits++; } @@ -896,14 +896,14 @@ ivas_error config_acelp1( fix_first = 1; } - /* TC signalling */ + /* TC signaling */ if ( L_frame == L_FRAME ) { if ( tc_subfr == TC_0_0 ) { if ( enc_dec == ENC ) { - bits -= 1; /* TC signalling */ + bits -= 1; /* TC signaling */ } if ( acelp_cfg->ltf_mode == NORMAL_OPERATION ) @@ -915,7 +915,7 @@ ivas_error config_acelp1( { if ( enc_dec == ENC ) { - bits -= 4; /* TC signalling */ + bits -= 4; /* TC signaling */ } if ( acelp_cfg->ltf_mode == NORMAL_OPERATION ) @@ -927,7 +927,7 @@ ivas_error config_acelp1( { if ( enc_dec == ENC ) { - bits -= 4; /* TC signalling */ + bits -= 4; /* TC signaling */ } if ( acelp_cfg->ltf_mode == NORMAL_OPERATION ) @@ -939,7 +939,7 @@ ivas_error config_acelp1( { if ( enc_dec == ENC ) { - bits -= 3; /* TC signalling */ + bits -= 3; /* TC signaling */ } if ( acelp_cfg->ltf_mode == NORMAL_OPERATION ) @@ -951,7 +951,7 @@ ivas_error config_acelp1( { if ( enc_dec == ENC ) { - bits -= 3; /* TC signalling */ + bits -= 3; /* TC signaling */ } if ( acelp_cfg->ltf_mode == NORMAL_OPERATION ) @@ -963,7 +963,7 @@ ivas_error config_acelp1( { if ( enc_dec == ENC ) { - bits -= 4; /* TC signalling */ + bits -= 4; /* TC signaling */ } if ( acelp_cfg->ltf_mode == NORMAL_OPERATION ) @@ -978,11 +978,11 @@ ivas_error config_acelp1( { if ( tc_subfr <= 2 * L_SUBFR ) { - bits -= 2; /* TC signalling */ + bits -= 2; /* TC signaling */ } else { - bits -= 3; /* TC signalling */ + bits -= 3; /* TC signaling */ } } diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c index 1e36dbb5356f410db142417f730da72d32bbdb07..e6213877b8129413e47a1ac7fd06598c9194b9d3 100644 --- a/lib_com/bitstream.c +++ b/lib_com/bitstream.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -49,7 +49,7 @@ #include "ivas_prot.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUGGING @@ -622,7 +622,7 @@ uint16_t get_indice_1( return st->bit_stream[pos]; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /*-------------------------------------------------------------------* * reset_indices_enc() @@ -833,12 +833,13 @@ static ivas_error write_indices_element( /* restore previous pointer position */ pt_stream_loc = pt_stream_backup; } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE /* TODO implemented only for MCT for now */ if ( ( st_ivas->hEncoderConfig->ivas_format == MC_FORMAT ) && ( st_ivas->mc_mode == MC_MODE_MCT ) && ( element_id * CPE_CHANNELS + n == LFE_CHANNEL ) ) { continue; } +#endif #ifdef ENABLE_BITRATE_VERIFICATION total_nb_bits = #endif @@ -879,10 +880,6 @@ static ivas_error write_indices_element( for ( n = 0; n < n_channels; n++ ) { - if ( ( st_ivas->hEncoderConfig->ivas_format == MC_FORMAT ) && ( st_ivas->mc_mode == MC_MODE_MCT ) && ( element_id * CPE_CHANNELS + n == LFE_CHANNEL ) ) - { - continue; - } reset_indices_enc( sts[n]->hBstr, MAX_NUM_INDICES ); } } @@ -1244,7 +1241,7 @@ static void dec_prm_core( /*-----------------------------------------------------------------* * decision_matrix_core_dec() * - * Read core signalling bits from the bitstream + * Read core signaling bits from the bitstream * Set st->core, and st->bwidth if signalled together with the core. *-----------------------------------------------------------------*/ @@ -1291,12 +1288,12 @@ static void decision_matrix_core_dec( } /*-----------------------------------------------------------------* - * Read ACELP signalling bits from the bitstream + * Read ACELP signaling bits from the bitstream *-----------------------------------------------------------------*/ if ( st->core == ACELP_CORE ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ start_idx = 0; while ( acelp_sig_tbl[start_idx] != st->total_brate ) { @@ -1312,11 +1309,11 @@ static void decision_matrix_core_dec( /* retrieve the number of bits */ nBits = (int16_t) acelp_sig_tbl[start_idx++]; - /* retrieve the signalling indice */ + /* retrieve the signaling indice */ ind = acelp_sig_tbl[start_idx + get_next_indice( st, nBits )]; st->bwidth = ( ind >> 3 ) & 0x7; - /* convert signalling indice into signalling information */ + /* convert signaling indice into signaling information */ if ( ( ind & 0x7 ) == LR_MDCT ) { st->core = HQ_CORE; @@ -1324,7 +1321,7 @@ static void decision_matrix_core_dec( } /*-----------------------------------------------------------------* - * Read HQ signalling bits from the bitstream + * Read HQ signaling bits from the bitstream * Set HQ core type *-----------------------------------------------------------------*/ @@ -1811,7 +1808,11 @@ ivas_error preview_indices( if ( bit_stream[2] == 0 ) { st_ivas->ivas_format = SBA_FORMAT; +#ifndef LBR_SBA st_ivas->sba_mode = ivas_sba_mode_select( total_brate ); +#else + st_ivas->sba_mode = ivas_sba_mode_select( ); +#endif } else { @@ -1820,7 +1821,7 @@ ivas_error preview_indices( break; } } - else if ( total_brate == IVAS_SID_4k4 ) + else if ( total_brate == IVAS_SID_5k2 ) { /* read SID format */ st_ivas->sid_format = 0; @@ -1849,7 +1850,7 @@ ivas_error preview_indices( break; case SID_ISM: st_ivas->ivas_format = ISM_FORMAT; - /* temporary hack to make mode signalling work with the current 1-object ISM DTX: read padding bits */ + /* temporary hack to make mode signaling work with the current 1-object ISM DTX: read padding bits */ /* Todo: how to apply this here? maybe pt_stream += ... would work? */ /* st->bit_stream += ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; */ break; @@ -1884,14 +1885,6 @@ ivas_error preview_indices( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Invalid value %c found in SID format field.", st_ivas->sid_format ); } } - else if ( total_brate == IVAS_SID_5k ) - { - /* SBA SID frame */ - st_ivas->sid_format = SID_SBA_1TC; - st_ivas->ivas_format = SBA_FORMAT; - st_ivas->sba_mode = SBA_MODE_SPAR; - st_ivas->element_mode_init = IVAS_SCE; - } /* only read element mode from active frames */ if ( is_DTXrate( total_brate ) == 0 ) @@ -1958,16 +1951,12 @@ ivas_error preview_indices( /* read number of objects from the bitstream */ st_ivas->nchan_transport = 1; - if ( total_brate != SID_2k40 && total_brate != FRAME_NO_DATA ) + k = (int16_t) ( ( total_brate / FRAMES_PER_SEC ) - 1 ); + while ( bit_stream[k] == 1 && st_ivas->nchan_transport < MAX_NUM_OBJECTS ) { - k = (int16_t) ( ( total_brate / FRAMES_PER_SEC ) - 1 ); - while ( bit_stream[k] == 1 && st_ivas->hDecoderConfig->nchan_out < MAX_NUM_OBJECTS ) - { - st_ivas->nchan_transport++; - k--; - } + st_ivas->nchan_transport++; + k--; } - st_ivas->transport_config = AUDIO_CONFIG_EXTERNAL + st_ivas->nchan_transport; st_ivas->ism_mode = ivas_ism_mode_select( st_ivas->nchan_transport, total_brate ); @@ -1975,20 +1964,14 @@ ivas_error preview_indices( } else if ( st_ivas->ivas_format == SBA_FORMAT ) { - if ( ( st_ivas->sba_mode != SBA_MODE_SPAR ) || ( ( st_ivas->sba_mode == SBA_MODE_SPAR ) && ( total_brate >= IVAS_256k ) ) ) - { - /* Read SBA planar flag and SBA order */ - st_ivas->sba_planar = ( bit_stream[IVAS_FORMAT_SIGNALING_NBITS_SBA] == 1 ); - st_ivas->sba_order = ( bit_stream[IVAS_FORMAT_SIGNALING_NBITS_SBA + 2] == 1 ); - st_ivas->sba_order += 2 * ( bit_stream[IVAS_FORMAT_SIGNALING_NBITS_SBA + 1] == 1 ); - } - else - { - st_ivas->sba_planar = 0; - st_ivas->sba_order = 1; - } + /* Read SBA planar flag and SBA order */ + st_ivas->sba_planar = ( bit_stream[IVAS_FORMAT_SIGNALING_NBITS_SBA] == 1 ); + st_ivas->sba_order = ( bit_stream[IVAS_FORMAT_SIGNALING_NBITS_SBA + 2] == 1 ); + st_ivas->sba_order += 2 * ( bit_stream[IVAS_FORMAT_SIGNALING_NBITS_SBA + 1] == 1 ); - ivas_sba_config( total_brate, st_ivas->sba_order, -1, &( st_ivas->nchan_transport ), st_ivas->sba_planar, &( st_ivas->nSCE ), &( st_ivas->nCPE ), &( st_ivas->element_mode_init ), st_ivas->sba_mode ); + st_ivas->sba_analysis_order = ivas_sba_get_analysis_order( total_brate, st_ivas->sba_order ); + + ivas_sba_config( total_brate, st_ivas->sba_analysis_order, -1, &( st_ivas->nchan_transport ), st_ivas->sba_planar, &( st_ivas->nSCE ), &( st_ivas->nCPE ), &( st_ivas->element_mode_init ) ); } } @@ -2034,7 +2017,7 @@ ivas_error read_indices( file_read_FECpattern( &st_ivas->bfi ); st_ivas->bfi |= bfi; - if ( bfi ) + if ( bfi == FRAMEMODE_MISSING ) /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ { for ( k = 0; k < num_bits; k++ ) { @@ -2068,15 +2051,7 @@ ivas_error read_indices( } else if ( k == SIZE_IVAS_BRATE_TBL ) { - /*temp change for spar DTX*/ - if ( total_brate == IVAS_SID_5k ) - { - st_ivas->element_mode_init = -1; - } - else - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error, illegal bitrate (%d) in the G.192 frame ! Exiting ! \n", total_brate ); - } + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error, illegal bitrate (%d) in the G.192 frame ! Exiting ! \n", total_brate ); } else { @@ -2121,7 +2096,7 @@ ivas_error read_indices( } else { - sid_upd_bad = 1; /* this frame type may happen in ETSI/3GPP CS cases , a corrupt sid frames */ + sid_upd_bad = 1; /* this frame type may happen in ETSI/3GPP CS cases, a corrupt SID frames */ } } @@ -2206,9 +2181,11 @@ ivas_error read_indices( /* total_brate= 0 */ } - /* handle bad/lost speech frame(and CS bad sid frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ - if ( ( ( *CNG != 0 ) && ( ( speech_bad != 0 ) || ( speech_lost != 0 ) ) ) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ - ( sid_upd_bad != 0 ) ) /* SID_UPD_BAD --> start CNG */ + /* handle bad/lost speech frame(and CS bad SID frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ + if ( ( + bfi != FRAMEMODE_FUTURE && /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ + ( *CNG != 0 ) && ( ( speech_bad != 0 ) || ( speech_lost != 0 ) ) ) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ + ( sid_upd_bad != 0 ) ) /* SID_UPD_BAD --> start CNG */ { st_ivas->bfi = 0; /* bfi=0 needed to activate CNG code */ total_brate = FRAME_NO_DATA; @@ -2250,7 +2227,8 @@ ivas_error read_indices( } /* GOOD frame */ - if ( st_ivas->bfi == 0 ) + if ( st_ivas->bfi == 0 || st_ivas->bfi == FRAMEMODE_FUTURE /* TODO(mcjbm): This fixes channel-aware mode BE. Still requires review from a bitstream reading expert */ + ) { /* GOOD frame - convert ITU-T G.192 words to short values */ st_ivas->hDecoderConfig->ivas_total_brate = total_brate; @@ -2325,7 +2303,7 @@ static Word32 read_indices_mime_handle_dtx( { if ( st->bfi ) { - sid_upd_bad = 1; /* corrupt sid_first, signaled as bad sid */ + sid_upd_bad = 1; /* corrupt sid_first, signaled as bad SID */ } else { @@ -2383,7 +2361,7 @@ static Word32 read_indices_mime_handle_dtx( } /* in CNG */ - /* handle bad speech frame(and bad sid frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ + /* handle bad speech frame(and bad SID frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ if ( ( *CNG != 0 && ( speech_bad || speech_lost || no_data ) ) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ sid_upd_bad ) /* SID_UPD_BAD --> start/stay CNG */ { @@ -2504,7 +2482,7 @@ static void get_rfFlag( /* check for rf_flag in the packet and extract the rf_frame_type and rf_fec_offset */ if ( st->total_brate == ACELP_13k20 && ( st->bfi == FRAMEMODE_NORMAL || st->bfi == FRAMEMODE_FUTURE ) ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ start_idx = 0; while ( acelp_sig_tbl[start_idx] != st->total_brate ) { @@ -2518,10 +2496,10 @@ static void get_rfFlag( /* retrieve the number of bits */ nBits_tmp = (int16_t) acelp_sig_tbl[start_idx++]; - /* retrieve the signalling indice */ + /* retrieve the signaling indice */ ind_tmp = acelp_sig_tbl[start_idx + get_indice( st, 0, nBits_tmp )]; - /* convert signalling indice into RF flag. */ + /* convert signaling indice into RF flag. */ *rf_flag = ( ind_tmp >> 7 ) & 0x1; if ( ind ) @@ -2624,7 +2602,7 @@ static void get_rfTargetBits( /*-------------------------------------------------------------------* * berCheck() * - * Check for bit errors in channel aware signalling. + * Check for bit errors in channel aware signaling. *-------------------------------------------------------------------*/ static void berCheck( @@ -2747,122 +2725,12 @@ void get_NextCoderType( tmp += bit_stream[k]; } - /* retrieve the signalling indice */ + /* retrieve the signaling indice */ *next_coder_type = acelp_sig_tbl[start_idx + tmp] & 0x7; return; } -/*-------------------------------------------------------------------* - * read_indices_from_djb() - * - * Read indices from the de-jitter buffer payload (works also for AMR-WB IO mode) - *-------------------------------------------------------------------*/ -void read_indices_from_djb( - Decoder_State *st, /* i/o: decoder state structure */ - uint8_t *pt_stream, /* i : bitstream file */ - int16_t *CNG, - const int16_t num_bits, /* i : input frame length in bits */ - const Word16 isAMRWB_IOmode, - const Word16 core_mode, - const Word16 qbit, - const Word16 bitstreamformat, - const Word16 amrwb_rfc4867_flag, - const int16_t partialframe, /* i : partial frame information */ - const int16_t next_coder_type /* i : next coder type information */ -) -{ - int16_t k; - UWord8 mask = 0x80; - Word16 no_data = 0; - Word16 sti = -1; - uint16_t *bit_stream_ptr; - int32_t total_brate; - int16_t speech_lost = 0; - - st->bfi = 0; - st->BER_detect = 0; - st->mdct_sw_enable = 0; - st->mdct_sw = 0; - reset_indices_dec( st ); - - st->bfi = !qbit; - total_brate = (Word32) (num_bits) *50; - - if ( num_bits == 0 ) /* guess type of missing frame for SP_LOST and NO_DATA */ - { - speech_lost = *CNG == 0; - no_data = *CNG != 0; - } - - if ( partialframe || st->prev_use_partial_copy ) - { - st->next_coder_type = next_coder_type; - } - else - { - st->next_coder_type = INACTIVE; - } - - if ( partialframe == 1 ) - { - st->bfi = 2; - } - - /* unpack speech data */ - bit_stream_ptr = st->bit_stream; - /* convert bitstream from compact bytes to short values and store it in decoder state */ - for ( k = 0; k < num_bits; k++ ) - { - if ( bitstreamformat == VOIP_RTPDUMP && isAMRWB_IOmode ) - { - st->bit_stream[sort_ptr[core_mode][k]] = unpack_bit( &pt_stream, &mask ); - bit_stream_ptr++; - } - else - { - *bit_stream_ptr++ = unpack_bit( &pt_stream, &mask ); - } - } - - /* unpack auxiliary bits */ - if ( isAMRWB_IOmode && total_brate == SID_1k75 ) - { - if ( bitstreamformat == VOIP_RTPDUMP ) - { - /* A.2.2.1.3: AMR-WB SID_1k75 frame is followed by STI bit and CMI bits */ - sti = unpack_bit( &pt_stream, &mask ); - } - else - { - /* VOIP_G192_RTP does not contain STI and CMI */ - sti = 1; - } - read_indices_mime_handle_sti_and_all_zero_bits( st, &total_brate, sti ); - } - - /* add two zero bytes for arithmetic coder flush */ - for ( k = 0; k < 8 * 2; ++k ) - { - *bit_stream_ptr++ = 0; - } - - total_brate = read_indices_mime_handle_dtx( st, CNG, isAMRWB_IOmode, core_mode, total_brate, sti, speech_lost, no_data, amrwb_rfc4867_flag ); - /* st->CNG set inside */ - - if ( st->bfi != 1 ) - { - /* select Mode 1 or Mode 2 */ - decoder_selectCodec( st, total_brate, *st->bit_stream ? 1 : 0 ); - - /* a change of the total bitrate should not be known to the decoder, if the received frame was truly lost */ - st->total_brate = total_brate; - - mdct_switching_dec( st ); - } - - return; -} /*-------------------------------------------------------------------* * get_indice_preview() @@ -2923,7 +2791,7 @@ void evs_dec_previewFrame( if ( total_brate == ACELP_13k20 ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ start_idx = 0; while ( acelp_sig_tbl[start_idx] != total_brate ) { @@ -2936,10 +2804,10 @@ void evs_dec_previewFrame( /* retrieve the number of bits */ nBits = (int16_t) acelp_sig_tbl[start_idx++]; - /* retrieve the signalling indice */ + /* retrieve the signaling indice */ ind = acelp_sig_tbl[start_idx + get_indice_preview( bitstream, bitstreamSize, 0, nBits )]; - /* convert signalling indice into RF flag. */ + /* convert signaling indice into RF flag. */ rf_flag = ( ind >> 7 ) & 0x1; if ( rf_flag != 0 ) { @@ -2970,4 +2838,19 @@ void evs_dec_previewFrame( } -#undef WMC_TOOL_MAN +void dtx_read_padding_bits( + DEC_CORE_HANDLE st, + const int16_t num_bits ) +{ + /* TODO: temporary hack, need to decide what to do with core-coder bitrate */ + int32_t tmp; + + tmp = st->total_brate; + st->total_brate = st->total_brate + num_bits * FRAMES_PER_SEC; + get_next_indice( st, num_bits ); + st->total_brate = tmp; + + return; +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/calc_st_com.c b/lib_com/calc_st_com.c index 5f1c3776d9aa45174e3e60b2587d82d3810a3ade..2f2cc56333ef7799daa532fc45d58fa77711878e 100644 --- a/lib_com/calc_st_com.c +++ b/lib_com/calc_st_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------------- diff --git a/lib_com/cb_shape.c b/lib_com/cb_shape.c index b44c46ab0f341c445e2495abfc250f4fd93616e5..364ed639f323b294b764f924d7c69f572d1695f1 100644 --- a/lib_com/cb_shape.c +++ b/lib_com/cb_shape.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * cb_shape() diff --git a/lib_com/cldfb.c b/lib_com/cldfb.c index 1d9fefcebb61432c0d2ecb4e47a917423e33b404..1490703aeed53e88f6c690fa27b9118425d87ca0 100644 --- a/lib_com/cldfb.c +++ b/lib_com/cldfb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "stat_dec.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #if __STDC_VERSION__ >= 199901L #if defined __ICL @@ -706,8 +706,7 @@ ivas_error openCldfb( HANDLE_CLDFB_FILTER_BANK hs; int16_t buf_len; - hs = (HANDLE_CLDFB_FILTER_BANK) count_malloc( sizeof( CLDFB_FILTER_BANK ) ); - if ( hs == NULL ) + if ( ( hs = (HANDLE_CLDFB_FILTER_BANK) malloc( sizeof( CLDFB_FILTER_BANK ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" ); } @@ -728,8 +727,7 @@ ivas_error openCldfb( buf_len = hs->p_filter_length; } - hs->cldfb_state = (float *) count_malloc( buf_len * sizeof( float ) ); - if ( hs->cldfb_state == NULL ) + if ( ( hs->cldfb_state = (float *) malloc( buf_len * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" ); } @@ -885,16 +883,19 @@ void deleteCldfb( { HANDLE_CLDFB_FILTER_BANK hs = *h_cldfb; - if ( hs ) + if ( h_cldfb == NULL || *h_cldfb == NULL ) { - if ( hs->cldfb_state ) - { - count_free( hs->cldfb_state ); - } - count_free( hs ); - *h_cldfb = NULL; + return; } + if ( hs->cldfb_state ) + { + free( hs->cldfb_state ); + } + + free( hs ); + *h_cldfb = NULL; + return; } @@ -1148,8 +1149,7 @@ ivas_error cldfb_save_memory( hs->memory_length = hs->p_filter_length; } - hs->memory = (float *) count_malloc( hs->memory_length * sizeof( float ) ); - if ( hs->memory == NULL ) + if ( ( hs->memory = (float *) malloc( hs->memory_length * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB\n" ); } @@ -1199,7 +1199,7 @@ void cldfb_restore_memory( } hs->memory_length = 0; - count_free( hs->memory ); + free( hs->memory ); hs->memory = NULL; return; diff --git a/lib_com/cng_exc.c b/lib_com/cng_exc.c index 62955ee95505a58be0c88b3c36a2b7336c7cae6a..9f0a22320e8732322a1d2580499534d0dbca8544 100644 --- a/lib_com/cng_exc.c +++ b/lib_com/cng_exc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_com/cnst.h b/lib_com/cnst.h index c5911101093f04546215db45f30fdd745649ff42..db1dc3d8982a768eff807f35d083dbabeae15f58 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -67,8 +67,7 @@ #define MAX16B_FLT 32767.0f #define MIN16B_FLT ( -32768.0f ) #define PCM16_TO_FLT_FAC 32768.0f - - +#define MDFT_NORM_SCALING ( 1.0f / PCM16_TO_FLT_FAC ) #define MAX_FRAME_COUNTER 200 #define MAX_BITS_PER_FRAME 10240 /* Bits per frame for max. bitrate 512kbps */ @@ -133,9 +132,9 @@ enum{ #define MAX_V_MULT_MAT 100 /* maximum array length for the function v_mult_mat() */ -#define G192_BIN0 (uint16_t) 0x007F -#define G192_BIN1 (uint16_t) 0x0081 - +#define SBA_AGC_FORCE_ENABLE 1 +#define SBA_AGC_FORCE_DISABLE 0 +#define SBA_AGC_DEFAULT -1 /*----------------------------------------------------------------------------------* * Layers @@ -553,7 +552,7 @@ enum #define L_MDCT_OVLP_MAX_CORE_FS L_NEXT_MAX_32k /* 280, 2/3 * L_MDCT_OVLP_MAX */ #define L_MDCT_HALF_OVLP_MAX_CORE_FS 2 * ( L_MDCT_HALF_OVLP_MAX ) / 3 /* 2/3 * L_MDCT_HALF_OVLP_MAX */ #define L_MDCT_MIN_OVLP_MAX_CORE_FS 2 * ( L_MDCT_MIN_OVLP_MAX ) / 3 /* 2/3 * L_MDCT_MIN_OVLP_MAX */ -#define L_ALDO_WIN1_MAX_CORE_FS 460 /* ALDO1 maximum window length for max core fs */ +#define L_ALDO_WIN1_MAX_CORE_FS 460 /* ALDO1 maximum window length for max core Fs */ #define L_ALDO_WIN1_FB_MAX 690 /* ALDO1 maximum window length */ /*----------------------------------------------------------------------------------* @@ -814,11 +813,11 @@ typedef enum #define FORMANT_SHARPENING_G1_16k 0.8f /* Formant sharpening numerator weighting at 16kHz */ #define FORMANT_SHARPENING_G2_16k 0.92f /* Formant sharpening denominator weighting at 16kHz */ -#define FSCALE_DENOM 512 +#define FSCALE_DENOM 512 #define ACELP_FIXED_CDK_NB 41 #define ACELP_FIXED_CDK_BITS( n ) PulseConfTable[n].bits -#define L_FIR 31 +#define L_FIR 31 enum TRACKPOS { @@ -891,7 +890,7 @@ enum * TCX constants *---------------------------------------------------------------*/ -#define NBITS_TCX_GAIN 7 +#define NBITS_TCX_GAIN 7 #define NOISE_FILL_RANGES 1 #define NBITS_NOISE_FILL_LEVEL 3 /* Number of bits used for coding noise filling level for each range */ @@ -1023,6 +1022,7 @@ enum #define SIZE_BK22_36b 128 #define SIZE_BK23_36b 64 +/* Gain quantizer constants */ #define NB_QUA_GAIN5B 32 /* Number of quantization level */ #define NB_QUA_GAIN6B 64 /* Number of quantization level */ #define NB_QUA_GAIN7B 128 /* Number of quantization level */ @@ -1269,6 +1269,8 @@ enum #define MAX_LEN_MA_FILTER 20 /* maximum length of the MA filter for SHB TD envelope calculation */ #define TABLE_CUMSUM_MAX_N 320 /* maximum length of cumsum(i) and cumsum(i*i) tables */ +#define NUM_BITS_FB_FRAMEGAIN_TBE 4 /* Number of bits for framegain for FB TBE */ + /*----------------------------------------------------------------------------------* * SWB BWE constants *----------------------------------------------------------------------------------*/ @@ -1282,7 +1284,7 @@ enum #define FB_MAX_GAIN_VAR 0.5f -#define NUM_BITS_FB_FRAMEGAIN 4 /* Number of bits for framegain for FB */ +#define NUM_BITS_FB_FRAMEGAIN 4 /* Number of bits for framegain for FB BWE */ #define FB_BAND_BEGIN 620 /* == 15.5 kHz */ #define FB_BAND_BEGIN_12k8 560 /* == 14 kHz */ #define FB_BAND_END 800 /* == 20 kHz */ @@ -1680,6 +1682,13 @@ enum #define HALF_D_STAB_TBL_FX ( (Word16) 422 ) /* Q13 0.1013138/2.0 */ #define NUM_ENV_STAB_PLC_STATES 2 /* Number of states of markov model */ +#define ENV_STAB_EST1 2.93f /* env_stab estimation coefficient 1 */ +#define ENV_STAB_EST2 (-2.20f) /* env_stab estimation coefficient 2 */ +#define ENV_STAB_EST3 0.741f /* env_stab estimation coefficient 3 */ +#define STAB_FAC_EST1 1.093f /* stab_fac HQ estimation coefficient 1 */ +#define STAB_FAC_EST2 (-5.84e-05f) /* stab_fac HQ estimation coefficient 2, including Q12 scaling */ +#define STAB_FAC_EST3 0.125f /* stab_fac HQ estimation coefficient 3 */ + #define ATT_LIM_HANGOVER 150 /* Number of hangover frames for disabling stability dependent attenuation */ #define DELTA_TH 5.0f /* Delta energy threshold for transient detection for envelope stability */ #define ENERGY_TH 100.0f /* Energy threshold for transient detection */ diff --git a/lib_com/codec_tcx_common.c b/lib_com/codec_tcx_common.c index 98a2fb4bd012eed1c32bdb46233fc398d5ac6542..7bb6dac40bb4b5d40bc869e53047fbcbc55e5db9 100644 --- a/lib_com/codec_tcx_common.c +++ b/lib_com/codec_tcx_common.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * tcxGetNoiseFillingTilt() diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index b504d89731ff227a6c6c87728f0872ed52bbc099..3e012a6f99685c080760cade2d1e15a90874970a 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,19 +38,39 @@ #include "options.h" #include #include +#include "ivas_error.h" /*----------------------------------------------------------------------------------* * Common API constants *----------------------------------------------------------------------------------*/ -#define IVAS_MAX_BITS_PER_FRAME ( 512000 / 50 ) -#define IVAS_MAX_NUM_OBJECTS 4 -#define IVAS_MAX_OUTPUT_CHANNELS 16 -#define IVAS_CLDFB_NO_CHANNELS_MAX ( 60 ) +#define IVAS_MAX_BITS_PER_FRAME ( 512000 / 50 ) +#define IVAS_MAX_NUM_OBJECTS 4 +#define IVAS_MAX_OUTPUT_CHANNELS 16 +#define IVAS_CLDFB_NO_CHANNELS_MAX ( 60 ) +#define IVAS_MAX_INPUT_LFE_CHANNELS 4 + +#define RENDERER_HEAD_POSITIONS_PER_FRAME 4 + + /*----------------------------------------------------------------------------------* * Common API structures *----------------------------------------------------------------------------------*/ +typedef enum _IVAS_ENC_FEC_INDICATOR +{ + IVAS_ENC_FEC_LO, + IVAS_ENC_FEC_HI, + IVAS_ENC_FEC_UNDEFINED = 0xffff +} IVAS_ENC_FEC_INDICATOR; + +typedef struct _IVAS_ENC_CHANNEL_AWARE_CONFIG +{ + int16_t channelAwareModeEnabled; + IVAS_ENC_FEC_INDICATOR fec_indicator; + int16_t fec_offset; +} IVAS_ENC_CHANNEL_AWARE_CONFIG; + typedef struct _IVAS_ISM_METADATA { float azimuth; @@ -58,18 +78,38 @@ typedef struct _IVAS_ISM_METADATA float radius; float spread; float gainFactor; + float yaw; + float pitch; } IVAS_ISM_METADATA; -typedef struct _IVAS_QUATERNION +typedef struct { float w, x, y, z; } IVAS_QUATERNION; +typedef struct +{ + float x, y, z; +} IVAS_VECTOR3; + +typedef struct +{ + float x, y, z; + +} IVAS_POSITION; + typedef struct ivas_masa_metadata_frame_struct *IVAS_MASA_METADATA_HANDLE; +#ifdef FIX_350_MASA_DELAY_COMP +typedef struct ivas_masa_decoder_ext_out_meta_struct *MASA_DECODER_EXT_OUT_META_HANDLE; +#else typedef struct ivas_masa_qmetadata_frame_struct *IVAS_MASA_QMETADATA_HANDLE; +#endif typedef struct TDREND_HRFILT_FiltSet_struct *IVAS_DEC_HRTF_HANDLE; +typedef struct ivas_hrtfs_crend_structure *IVAS_DEC_HRTF_CREND_HANDLE; +typedef struct ivas_hrtfs_fastconv_struct *IVAS_DEC_HRTF_FASTCONV_HANDLE; +typedef struct ivas_hrtfs_parambin_struct *IVAS_DEC_HRTF_PARAMBIN_HANDLE; #ifdef DEBUGGING typedef enum @@ -80,6 +120,15 @@ typedef enum } IVAS_RENDER_TYPE_OVERRIDE; #endif +typedef struct +{ + float azimuth; + float elevation; + float radius; + float yaw; + float pitch; +} IVAS_REND_AudioObjectPosition; + typedef struct _IVAS_ROOM_ACOUSTICS_CONFIG { int16_t override; @@ -99,6 +148,7 @@ typedef struct _IVAS_RENDER_CONFIG IVAS_RENDER_TYPE_OVERRIDE renderer_type_override; #endif IVAS_ROOM_ACOUSTICS_CONFIG_DATA room_acoustics; + float directivity[3]; } IVAS_RENDER_CONFIG_DATA, *IVAS_RENDER_CONFIG_HANDLE; typedef struct _IVAS_LS_CUSTOM_LAYOUT @@ -117,17 +167,18 @@ typedef struct ivas_LS_setup_custom IVAS_LSSETUP_CUSTOM_STRUCT; typedef struct _IVAS_JBM_TRACE_DATA { - double playTime; - int16_t partialCopyOffset; + uint32_t systemTimestamp_ms; + uint16_t extBufferedSamples; + uint16_t lastDecodedWasActive; + int32_t output_Fs; + int16_t dataUnit_flag; uint16_t sequenceNumber; uint32_t timeStamp; uint32_t rcvTime; - int16_t lastDecodedWasActive; - int16_t partial_frame_flag; - int16_t dataUnit_flag; + int16_t partial_frame; + int16_t partialCopyOffset; } IVAS_JBM_TRACE_DATA; - #endif /* COMMON_API_TYPES_H */ diff --git a/lib_com/control.h b/lib_com/control.h index 2b3f92b5355b09aa9c32a11f37343c2c07e46ade..725163728dc88ec26e8cee3d1f0b2c7c28e5721e 100644 --- a/lib_com/control.h +++ b/lib_com/control.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/core_com_config.c b/lib_com/core_com_config.c index 5f5103a03fd8ad3841013a5ba985847d63db06ac..d138fe1a1ed28c2dc77f12c855af07457a843319 100644 --- a/lib_com/core_com_config.c +++ b/lib_com/core_com_config.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" @@ -54,8 +54,8 @@ /*! r: flag indicating a valid bitrate */ int16_t is_EVS_bitrate( - const int32_t ivas_total_brate, /* i : EVS total bitrate */ - int16_t *Opt_AMR_WB /* i : AMR-WB IO flag */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + int16_t *Opt_AMR_WB /* i : AMR-WB IO flag */ ) { int16_t j; @@ -163,9 +163,9 @@ int16_t get_codec_mode( *-------------------------------------------------------------------*/ int16_t getTcxonly( - const int16_t element_mode, /* i : IVAS element mode */ - const int32_t total_brate, /* i : total bitrate */ - const int16_t is_mct /* i : MCT mode flag */ + const int16_t element_mode, /* i : IVAS element mode */ + const int32_t total_brate, /* i : total bitrate */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ ) { int16_t tcxonly = 0; @@ -187,7 +187,7 @@ int16_t getTcxonly( } break; case IVAS_CPE_MDCT: - if ( total_brate >= ( is_mct ? IVAS_32k : IVAS_48k ) ) + if ( total_brate >= ( MCT_flag ? IVAS_32k : IVAS_48k ) ) { tcxonly = 1; } @@ -247,16 +247,21 @@ int16_t getResq( *-------------------------------------------------------------------*/ int16_t getTnsAllowed( - const int32_t total_brate, /* i : total bitrate */ - const int16_t igf, /* i : flag indicating IGF activity*/ - const int16_t element_mode, /* i : IVAS element mode */ + const int32_t total_brate, /* i : total bitrate */ + const int16_t igf, /* i : flag indicating IGF activity*/ + const int16_t element_mode /* i : IVAS element mode */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , const MCT_CHAN_MODE mct_chan_mode /* i : MCT channel mode */ +#endif ) { int16_t tnsAllowed = 0; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif if ( igf ) { if ( total_brate > HQ_16k40 || ( ( total_brate > HQ_13k20 ) && element_mode == IVAS_CPE_DFT ) ) @@ -268,7 +273,9 @@ int16_t getTnsAllowed( { tnsAllowed = 1; } +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif return tnsAllowed; } @@ -411,16 +418,21 @@ int16_t getIgfPresent( const int16_t element_mode, /* i : IVAS element mode */ const int32_t total_brate, /* i : total bitrate */ const int16_t bwidth, /* i : audio bandwidth */ - const int16_t rf_mode, /* i : flag to signal the RF mode */ + const int16_t rf_mode /* i : flag to signal the RF mode */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , const int16_t mct_chan_mode /* i : MCT channel mode */ +#endif ) { int16_t igfPresent = 0; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( mct_chan_mode == MCT_CHAN_MODE_LFE ) { return igfPresent; } +#endif if ( bwidth == SWB ) { @@ -808,8 +820,11 @@ void init_tcx_cfg( const int16_t infoIGFStopFreq, const int16_t element_mode, const int16_t ini_frame, - const int16_t is_mct, + const int16_t MCT_flag +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , const MCT_CHAN_MODE mct_chan_mode /* i : MDCT channel mode */ +#endif ) { int16_t i; @@ -840,17 +855,24 @@ void init_tcx_cfg( /* set number of coded lines */ hTcxCfg->tcx_coded_lines = getNumTcxCodedLines( bwidth ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( mct_chan_mode == MCT_CHAN_MODE_LFE ) { hTcxCfg->tcx_coded_lines = MCT_LFE_MAX_LINE; } +#endif /* TNS in TCX */ hTcxCfg->pCurrentTnsConfig = NULL; - hTcxCfg->fIsTNSAllowed = getTnsAllowed( total_brate, igf, element_mode, mct_chan_mode ); + hTcxCfg->fIsTNSAllowed = getTnsAllowed( total_brate, igf, element_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + mct_chan_mode +#endif + ); if ( hTcxCfg->fIsTNSAllowed ) { - InitTnsConfigs( bwidth, hTcxCfg->tcx_coded_lines, hTcxCfg->tnsConfig, infoIGFStopFreq, total_brate, element_mode, is_mct ); + InitTnsConfigs( bwidth, hTcxCfg->tcx_coded_lines, hTcxCfg->tnsConfig, infoIGFStopFreq, total_brate, element_mode, MCT_flag ); SetAllowTnsOnWhite( hTcxCfg->tnsConfig, element_mode == IVAS_CPE_MDCT ); } diff --git a/lib_com/deemph.c b/lib_com/deemph.c index 20b5c43719ffb01913991cc2508412b8549b4e85..9f4463d6a820cb6ebeb4a170b3e7ab56008c20c6 100644 --- a/lib_com/deemph.c +++ b/lib_com/deemph.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * deemph() diff --git a/lib_com/delay_comp.c b/lib_com/delay_comp.c index a957150b936957da3f6919c6ee17e893508433c5..b96798815e46592f6a4bf3194e248c1145b7bc30 100644 --- a/lib_com/delay_comp.c +++ b/lib_com/delay_comp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * get_delay() @@ -50,18 +50,16 @@ *--------------------------------------------------------------------------*/ /*! r: delay value in ns */ -float get_delay( - const int16_t what_delay, /* i : what delay? (ENC or DEC) */ - const int32_t io_fs, /* i : input/output sampling frequency */ - const IVAS_FORMAT ivas_format, /* i : IVAS format */ - HANDLE_CLDFB_FILTER_BANK hCldfb, /* i : Handle of Cldfb analysis */ - RENDERER_TYPE renderer_type, /* i : IVAS rendering type */ - const int32_t binaural_latency_ns /* i : binaural renderer HRTF delay in ns */ +int32_t get_delay( + const int16_t enc_dec, /* i : encoder/decoder flag */ + const int32_t io_fs, /* i : input/output sampling frequency */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + HANDLE_CLDFB_FILTER_BANK hCldfb /* i : Handle of Cldfb analysis */ ) { - float delay = 0; + int32_t delay = 0; - if ( what_delay == ENC ) + if ( enc_dec == ENC ) { if ( ivas_format == MONO_FORMAT ) /* EVS mono */ { @@ -70,6 +68,13 @@ float get_delay( else /* IVAS */ { delay = IVAS_ENC_DELAY_NS; + +#ifdef FIX_350_MASA_DELAY_COMP + if ( ivas_format == MASA_FORMAT ) + { + delay = 0; /* All delay is compensated in the decoder with MASA */ + } +#endif } if ( ivas_format == SBA_FORMAT ) @@ -78,7 +83,7 @@ float get_delay( delay += IVAS_FB_ENC_DELAY_NS; } } - else + else /* DEC */ { if ( ivas_format == MONO_FORMAT ) /* EVS mono */ { @@ -95,15 +100,19 @@ float get_delay( { delay = IVAS_DEC_DELAY_NS; - if ( hCldfb != NULL || renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + if ( hCldfb != NULL ) { + /* compensate for filterbank delay */ delay += IVAS_FB_DEC_DELAY_NS; } - /* compensate for Binaural renderer HRTF delay */ + +#ifdef FIX_350_MASA_DELAY_COMP + if ( ivas_format == MASA_FORMAT ) { - delay += binaural_latency_ns; + delay += IVAS_ENC_DELAY_NS; /* Compensate also the encoder delay in the decoder with MASA */ } +#endif } } diff --git a/lib_com/disclaimer.c b/lib_com/disclaimer.c index 749f9fcce2541ad6b9f4c73f3c2e5c7dda36fbe1..ed55a45b063d596dea4b6d4968633533c8c3e177 100644 --- a/lib_com/disclaimer.c +++ b/lib_com/disclaimer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ #include #include "options.h" @@ -42,6 +41,8 @@ #endif #include "prot.h" +#define WMC_TOOL_SKIP + int16_t print_disclaimer( FILE *fPtr ) { diff --git a/lib_com/dlpc_bfi.c b/lib_com/dlpc_bfi.c index 33ba286c3c3312ca87ce46948cb5f287a6087b50..b894b845f803c57392987fba058d2d1b74d74b68 100644 --- a/lib_com/dlpc_bfi.c +++ b/lib_com/dlpc_bfi.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * routine: dlpc_bfi() diff --git a/lib_com/edct.c b/lib_com/edct.c index 8fe84049a60c56c19ede56a66e94db1ce988684e..6f6d6c32b65d0d7c5c671865cf8aeb419852676b 100644 --- a/lib_com/edct.c +++ b/lib_com/edct.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include /* for cosf, sinf */ static ivas_error get_edct_table( diff --git a/lib_com/enh1632.c b/lib_com/enh1632.c index 985398eec9fa3c98d02bec048df21178fefcb913..1dd192faaa7d9c2d0190c781c3a18af3cdda27db 100644 --- a/lib_com/enh1632.c +++ b/lib_com/enh1632.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,7 +30,6 @@ *******************************************************************************************************/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ /* =========================================================================== File: ENH1632.C v.2.3 - 30.Nov.2009 @@ -90,6 +89,8 @@ #include #include "stl.h" +#define WMC_TOOL_SKIP + /***************************************************************************** * * Constants and Globals @@ -629,5 +630,4 @@ Word32 L_rotl( Word32 L_var1, Word16 var2, Word16 *var3 ) return ( L_var_out ); } - -/* end of file */ +#undef WMC_TOOL_SKIP diff --git a/lib_com/enh1632.h b/lib_com/enh1632.h index a46fb8dbe74910e31b30baf2f4d8a2adac2a92a2..9216ea6c201a3b63690723318b65ea19367445c2 100644 --- a/lib_com/enh1632.h +++ b/lib_com/enh1632.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/enh40.c b/lib_com/enh40.c index 777bfffd8f0a41b3b72f65540c2afe4e5f00c915..8a48cece39bed8b7e709fedb9bd8c9b40c5354a0 100644 --- a/lib_com/enh40.c +++ b/lib_com/enh40.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,7 +30,6 @@ *******************************************************************************************************/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ /* =========================================================================== File: ENH40.C v.2.3 - 30.Nov.2009 @@ -93,6 +92,7 @@ * Include-Files * *****************************************************************************/ + #include #include #include "stl.h" @@ -100,6 +100,8 @@ #include #endif /* BASOP_NOGLOB */ +#define WMC_TOOL_SKIP + #ifdef _MSC_VER #pragma warning( disable : 4310 ) #endif @@ -161,7 +163,6 @@ #ifndef BASOP_NOGLOB Word40 L40_shl( Word40 L40_var1, Word16 var2 ) #else /* BASOP_NOGLOB */ - Word40 L40_shl_o( Word40 L40_var1, Word16 var2, Flag *Overflow ) #endif /* BASOP_NOGLOB */ { @@ -189,11 +190,10 @@ Word40 L40_shl_o( Word40 L40_var1, Word16 var2, Flag *Overflow ) { #if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) if ( L40_var_out > 0x003fffffffff ) - { #else if ( L40_var_out > 0x003fffffffffLL ) - { #endif + { #ifndef BASOP_NOGLOB Overflow = 1; exit( 1 ); @@ -258,11 +258,10 @@ Word40 L40_shl( Word40 L40_var1, Word16 var2 ) { #if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) if ( L40_var_out > 0x003fffffffff ) - { #else if ( L40_var_out > 0x003fffffffffLL ) - { #endif + { assert( 0 ); L40_var_out = MAX_40; break; @@ -542,7 +541,6 @@ Word40 L40_add( Word40 L40_var1, Word40 L40_var2 ) #ifndef BASOP_NOGLOB Word40 L40_sub( Word40 L40_var1, Word40 L40_var2 ) #else /* BASOP_NOGLOB */ - Word40 L40_sub_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow ) #endif /* BASOP_NOGLOB */ { @@ -1308,4 +1306,4 @@ Word40 L40_shl_r( Word40 L40_var1, Word16 var2 ) } -/* end of file */ +#undef WMC_TOOL_SKIP diff --git a/lib_com/enh40.h b/lib_com/enh40.h index d2a84652d49de4c263c820e931f2e56b7551c13e..a55bd925e9da5ca2408aa43f18f787a3ae32be64 100644 --- a/lib_com/enh40.h +++ b/lib_com/enh40.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/enhancer.c b/lib_com/enhancer.c index 2ed4271c05d55d80c41af33c08433d0b45134ab9..d0eeeb76c73ca4e185eafd8b6edd34006d66ee69 100644 --- a/lib_com/enhancer.c +++ b/lib_com/enhancer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_com/enr_1_az.c b/lib_com/enr_1_az.c index f5f88ed55c1d77fcfadf828948264bcd6bc21415..2b66a14d726bc263dd8feea5a484faeb81c1efe1 100644 --- a/lib_com/enr_1_az.c +++ b/lib_com/enr_1_az.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * enr_1_Az() diff --git a/lib_com/env_adj.c b/lib_com/env_adj.c index a169311615a49f6a4cdf4147d930d28823667fd4..03b7d6cef61c1c070a52ec6141ba51ca3d0f2b6c 100644 --- a/lib_com/env_adj.c +++ b/lib_com/env_adj.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * env_adj() diff --git a/lib_com/env_stab.c b/lib_com/env_stab.c index abe93eddcef7cfcfa6bff8996dc8f74ab216b693..b4da4ce9d70d675dc0de77f32c6d1ca061ede6d5 100644 --- a/lib_com/env_stab.c +++ b/lib_com/env_stab.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUGGING #include "assert.h" #endif @@ -63,10 +63,11 @@ /*--------------------------------------------------------------------------*/ float env_stability( - const int16_t *ynrm, /* i : Norm vector for current frame */ - const int16_t nb_sfm, /* i : Number of sub-bands */ - int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ - int16_t *mem_env_delta /* i/o: Envelope stability memory for smoothing*/ + const int16_t *ynrm, /* i : Norm vector for current frame */ + const int16_t nb_sfm, /* i : Number of sub-bands */ + int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ + int16_t *mem_env_delta, /* i/o: Envelope stability memory for smoothing*/ + const int16_t core_switching_flag /* i : Core switching flag */ ) { Word16 env_delta; @@ -82,53 +83,68 @@ float env_stability( Flag Overflow; #endif /* BASOP_NOGLOB */ - /* Calculate envelope stability parameter */ - L_env_delta = L_deposit_l( 0 ); - for ( i = 0; i < nb_sfm; i++ ) + if ( core_switching_flag ) { - tmp = sub( mem_norm[i], ynrm[i] ); - L_env_delta = L_mac0( L_env_delta, tmp, tmp ); - mem_norm[i] = ynrm[i]; + for ( i = 0; i < nb_sfm; i++ ) + { + mem_norm[i] = ynrm[i]; + } +#ifdef BASOP_NOGLOB + Overflow = 0; + env_delta = shl_o( *mem_env_delta, 1, &Overflow ); +#else + env_delta = shl_o( *mem_env_delta, 1 ); +#endif } + else + { + /* Calculate envelope stability parameter */ + L_env_delta = L_deposit_l( 0 ); + for ( i = 0; i < nb_sfm; i++ ) + { + tmp = sub( mem_norm[i], ynrm[i] ); + L_env_delta = L_mac0( L_env_delta, tmp, tmp ); + mem_norm[i] = ynrm[i]; + } #ifdef DEBUGGING - assert( nb_sfm == 27 || nb_sfm == 26 ); + assert( nb_sfm == 27 || nb_sfm == 26 ); #endif - inv_nb_sfm = 19418; /* Q19 */ - if ( nb_sfm == 26 ) - { - inv_nb_sfm = 20165; /* Q19 */ - } - exp = norm_l( L_env_delta ); - L_env_delta = Mult_32_16( L_shl( L_env_delta, exp ), inv_nb_sfm ); /* 0+exp+19-15 */ + inv_nb_sfm = 19418; /* Q19 */ + if ( nb_sfm == 26 ) + { + inv_nb_sfm = 20165; /* Q19 */ + } + exp = norm_l( L_env_delta ); + L_env_delta = Mult_32_16( L_shl( L_env_delta, exp ), inv_nb_sfm ); /* 0+exp+19-15 */ - L_tmp = Sqrt_l( L_env_delta, &exp2 ); /* exp+4+31+exp2 */ + L_tmp = Sqrt_l( L_env_delta, &exp2 ); /* exp+4+31+exp2 */ - exp = add( 35, add( exp, exp2 ) ); - if ( sub( s_and( exp, 1 ), 1 ) == 0 ) - { - L_tmp = Mult_32_16( L_tmp, 23170 ); /* 1/sqrt(2) in Q15 */ - } - exp = shr( exp, 1 ); + exp = add( 35, add( exp, exp2 ) ); + if ( sub( s_and( exp, 1 ), 1 ) == 0 ) + { + L_tmp = Mult_32_16( L_tmp, 23170 ); /* 1/sqrt(2) in Q15 */ + } + exp = shr( exp, 1 ); #ifndef BASOP_NOGLOB - env_delta = round_fx( L_shl( L_tmp, sub( 26, exp ) ) ); /* Q10 */ - L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ - L_tmp = L_mac( L_tmp, 29491, *mem_env_delta ); /* 29491 is 0.9 in Q15. Q28 */ - *mem_env_delta = round_fx( L_tmp ); /* Q12 */ -#else /* BASOP_NOGLOB */ - env_delta = round_fx_o( L_shl_o( L_tmp, sub( 26, exp ), &Overflow ), &Overflow ); /* Q10 */ - L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ - L_tmp = L_mac_o( L_tmp, 29491, *mem_env_delta, &Overflow ); /* 29491 is 0.9 in Q15. Q28 */ - *mem_env_delta = round_fx_o( L_tmp, &Overflow ); /* Q12 */ -#endif /* BASOP_NOGLOB */ - Overflow = 0; + env_delta = round_fx( L_shl( L_tmp, sub( 26, exp ) ) ); /* Q10 */ + L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ + L_tmp = L_mac( L_tmp, 29491, *mem_env_delta ); /* 29491 is 0.9 in Q15. Q28 */ + *mem_env_delta = round_fx( L_tmp ); /* Q12 */ +#else /* BASOP_NOGLOB */ + env_delta = round_fx_o( L_shl_o( L_tmp, sub( 26, exp ), &Overflow ), &Overflow ); /* Q10 */ + L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ + L_tmp = L_mac_o( L_tmp, 29491, *mem_env_delta, &Overflow ); /* 29491 is 0.9 in Q15. Q28 */ + *mem_env_delta = round_fx_o( L_tmp, &Overflow ); /* Q12 */ +#endif /* BASOP_NOGLOB */ + Overflow = 0; #ifndef BASOP_NOGLOB - env_delta = round_fx( L_shl( L_tmp, 1 ) ); /* Q13 */ -#else /* BASOP_NOGLOB */ - env_delta = round_fx_o( L_shl_o( L_tmp, 1, &Overflow ), &Overflow ); /* Q13 */ -#endif /* BASOP_NOGLOB */ - + env_delta = round_fx( L_shl( L_tmp, 1 ) ); /* Q13 */ +#else /* BASOP_NOGLOB */ + env_delta = round_fx_o( L_shl_o( L_tmp, 1, &Overflow ), &Overflow ); /* Q13 */ +#endif /* BASOP_NOGLOB */ + } if ( Overflow != 0 ) /* Saturated due to the above up-shifting operation. */ { env_stab = stab_trans_fx[L_STAB_TBL - 1]; /* The highest quantized index. */ diff --git a/lib_com/env_stab_trans.c b/lib_com/env_stab_trans.c index 6a8ca2b26645aae233641c08c60e5bd516eb053f..a2d4492b3f4288ed3d707b824092d26b19fad166 100644 --- a/lib_com/env_stab_trans.c +++ b/lib_com/env_stab_trans.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * env_stab_transient_detect() diff --git a/lib_com/est_tilt.c b/lib_com/est_tilt.c index e126f761f8fc00c7b5cf8376be9e066a1381e543..8073e39dfb19833c1ae9d6e7fe1db21f6e38b029 100644 --- a/lib_com/est_tilt.c +++ b/lib_com/est_tilt.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * est_tilt() diff --git a/lib_com/fd_cng_com.c b/lib_com/fd_cng_com.c index 98b5a3df750b16c2bc1bfc6a32848f768b804d5a..f2dbf746b6f18d5e6b9fc07aaa570384733702be 100644 --- a/lib_com/fd_cng_com.c +++ b/lib_com/fd_cng_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- @@ -68,9 +68,7 @@ ivas_error createFdCngCom( HANDLE_FD_CNG_COM hs; /* Allocate memory */ - hs = (HANDLE_FD_CNG_COM) count_malloc( sizeof( FD_CNG_COM ) ); - - if ( hs == NULL ) + if ( ( hs = (HANDLE_FD_CNG_COM) malloc( sizeof( FD_CNG_COM ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD CNG COM" ); } @@ -162,7 +160,7 @@ void deleteFdCngCom( if ( hsCom != NULL ) { - count_free( hsCom ); + free( hsCom ); *hFdCngCom = NULL; } diff --git a/lib_com/fft.c b/lib_com/fft.c index ed0d6604e6760440e4af923480a19f957c73cc70..e6121e818ae1e58956c41a2b31f5fe3bd54abe08 100644 --- a/lib_com/fft.c +++ b/lib_com/fft.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef _MSC_VER #pragma warning( disable : 4310 ) @@ -6393,7 +6393,7 @@ void rfft( } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP #define SCALEFACTOR8 ( 4 ) #define SCALEFACTOR64 ( 7 ) @@ -6766,3 +6766,5 @@ void BASOP_cfft( return; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/fft_cldfb.c b/lib_com/fft_cldfb.c index 6967f87bcde8a7e6066b60991560e2044f991767..0ea848abdbba069cd73569df5054e417386a65fa 100644 --- a/lib_com/fft_cldfb.c +++ b/lib_com/fft_cldfb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "prot.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" #if __STDC_VERSION__ >= 199901L #if defined __ICL diff --git a/lib_com/fft_rel.c b/lib_com/fft_rel.c index a8b96e8217f50bf751bb0cb79c741bd5671b4489..46ee5e9434de472f4f967ecb2e8049e37c9ea617 100644 --- a/lib_com/fft_rel.c +++ b/lib_com/fft_rel.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_com/fill_spectrum.c b/lib_com/fill_spectrum.c index 9b743a5f1ce6aa260aebc1970dd8acfc67f4a331..6694824879aa5bcc6060d3cd6cb9d88a5479447d 100644 --- a/lib_com/fill_spectrum.c +++ b/lib_com/fill_spectrum.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * fill_spectrum() @@ -90,10 +90,10 @@ void fill_spectrum( const int16_t element_mode /* i : element mode */ ) { - float CodeBook[FREQ_LENGTH]; + float CodeBook[L_SPEC48k_EXT]; int16_t cb_size = 0; int16_t last_sfm; - float CodeBook_mod[FREQ_LENGTH]; + float CodeBook_mod[L_SPEC48k_EXT]; float norm_adj[NB_SFM]; int16_t high_sfm = 23; int16_t flag_32K_env_hangover; diff --git a/lib_com/findpulse.c b/lib_com/findpulse.c index e26980d2250907d667ee5654508e695d733f135b..3383397bcf939edd9426f6a5446c768c3e7e840a 100644 --- a/lib_com/findpulse.c +++ b/lib_com/findpulse.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* * findpulse() diff --git a/lib_com/fine_gain_bits.c b/lib_com/fine_gain_bits.c index 240b174bef0d4b04836a4afff69b3b213a1ab367..c4c5ce3fca9b69e954e85058aab1a7de17227a6d 100644 --- a/lib_com/fine_gain_bits.c +++ b/lib_com/fine_gain_bits.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "rom_com.h" #include "prot.h" #include -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * subband_gain_bits() diff --git a/lib_com/frame_ener.c b/lib_com/frame_ener.c index d5c38e6640fbbfd54e85cb79d07a83c47b3be320..f44cb099ce8c2e66a70d680c3488ab9b401b1517 100644 --- a/lib_com/frame_ener.c +++ b/lib_com/frame_ener.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* * fer_energy() diff --git a/lib_com/get_gain.c b/lib_com/get_gain.c index 320d5ad12ce246927b50b8f5da73f9a01848f0ab..e3457128fe5c314636d81380d742a9d5a67e1595 100644 --- a/lib_com/get_gain.c +++ b/lib_com/get_gain.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* * get_gain() diff --git a/lib_com/gs_bitallocation.c b/lib_com/gs_bitallocation.c index 8c98bf27d9212b4343afde96ae2a84d9d3eb1825..7f7809428f9fb765f68dd2aceba11f608a4a8c85 100644 --- a/lib_com/gs_bitallocation.c +++ b/lib_com/gs_bitallocation.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -200,7 +200,7 @@ void bands_and_bit_alloc( /* 2- Decide the pourcentage of bits allocated to LF (between 50-75%) depending of the temporal contribution in GSC */ bit_fracf = ( -0.125f * Diff_len + 76.0f ) / 100; - check_bounds( &bit_fracf, 0.50f, 0.75f ); + bit_fracf = check_bounds( bit_fracf, 0.50f, 0.75f ); /* Adjusment of the bitrate between LF and HF base on the content type */ /* 1 = new GSC bit alloc @@ -236,7 +236,7 @@ void bands_and_bit_alloc( nb_bands_adj = 0.02f * SWB_bit_budget - 1.2f; } nb_bands_max = (int16_t) ( nb_bands_max * nb_bands_adj + 0.5f ); - check_bounds_s( &nb_bands_max, 5, nb_tot_bands ); + nb_bands_max = check_bounds_s( nb_bands_max, 5, nb_tot_bands ); bit_fracf *= SWB_bit_budget; diff --git a/lib_com/gs_gains.c b/lib_com/gs_gains.c index ea23b2778149d5d69599fc3b020364ba9e552949..40626468b65089c0eb8a84e209615bd55464a31b 100644 --- a/lib_com/gs_gains.c +++ b/lib_com/gs_gains.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_com/gs_inact_switching.c b/lib_com/gs_inact_switching.c index a9d2a80046e93d125437f1a782088a52e1d2100a..cd380e86e01e4776259663a806c235b331b60bfc 100644 --- a/lib_com/gs_inact_switching.c +++ b/lib_com/gs_inact_switching.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_com/gs_noisefill.c b/lib_com/gs_noisefill.c index 2885f324cabf420859365cebb3ac84fa7aeeb28a..a92aec07515888a5f48888eb667fe210c7496297 100644 --- a/lib_com/gs_noisefill.c +++ b/lib_com/gs_noisefill.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * gs_noisf() diff --git a/lib_com/gs_preech.c b/lib_com/gs_preech.c index b7ab89a879ec5ab5267ae3e05d277d18d9fe49df..5a98f409369c0a19f0983496d8963323c09e294d 100644 --- a/lib_com/gs_preech.c +++ b/lib_com/gs_preech.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_com/guided_plc_util.c b/lib_com/guided_plc_util.c index cb14c503c895980513c8ac8a8c4e8b83cf389342..884c2beeb860104d820e9dedadd5d0ef742ae43b 100644 --- a/lib_com/guided_plc_util.c +++ b/lib_com/guided_plc_util.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_com/hp50.c b/lib_com/hp50.c index 58b15a4211759df7ce791dac0f6bd95e76704cf1..3624fabb449fd153e55b2c3ed0fb44b00e19bbc1 100644 --- a/lib_com/hp50.c +++ b/lib_com/hp50.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,14 +34,13 @@ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -#include "typedef.h" #include #include "options.h" #ifdef DEBUGGING #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /* diff --git a/lib_com/hq2_bit_alloc.c b/lib_com/hq2_bit_alloc.c index b46f54480e78f00ab8bad762c518b94468c40fdd..6b53adec8f931b292bf97f51c06747c4a56930d8 100644 --- a/lib_com/hq2_bit_alloc.c +++ b/lib_com/hq2_bit_alloc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,9 +45,9 @@ #include "basop_util.h" #include "basop_mpy.h" #include "stl.h" -#include "wmops.h" +#include "wmc_auto.h" -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /*------------------------------------------------------------------- * Local constants @@ -375,6 +375,11 @@ void hq2_bit_alloc_har( Word32 L_y[BANDS_MAX]; +#ifdef BASOP_NOGLOB + Flag Overflow; + Overflow = 0; +#endif + grp_rngmax_fx[0] = 0; grp_rngmax_fx[1] = 0; @@ -639,7 +644,12 @@ void hq2_bit_alloc_har( L_temp = Mpy_32_16( L_Ravg_sub[GRP_SB - 1], sub( GRP_SB, 1 ) ); /* Qbe+0+1 */ L_temp = Mpy_32_16( L_temp, Inv_norm_sum_fx ); /* Qbe+1+QIpb+1 */ +#ifdef BASOP_NOGLOB + lf_hf_ge_r_fx = round_fx_o( L_shl_o( L_temp, sub( 15 + 16, sub( add( SWB_BWE_LR_Qbe, QIns ), 30 ) ), &Overflow ), &Overflow ); + Overflow = 0; /* reset BASOP Overflow */ +#else lf_hf_ge_r_fx = round_fx( L_shl( L_temp, sub( 15 + 16, sub( add( SWB_BWE_LR_Qbe, QIns ), 30 ) ) ) ); +#endif exp_normn = norm_s( norm_sum_fx ); exp_normn = sub( exp_normn, 1 ); @@ -1030,3 +1040,5 @@ void hq2_bit_alloc( } return; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/hq2_core_com.c b/lib_com/hq2_core_com.c index 33411f9334f4a4be4fa4610b232538658a9a38c3..aafe578b42507f58737fe96dd5cf4987041e0548 100644 --- a/lib_com/hq2_core_com.c +++ b/lib_com/hq2_core_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "prot.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * mdct_spectrum_denorm() @@ -306,7 +306,7 @@ void reverse_transient_frame_energies( return; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP void bit_allocation_second_fx( Word32 *Rk, Word32 *Rk_sort, @@ -415,7 +415,7 @@ void bit_allocation_second_fx( return; } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /*--------------------------------------------------------------------------* * spt_shorten_domain_pre() diff --git a/lib_com/hq2_noise_inject.c b/lib_com/hq2_noise_inject.c index 3eac77d81bb5c6ee6257879450b658d7cac9177a..0404056dd1ff41587e88825f5ead51872e9ad0d3 100644 --- a/lib_com/hq2_noise_inject.c +++ b/lib_com/hq2_noise_inject.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hq2_noise_inject() diff --git a/lib_com/hq_bit_allocation.c b/lib_com/hq_bit_allocation.c index fbb655e4f32d46e895bdc1aab14b9c3c6fbac152..faba9f8da9ac3e180010436fc99ae163b5f1ad36 100644 --- a/lib_com/hq_bit_allocation.c +++ b/lib_com/hq_bit_allocation.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hq_bit_allocation() diff --git a/lib_com/hq_conf.c b/lib_com/hq_conf.c index ed548171a16629c02424cc01f78da39ddcc77cea..ac9298159358bd297456c9fbee4046a305e83250 100644 --- a/lib_com/hq_conf.c +++ b/lib_com/hq_conf.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hq_configure() diff --git a/lib_com/hq_tools.c b/lib_com/hq_tools.c index 7a154a00a695890085459225c2f49727be3e789f..1d89d0314597493852e85af60f0e57247410d33c 100644 --- a/lib_com/hq_tools.c +++ b/lib_com/hq_tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * Local function prototypes diff --git a/lib_com/hvq_pvq_bitalloc.c b/lib_com/hvq_pvq_bitalloc.c index 9357a37964c7ef055b42e156a329ab7f29e915ab..2808030ae6715e74a318805fa8aaea01a603f2f3 100644 --- a/lib_com/hvq_pvq_bitalloc.c +++ b/lib_com/hvq_pvq_bitalloc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------*/ /* Function hvq_pvq_bitalloc */ diff --git a/lib_com/ifft_rel.c b/lib_com/ifft_rel.c index d0200f87be07faf57c7d7b1976863b08be4d6f4d..fc267a7a10bc80c9cfc5ed856e472959aa780f7c 100644 --- a/lib_com/ifft_rel.c +++ b/lib_com/ifft_rel.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants diff --git a/lib_com/igf_base.c b/lib_com/igf_base.c index 70b202770a9c4188e3fcf44c6368cd5ebaa61afe..ac196510091b86a46c00022395b6520d55d93e48 100644 --- a/lib_com/igf_base.c +++ b/lib_com/igf_base.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * IGF_ApplyTransFac() diff --git a/lib_com/index_pvq_opt.c b/lib_com/index_pvq_opt.c index e09c831dab77b5331c7809644c6925b9e469f162..c762e96c71a820ca99e270120ed74bff0b70f81e 100644 --- a/lib_com/index_pvq_opt.c +++ b/lib_com/index_pvq_opt.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * LOCAL DEFINITIONS @@ -89,8 +89,7 @@ static int16_t local_norm_l_opt( { int16_t l32res; -#define WMC_TOOL_MAN - MAC( 1 ); +#define WMC_TOOL_SKIP if ( l32var == (int32_t) MINNEG ) { @@ -115,7 +114,7 @@ static int16_t local_norm_l_opt( } } } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP return ( l32res ); } diff --git a/lib_com/int_lsp.c b/lib_com/int_lsp.c index 5e1175ab1e2dc944f230f3fb1ea763dc43bb25ce..ff1c9cace4f66b4bcfca0ccb00ef672fec98b867 100644 --- a/lib_com/int_lsp.c +++ b/lib_com/int_lsp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * int_lsp() diff --git a/lib_com/interleave_spectrum.c b/lib_com/interleave_spectrum.c index ae1432a1eb7b7d6527cebfd4ba3142fd5e3ede63..6046bf8f20959d616b33498e6c37edb6a48ca2c3 100644 --- a/lib_com/interleave_spectrum.c +++ b/lib_com/interleave_spectrum.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * interleave_spectrum() diff --git a/lib_com/interpol.c b/lib_com/interpol.c index da4b41a9f9d593c4f7903f1a659d4f1366a78601..4172c4acf7367433db573ef0d1d3c615bdc920b3 100644 --- a/lib_com/interpol.c +++ b/lib_com/interpol.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * interpolation() @@ -70,10 +70,10 @@ float interpolation( for ( i = 0; i < nb_coef; i++ ) { s += ( *x1-- ) * ( *c1 ) + ( *x2++ ) * ( *c2 ); -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP c1 += up_samp; c2 += up_samp; -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } return s; diff --git a/lib_com/isf_dec_amr_wb.c b/lib_com/isf_dec_amr_wb.c index 79eeda7b5464df8acbb1d41f7f32a656b60aa24e..d51731d1c005195f68a932df57fce09dd2d4e4dc 100644 --- a/lib_com/isf_dec_amr_wb.c +++ b/lib_com/isf_dec_amr_wb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * isf_dec_amr_wb() diff --git a/lib_com/ivas_agc_com.c b/lib_com/ivas_agc_com.c index d7a174fe654763706100c955c0fe11e27fc2ab97..e39b8df82d38b2e87b7b046e4b1dd9d5db121265 100644 --- a/lib_com/ivas_agc_com.c +++ b/lib_com/ivas_agc_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,14 +39,18 @@ #include "debug.h" #endif #include -#include "wmops.h" +#include "wmc_auto.h" +#include "prot.h" /*------------------------------------------------------------------------------------------* * Local constants *------------------------------------------------------------------------------------------*/ -#define SQRKMAX ( 1.5f ) -#define NBITS_DIFFG ( 2 ) +#define SQRKMAX ( 1.5f ) +#define NBITS_DIFFG ( 2 ) +#define DBSTEP ( -6.f ) /* desired dB step value in dB*/ +#define ABS_EMIN_MAX ( 3 ) +#define MAXATTEXP ( 1 ) /* the desired maximum attenuation exponent range per frame*/ /*-----------------------------------------------------------------------------------------* * Function ivas_agc_initWindowFunc() @@ -60,12 +64,14 @@ void ivas_agc_initWindowFunc( { int16_t i; float N; + float a; N = (float) ( length - 1 ); + a = 0.5f * ( 1.f - powf( 10.f, DBSTEP / 20.f ) ); for ( i = 0; i < length; i++ ) { - pWinFunc[i] = 0.75f + 0.25f * cosf( EVS_PI * i / N ); + pWinFunc[i] = 1.f + a * ( cosf( EVS_PI * i / N ) - 1.f ); } return; @@ -89,7 +95,7 @@ void ivas_agc_calcGainParams( nbits = NBITS_DIFFG; - *absEmin = (uint16_t) ceilf( logf( ceilf( SQRKMAX * numCoeffs ) ) * INV_LOG_2 ); + *absEmin = max( ABS_EMIN_MAX, (uint16_t) ceilf( logf( ceilf( SQRKMAX * numCoeffs ) ) * INV_LOG_2 ) ); totExp = *absEmin + AGC_EMAX + 1; *betaE = (uint16_t) ceilf( logf( totExp ) * INV_LOG_2 ); @@ -98,10 +104,11 @@ void ivas_agc_calcGainParams( if ( nbits > 0 ) { - Bm = NBITS_DIFFG; + Bm = min( AGC_BITS_PER_CH - 1, NBITS_DIFFG ); } *maxAttExp = ( (uint16_t) powf( 2, Bm ) ) - 2; + *maxAttExp = min( MAXATTEXP, *maxAttExp ); return; } diff --git a/lib_com/ivas_arith.c b/lib_com/ivas_arith.c index 9edbf5f53c1dd7cd031c1d7466a6d9b82a0c1c78..3b8b75138b5d88880e48435726a258583e821c7f 100644 --- a/lib_com/ivas_arith.c +++ b/lib_com/ivas_arith.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" #include "ivas_prot.h" #include "stat_dec.h" diff --git a/lib_com/ivas_avq_pos_reorder_com.c b/lib_com/ivas_avq_pos_reorder_com.c index 66152d26fd6f84b861bc7190939ed3474030dfe4..6f75fa220129801be54f2a2cb7ac809d86111057 100644 --- a/lib_com/ivas_avq_pos_reorder_com.c +++ b/lib_com/ivas_avq_pos_reorder_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * ordr_esti() diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index c299bcaba74e2d2e2d50293242220bfe2abbf7a2..b7d6d467ef9e5f2b3fad4bbe065fca6e5de5f609 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,6 @@ #include #include "options.h" #include "cnst.h" -#include "ivas_error.h" /* clang-format off */ @@ -49,15 +48,13 @@ #define _180_OVER_PI ( 180.0f / EVS_PI ) #define SQRT2 1.414213562373095f +#define SQRT2_OVER_2 (SQRT2 / 2.0f) #define INV_SQRT2 7.071067811865475e-1f /* 1/sqrt(2) */ #define INV_SQRT3 0.577350269189626f /* 1/sqrt(3) */ #define LOG_10 2.30258509299f -#define SQRT2_OVER_2 (SQRT2 / 2.0f) - -#define ALIGN8(x) ((((x)+7) >> 3) << 3) /*----------------------------------------------------------------------------------* * IVAS formats @@ -109,6 +106,8 @@ typedef enum AUDIO_CONFIG_ISM2, /* ISM2 */ AUDIO_CONFIG_ISM3, /* ISM3 */ AUDIO_CONFIG_ISM4, /* ISM4 */ + AUDIO_CONFIG_MASA1, /* MASA1 */ // TBV: seems not to be used + AUDIO_CONFIG_MASA2, /* MASA2 */ // TBV: seems not to be used AUDIO_CONFIG_EXTERNAL /* external renderer */ } AUDIO_CONFIG; @@ -161,18 +160,16 @@ typedef enum * IVAS general constants *----------------------------------------------------------------------------------*/ -#define MAX_INPUT_CHANNELS 16 /* Maximum number of input channels */ -#define MAX_TRANSPORT_CHANNELS 12 /* Maximum number of transport channels */ +#define MAX_INPUT_CHANNELS 16 /* Maximum number of input channels (HOA 3rd order) */ +#define MAX_TRANSPORT_CHANNELS 12 /* Maximum number of transport channels */ #define MAX_INTERN_CHANNELS 16 /* Maximum number of intern channels (HOA 3rd order) */ #define HEAD_ROTATION_HOA_ORDER 3 /* HOA 3rd order */ #define MAX_CICP_CHANNELS 16 /* max channels for loudspeaker layouts (16 for custom layouts)*/ #define MAX_OUTPUT_CHANNELS 16 /* Maximum number of output channels (HOA 3rd order) */ -#define IVAS_MAX_NUM_CH 16 /* == MAX_OUTPUT_CHANNELS */ - -#define FOA_CHANNELS 4 /* number of FOA channels */ #define BINAURAL_CHANNELS 2 /* number of channels for binaural output configuration */ #define CPE_CHANNELS 2 /* number of CPE (stereo) channels */ +#define FOA_CHANNELS 4 /* number of FOA channels */ #define MAX_NUM_OBJECTS 4 /* max. number of audio objects */ #define MAX_SCE MAX_NUM_OBJECTS /* max. number of SCEs */ @@ -193,13 +190,13 @@ typedef enum #define IVAS_MAX_SBA_ORDER 3 /* Maximum supported Ambisonics order */ +#define IVAS_NUM_SUPPORTED_FS 3 /* number of supported sampling-rates in IVAS */ /*----------------------------------------------------------------------------------* * IVAS Bitrates *----------------------------------------------------------------------------------*/ -#define IVAS_SID_4k4 4400 /* SID frame bitrate */ -#define IVAS_SID_5k 5000 /* SBA SID frame bitrate */ +#define IVAS_SID_5k2 5200 /* SID frame bitrate */ #define IVAS_13k2 13200 #define IVAS_16k4 16400 #define IVAS_24k4 24400 @@ -217,8 +214,8 @@ typedef enum #define IVAS_BRATE_MAX IVAS_512k -#define SIZE_IVAS_BRATE_TBL 17 -#define IVAS_NUM_ACTIVE_BRATES (SIZE_IVAS_BRATE_TBL - 3) +#define SIZE_IVAS_BRATE_TBL 16 +#define IVAS_NUM_ACTIVE_BRATES (SIZE_IVAS_BRATE_TBL - 2) /*----------------------------------------------------------------------------------* * IVAS modes : IVAS SCE, IVAS CPE modes (DFT, TD, MDCT stereo) @@ -237,7 +234,7 @@ typedef enum #define NBITS_ELEMENT_MODE 1 /* number of bits to encode the stereo element mode */ #define NBITS_BWIDTH 2 /* number of bits to encode all audio bandwidths */ -/* format signalling in SID frames */ +/* format signaling in SID frames */ #define SID_FORMAT_NBITS 3 /* Bit 0 | Bit 1 | Bit 2 */ /*-------|-------|------ */ #define SID_DFT_STEREO 0x0 /* 0| 0| 0 */ @@ -296,11 +293,9 @@ typedef enum /*----------------------------------------------------------------------------------* - * ISm Constants + * ISM Constants *----------------------------------------------------------------------------------*/ -#define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ - #define ISM_NB_BITS_METADATA_NOMINAL ( ( SCE_CORE_16k_LOW_LIMIT - ACELP_16k_LOW_LIMIT ) / FRAMES_PER_SEC ) /* nominal number of metadata bits - used for configuration of Core-Coder modules */ #define ISM_METADATA_VAD_FLAG_BITS 1 @@ -325,6 +320,15 @@ typedef enum #define ISM_Q_STEP 2.5f #define ISM_Q_STEP_BORDER 5.0f +#define ISM_RADIUS_NBITS 6 +#define ISM_RADIUS_MIN 0.0f +#define ISM_RADIUS_DELTA 0.25f /* Max radius = (2^ISM_RADIUS_NBITS-1)*0.25 = 15.75 */ +#define ISM_EXTENDED_METADATA_BRATE IVAS_64k +#define ISM_EXTENDED_METADATA_BITS 1 +#ifdef FIX_379_EXT_METADATA +#define ISM_METADATA_RS_MAX_FRAMES 5 /* Number of frames with opposite extended metadata flags before switching */ +#endif + /* Parametric ISM */ #define MAX_PARAM_ISM_NBANDS 11 #define MAX_PARAM_ISM_NBANDS_WB 9 @@ -338,6 +342,27 @@ typedef enum #define PARAM_ISM_MAX_CHAN 16 #define PARAM_ISM_HYS_BUF_SIZE 10 +/* ISM DTX */ +#ifdef DISCRETE_ISM_DTX_CNG +#define ISM_DTX_COH_SCA_BITS 4 +#else +#define PARAM_ISM_DTX_COH_SCA_BITS 4 +#endif +#ifdef DISCRETE_ISM_DTX_CNG +#define ISM_DTX_AZI_BITS_HIGH 8 +#define ISM_DTX_ELE_BITS_HIGH 7 +#define ISM_Q_STEP_HIGH (ISM_Q_STEP / 2) +#define ISM_Q_STEP_BORDER_HIGH (ISM_Q_STEP_BORDER / 2) +#define ISM_DTX_AZI_BITS_LOW 6 +#define ISM_DTX_ELE_BITS_LOW 5 +#define ISM_Q_STEP_LOW (ISM_Q_STEP * 2) +#define ISM_Q_STEP_BORDER_LOW (ISM_Q_STEP_BORDER * 2) +#else +#define PARAM_ISM_DTX_AZI_BITS 5 +#define PARAM_ISM_DTX_ELE_BITS 4 +#endif + + typedef enum { ISM_MODE_NONE, @@ -346,19 +371,34 @@ typedef enum } ISM_MODE; -/* ISm metadata bitstream */ +/* ISM metadata bitstream */ enum { IND_ISM_NUM_OBJECTS, - IND_ISM_METADATA_FLAG = IND_ISM_NUM_OBJECTS + MAX_NUM_OBJECTS, + IND_ISM_EXTENDED_FLAG = IND_ISM_NUM_OBJECTS + MAX_NUM_OBJECTS, +#ifdef FIX_379_EXT_METADATA + IND_ISM_METADATA_FLAG, +#else + IND_ISM_METADATA_FLAG = IND_ISM_EXTENDED_FLAG + MAX_NUM_OBJECTS, /* EN2VE: Is this not supposed to be in the loop part below, since it is one per ISM? */ +#endif IND_ISM_VAD_FLAG = IND_ISM_METADATA_FLAG + MAX_NUM_OBJECTS, +#ifdef DISCRETE_ISM_DTX_CNG + IND_ISM_NOISY_SPEECH_FLAG = IND_ISM_VAD_FLAG + MAX_NUM_OBJECTS, + IND_ISM_SCE_ID_DTX, +#else + IND_ISM_SCE_ID_DTX = IND_ISM_VAD_FLAG + MAX_NUM_OBJECTS, + IND_ISM_NOISY_SPEECH_FLAG, +#endif + IND_ISM_DTX_COH_SCA, /* ------------- loop for objects -------------- */ - TAG_ISM_LOOP_START = IND_ISM_VAD_FLAG + MAX_NUM_OBJECTS, + TAG_ISM_LOOP_START = IND_ISM_DTX_COH_SCA + MAX_NUM_OBJECTS, IND_ISM_AZIMUTH_DIFF_FLAG = TAG_ISM_LOOP_START, IND_ISM_AZIMUTH = TAG_ISM_LOOP_START, IND_ISM_ELEVATION_DIFF_FLAG = TAG_ISM_LOOP_START, IND_ISM_ELEVATION = TAG_ISM_LOOP_START, + IND_ISM_RADIUS_DIFF_FLAG = TAG_ISM_LOOP_START, + IND_ISM_RADIUS = TAG_ISM_LOOP_START, TAG_ISM_LOOP_END = TAG_ISM_LOOP_START + 100, /* IVAS_fmToDo: to be reviewed once the final metadata are defined */ /* --------- end of loop for objects ----------- */ @@ -467,6 +507,9 @@ enum #define STEREO_DFT_OFFSET 1 #define STEREO_DFT_NBDIV 2 +#define STEREO_DFT_ITD_CNG_XFADE 100 +#define STEREO_DFT_ITD_CNG_XFADE_RESET 2 + #define STEREO_DFT_DELAY_DEC_BWE_NS ( STEREO_DFT_OFFSET * STEREO_DFT_HOP_NS - ACELP_LOOK_NS ) /* 1.25ms/2.5ms: max delay for core decoder*/ #define STEREO_DFT_ENC_DFT_NB ( STEREO_DFT_OFFSET + 1 ) /*frame + lookahead*/ @@ -521,6 +564,8 @@ typedef enum #define STEREO_DFT_XCORR_LB_MAX 24 +#define STEREO_DFT_IPD_BUF_LEN 5 + #define STEREO_DFT_N_COH_PRED 4 /* Number of intra-frame predictors for coherence vector */ #define STEREO_DFT_COH_PRED_COEFFS 15 /* Number of coefficients per predictor */ #define STEREO_DFT_PRED_NBITS 2 /* Bits to signal predictor (log_2(4) = 2) */ @@ -532,6 +577,8 @@ typedef enum #define STEREO_DFT_SID_GIPD_NBITS 2 #define STEREO_DFT_FD_FILT 0.9f +#define STEREO_DFT_CNG_ITD_CNT 8 + /*Residual prediction*/ #define STEREO_DFT_PAST_MAX 4 #define STEREO_DFT_RES_PRED_BAND_MAX 12 @@ -567,7 +614,9 @@ typedef enum #define NO_SYMB_GR_PRED_G 8 #define STEREO_DFT_RES_BW_MAX 66 /*Maximum number of bin for residual signal in each frame (res_cod_band_max == 6 in 48kHz)*/ -#define SBA_DIRAC_STEREO_NUM_BANDS 5 + +#define SBA_DIRAC_STEREO_NUM_BANDS 12 + #define SBA_DIRAC_NRG_SMOOTH_LONG 10 #define SBA_DIRAC_NRG_SMOOTH_SHORT 3 @@ -757,7 +806,7 @@ enum fea_names #define TDM_L_NOVA_NS 5000000L /* mixing overlap length */ -#define TDM_SECONDARY_SIGNALLING 3 /* number of bits to code the signalling for secondary channel */ +#define TDM_SECONDARY_SIGNALLING 3 /* number of bits to code the signaling for secondary channel */ #define TDM_RATIO_BITS 5 /* number of bits to code the correlation ratio */ #define TDM_LP_REUSE_BITS 1 /* number of bits to code LP reuse flag for secondary channel */ #define TDM_LR_CONTENT_BITS 1 /* number of bits to code flag when the content is LR or not */ @@ -799,17 +848,22 @@ enum fea_names #define MAX_MDCT_ITD_BRATE IVAS_64k #define SNS_LOW_BR_MODE -1 -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT #define SNS_NPTS 16 /* Number of downsampled SNS parameters */ -#define MDCT_ST_PLC_FADEOUT_START_FRAME 3 +#define MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG 0.001f +#define MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME 2 * FRAMES_PER_SEC +#define MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN 20 typedef enum { EQUAL_CORES, TCX10_IN_0_TCX20_IN_1, TCX20_IN_0_TCX10_IN_1, } TONALMDCTCONC_NOISE_GEN_MODE; -#endif + +typedef enum { + ON_FIRST_LOST_FRAME, + ON_FIRST_GOOD_FRAME, +} TONALMDCTCONC_NOISE_SHAPE_WHITENING_MODE; /*----------------------------------------------------------------------------------* @@ -825,21 +879,30 @@ typedef enum { *----------------------------------------------------------------------------------*/ // VE: this should be renamed to e.g. N_SPATIAL_SUBFRAMES #define MAX_PARAM_SPATIAL_SUBFRAMES 4 /* Maximum number of subframes for parameteric spatial coding */ +#define L_SPATIAL_SUBFR_48k (L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES) /*----------------------------------------------------------------------------------* * SBA Constants *----------------------------------------------------------------------------------*/ +#define SBA_FOA_ORDER 1 +#define SBA_HOA2_ORDER 2 +#define SBA_HOA3_ORDER 3 + #define SBA_PLANAR_BITS 1 #define SBA_ORDER_BITS 2 + +#define SBA_MIN_BRATE_HOA IVAS_256k #define SBA_NHARM_HOA3 16 +#define SBA_T_DESIGN_11_SIZE 70 +#define SBA_DTX_BITRATE_THRESHOLD IVAS_80k typedef enum { SBA_MODE_NONE, SBA_MODE_DIRAC, - SBA_MODE_SPAR, + SBA_MODE_SPAR, // VE: this is actually SBA_MODE_SPAR_DIRAC } SBA_MODE; @@ -847,13 +910,7 @@ typedef enum * DirAC Constants *----------------------------------------------------------------------------------*/ -#define DIRAC_MAX_ANA_CHANS 4 /* Maximum number of channels for DirAC analysis */ -#define DIRAC_MAX_TRANS_CHANS 8 /* Maximum number of transport channels for DirAC */ - -#define DIRAC_MIN_BITRATE_8_TRANS_CHAN IVAS_384k -#define DIRAC_MIN_BITRATE_6_TRANS_CHAN IVAS_256k -#define DIRAC_MIN_BITRATE_4_TRANS_CHAN IVAS_160k /* minimum bitrate for sending 4 transport channels (FOA) */ -#define DIRAC_MIN_BITRATE_2_TRANS_CHAN IVAS_48k /* minimum bitrate for sending 2 transport channels (Stereo) */ +#define DIRAC_MAX_ANA_CHANS FOA_CHANNELS /* Maximum number of channels for DirAC analysis */ #define DIRAC_NUM_DIMS 3 /* number of directions to estimate (X,Y,Z) */ #define DIRAC_MAX_NBANDS 12 /* Maximum number of frequency bands for the DirAC Side Parameter decoding */ @@ -904,6 +961,11 @@ typedef enum #define DELAY_DIRAC_SPAR_ENC_CMP_NS 500000L /* here we may set the 24 samples (at 48 kHz) additional delay to something else, leave as is for now*/ #define DELAY_DIRAC_PARAM_DEC_SFR 2 /* Delay to be compensation for DirAC parameters in the decoder (subframes) */ +#ifdef FIX_350_MASA_DELAY_COMP +#define DELAY_MASA_PARAM_DEC_SFR 2 /* Delay to be compensation for MASA parameters in the decoder (subframes) */ +#define SPH_IDX_FRONT ( MASA_NO_POINTS_EQUATOR / 2 ) /* Spherical index corresponding to front direction for setting as default value */ +#endif + #define DIRAC_SLOT_NS 1250000L /* time duration of a time slot, 1.25ms (==DELAY_RENERER_NS/MAX_PARAM_SPATIAL_SUBFRAMES) */ #define DIRAC_SLOT_ENC_NS 5000000L @@ -911,6 +973,8 @@ typedef enum { DIRAC_OPEN, /* initialize to default value */ DIRAC_RECONFIGURE /* HOA3 */ + , + DIRAC_RECONFIGURE_MODE } DIRAC_CONFIG_FLAG; @@ -920,7 +984,7 @@ typedef enum #define SPAR_CONFIG_BW FB -#define IVAS_SPAR_MAX_CH (2*IVAS_MAX_SBA_ORDER + 2) /* FOA + planar HOA */ +#define IVAS_SPAR_MAX_CH (FOA_CHANNELS + 2 * ( IVAS_MAX_SBA_ORDER - 1 )) /* FOA + planar HOA */ #define IVAS_SPAR_P_LOWERTRI ((IVAS_SPAR_MAX_CH - 1) * (IVAS_SPAR_MAX_CH - 2)) >> 1 #define IVAS_SPAR_MAX_C_COEFF (IVAS_SPAR_MAX_CH - IVAS_SPAR_MAX_DMX_CHS) * ( IVAS_SPAR_MAX_DMX_CHS - 1) @@ -957,7 +1021,7 @@ typedef enum WX, WZ, WYiX, -} ivas_spar_foa_pmx_strings_t; +} ivas_spar_pmx_strings_t; #define NUM_MD_Q_COEFS_SET 4 @@ -977,7 +1041,7 @@ typedef enum #define IVAS_SPAR_BR_TABLE_LEN 18 #endif -/* TD decorr */ +/* TD decorr */ // VE: not all 16CH are currently supported -> t be revisited later enum { IVAS_TD_DECORR_OUT_1CH = 1, @@ -1009,9 +1073,9 @@ enum #define IVAS_DECORR_PARM_LOOKAHEAD_TAU 2e-3f #define IVAS_DECORR_PARM_APD_TAU 20e-3f -/* IVAS PCA */ +/* IVAS SBA PCA */ #define IVAS_PCA_NB_SUBR 20 /* 80 -> 0.25 ms, 40 -> 0.5 ms... */ -#define IVAS_PCA_COV_THRES 1e-9f +#define IVAS_PCA_COV_THRES 3e-5f #define IVAS_PCA_QUAT_EPS 1e-7f #define IVAS_PCA_QBITS 19 #define IVAS_PCA_N1 91 @@ -1032,6 +1096,39 @@ typedef enum PCA_MODE_INACTIVE = 1 } ivas_pca_bypass_mode; +enum +{ + PRED_Q_1 = 0, + PRED_Q_7, + PRED_Q_15, + PRED_Q_21, + PRED_Q_31, + PRED_Q_7_ACTIVE_W, + TOTAL_PRED_QUANT_STRATS_HUFF = 5, + PRED_Q_15_ACTIVE_W, + PRED_Q_21_ACTIVE_W, + TOTAL_PRED_QUANT_STRATS_ARITH + }; + +enum +{ + DRCT_Q_1 = 0, + DRCT_Q_7, + DRCT_Q_9, + DRCT_Q_11, + TOTAL_DRCT_QUANT_STRATS + }; + +enum +{ + DECD_Q_1 = 0, + DECD_Q_3, + DECD_Q_5, + DECD_Q_7, + DECD_Q_9, + DECD_Q_11, + TOTAL_DECD_QUANT_STRATS + }; /*----------------------------------------------------------------------------------* * MASA constants @@ -1045,7 +1142,11 @@ typedef enum #define MASA_MAXIMUM_CODING_SUBBANDS 24 #define MASA_MAXIMUM_DIRECTIONS 2 #define MASA_MAX_TRANSPORT_CHANNELS 2 + +#ifndef FIX_350_MASA_DELAY_COMP #define MASA_ENC_DELAY_SLOTS 7 +#endif + #define MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS 5 #define MASA_DELTA_AZI_DCT0 30 @@ -1109,7 +1210,7 @@ typedef enum #define MASA_STEREO_MIN_BITRATE IVAS_24k4 #define MASA_BIT_REDUCT_PARAM 10 - +#define MASA_MAXIMUM_TWO_DIR_BANDS 18 typedef enum { MASA_STEREO_NOT_DEFINED, @@ -1117,6 +1218,13 @@ typedef enum MASA_STEREO_DOWNMIX } MASA_TRANSPORT_SIGNAL_TYPE; +#ifdef FIX_382_MASA_META_FRAMING_ASYNC +typedef enum +{ + MASA_FRAME_1SF, + MASA_FRAME_4SF +} MASA_FRAME_MODE; +#endif /*----------------------------------------------------------------------------------* * Multichannel format @@ -1182,18 +1290,26 @@ typedef enum #define NBBITS_MCT_RATIO 4 #define BITRATE_MCT_RATIO_RANGE ( 1 << NBBITS_MCT_RATIO ) /* Range of the coded bitrate distribution ratio */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE #define LFE_BITS 180 - #define MCT_LFE_MAX_LINE 24 +#endif #define MCT_NUM_BLOCK_DATA_BITS 4 +#ifndef ISSUE_24_CLEANUP_MCT_LFE typedef enum { MCT_CHAN_MODE_REGULAR, MCT_CHAN_MODE_LFE, MCT_CHAN_MODE_IGNORE } MCT_CHAN_MODE; - +#else +typedef enum +{ + MCT_CHAN_MODE_REGULAR, + MCT_CHAN_MODE_IGNORE +} MCT_CHAN_MODE; +#endif /*----------------------------------------------------------------------------------* * Parametric MC Constants @@ -1273,7 +1389,7 @@ typedef enum #define IVAS_LFE_NUM_COEFFS_IN_SUBGRP 2 #define IVAS_LFE_MAX_NUM_DCT_PASS_BINS 8 #define IVAS_LFE_MAX_NUM_DCT_COEFFS (IVAS_LFE_MAX_NUM_DCT_PASS_BINS * IVAS_LFE_NUM_COEFFS_IN_SUBGRP) -#define IVAS_LFE_FADE_LEN_SEC_FLOAT ((float)0.008) +#define IVAS_LFE_FADE_NS 8000000L /* 8.0 ms */ #define IVAS_MAX_NUM_QUANT_STRATS 2 #define IVAS_MAX_NUM_DCT_COEF_GROUPS 4 #define IVAS_LFE_SHIFT_BITS 5 @@ -1297,7 +1413,7 @@ typedef enum #define PANNING_ELE_RESOLUTION 5 #define EFAP_MAX_CHAN_NUM 5 /* Maximum number of channels that constitute a polygon, 4 or 5 */ -#define EFAP_MAX_POLY_SET 70 /* Upper bound on number of polygons; with a Speaker setup of 26.0, we obtain 54 polygons/triangles in the matlab implementation. */ +#define EFAP_MAX_POLY_SET 50 /* Upper bound on number of polygons; with a Speaker setup of 16.0, we obtain 44 polygons/triangles in the matlab implementation. */ #define EFAP_MODE_EFAP 0 /* EFAP Panning */ #define EFAP_MODE_EFIP 1 /* EFIP Panning */ @@ -1316,25 +1432,39 @@ typedef enum *----------------------------------------------------------------------------------*/ #define BINAURAL_MAXBANDS 60 /* Max number of bands */ -#define BINAURAL_CONVBANDS 50 /* Bands upto which convolution is performed */ +#define BINAURAL_CONVBANDS 50 /* Bands upto which convolution is performed */ +#define BINAURAL_NTAPS 7 #define BINAURAL_NTAPS_MAX 96 #define HRTF_SH_ORDER 3 #define HRTF_SH_CHANNELS 16 +#define HRTF_LS_CHANNELS 15 #define HRTF_NUM_BINS 60 #define REVERB_PREDELAY_MAX 20 /* Max input delay for reverb module */ -#define GAIN_LFE 1.88364911f /* Gain applied to LFE during renderering */ +#define GAIN_LFE 1.88364911f /* Gain applied to LFE during renderering */ #define LOW_BIT_RATE_BINAURAL_EQ_BINS 17 /* Number of bins in an EQ applied at low bit rates in binauralization */ #define LOW_BIT_RATE_BINAURAL_EQ_OFFSET 14 /* Offset of bins where the low-bit-rate EQ starts*/ #define BINAURAL_COHERENCE_DIFFERENCE_BINS 9 /* Number of bins for direction-dependent diffuse-field binaural coherence */ +typedef enum +{ + BINAURAL_INPUT_AUDIO_CONFIG_INVALID, + BINAURAL_INPUT_AUDIO_CONFIG_COMBINED, /* 5_1, 5_1_2, 5_1_4, 7_1, 7_1_4 */ + BINAURAL_INPUT_AUDIO_CONFIG_HOA, /* FOA, HOA2, HOA3 */ + BINAURAL_INPUT_AUDIO_CONFIG_UNDEFINED /* Not used */ + +} BINAURAL_INPUT_AUDIO_CONFIG; + +#define HEADROT_ORDER 3 +#define HEADROT_SHMAT_DIM ( ( HEADROT_ORDER + 1 ) * ( HEADROT_ORDER + 1 ) ) +#define HEADROT_SHMAT_DIM2 ( HEADROT_SHMAT_DIM * HEADROT_SHMAT_DIM ) /*----------------------------------------------------------------------------------* * TD Binaural Object renderer *----------------------------------------------------------------------------------*/ -#define MAX_NUM_TDREND_CHANNELS 11 /* max. number of channels in TD renderer (objects or loudspeaker channels) */ +#define MAX_NUM_TDREND_CHANNELS MAX_CICP_CHANNELS /* max. number of channels in TD renderer (objects or loudspeaker channels) */ #define SFX_SPAT_BIN_MAX_NO_OF_OUTPUT_SAMPLES 288 /* 288 = 6 msec @ 48 kHz. */ #define HRTF_MODEL_N_SECTIONS 3 /* No. sections used in approximate evaluation of model */ @@ -1343,8 +1473,14 @@ typedef enum #define SFX_SPAT_BIN_MAX_FILTER_LENGTH 256 #define SPAT_BIN_MAX_INPUT_CHANNELS 1 /* Max number of input channels per source/object. Mono for now, but stereo objects may be considered. */ - -#define BINAURAL_TD_LATENCY_S 0.00675f /* Binaural TD renderer latency in second == 324 samples in between 333 and 315 */ +#define MAX_ITD 50 +#define SFX_SPAT_BIN_SINC_M 5 +#define SFX_SPAT_BIN_NUM_SUBSAMPLES 64 +#define ITD_MEM_LEN (MAX_ITD + SFX_SPAT_BIN_SINC_M) +#define L_SUBFRAME5MS_48k (L_FRAME48k/4) +#define MAX_ANGULAR_STEP (1.0f) +#define MAX_ANGULAR_STEP_INV ( 1.0f / MAX_ANGULAR_STEP ) +#define MAX_INTERPOLATION_STEPS 12 /* ----- Enums - TD Renderer ----- */ @@ -1376,11 +1512,6 @@ typedef enum typedef enum { TDREND_HRFILT_Method_BSplineModel -#ifdef TDREND_HRTF_TABLE_METHODS - , - TDREND_HRFILT_Method_Table_F, - TDREND_HRFILT_Method_Table_S -#endif } TDREND_HRFILT_Method_t; typedef enum @@ -1392,52 +1523,45 @@ typedef enum /*----------------------------------------------------------------------------------* - * Crend constants + * Orientation tracking constants *----------------------------------------------------------------------------------*/ -#define IVAS_REV_MAX_NR_BRANCHES 8 /* setup is for maximum */ - -#define IVAS_REV_MAX_IIR_FILTER_LENGTH 4 /* maximum nr of taps - MUST BE EVEN! */ - -#define RV_FILTER_MAX_FFT_SIZE ( 512 ) -#define RV_FILTER_MAX_HISTORY ( 512 - 160 ) /* for longest history */ - -#define RV_LENGTH_NR_FC ( RV_FILTER_MAX_FFT_SIZE / 2 ) + 1 - - /* Orientation tracking types */ -#define IVAS_ORIENT_TRK_REF 0 -#define IVAS_ORIENT_TRK_AVG 1 +#define IVAS_ORIENT_TRK_NONE 0 +#define IVAS_ORIENT_TRK_REF 1 +#define IVAS_ORIENT_TRK_AVG 2 +#define IVAS_ORIENT_TRK_REF_VEC 3 +#define IVAS_ORIENT_TRK_REF_VEC_LEV 4 typedef enum { - OTR_TRACKING_NONE = IVAS_ORIENT_TRK_REF-1, /* track orientation relative to external reference orientation (default: yaw=pitch=roll=0) */ - OTR_TRACKING_REF_ORIENT = IVAS_ORIENT_TRK_REF, /* track orientation relative to external reference orientation (default: yaw=pitch=roll=0) */ + OTR_TRACKING_NONE = IVAS_ORIENT_TRK_NONE, + OTR_TRACKING_REF_ORIENT = IVAS_ORIENT_TRK_REF, /* track orientation relative to external reference orientation (default: no rotation) */ OTR_TRACKING_AVG_ORIENT = IVAS_ORIENT_TRK_AVG /* track orientation relative to average orientation */ + , + OTR_TRACKING_REF_VEC = IVAS_ORIENT_TRK_REF_VEC, /* track orientation relative to external reference vector */ + OTR_TRACKING_REF_VEC_LEV = IVAS_ORIENT_TRK_REF_VEC_LEV /* track orientation relative to level component of external reference vector */ } OTR_TRACKING_T; - /*----------------------------------------------------------------------------------* * Reverberator constants *----------------------------------------------------------------------------------*/ +#define IVAS_REV_MAX_NR_BRANCHES 8 /* setup is for maximum */ +#define IVAS_REV_MAX_IIR_FILTER_LENGTH 4 /* maximum nr of taps - MUST BE EVEN! */ + +#define RV_FILTER_MAX_FFT_SIZE ( 512 ) +#define RV_FILTER_MAX_HISTORY ( 512 - 160 ) /* for longest history */ +#define RV_LENGTH_NR_FC ( RV_FILTER_MAX_FFT_SIZE / 2 ) + 1 + #define IVAS_REVERB_DEFAULT_N_BANDS 31 -#define IVAS_REVERB_DEFAULT_PRE_DELAY 0.016f -#define IVAS_REVERB_DEFAULT_INPUT_DELAY 0.1f /*----------------------------------------------------------------------------------* * FB mixer constants *----------------------------------------------------------------------------------*/ -#define IVAS_ONE_BY_960 0.001041666666666666f -#define IVAS_ONE_BY_640 0.0015625f -#define IVAS_ONE_BY_320 0.003125f -#define IVAS_ONE_BY_240 0.004166666666666667f -#define IVAS_ONE_BY_160 0.00625f -#define IVAS_ONE_BY_80 0.0125f - #define IVAS_960_PT_LEN 960 #define IVAS_640_PT_LEN 640 #define IVAS_480_PT_LEN 480 @@ -1447,8 +1571,6 @@ typedef enum #define IVAS_80_PT_LEN 80 #define IVAS_40_PT_LEN 40 -#define IVAS_NUM_SUPPORTED_FS 3 - /* FB windows ovlp */ #define IVAS_FB_4MS_48K_SAMP 192 #define IVAS_FB_1MS_48K_SAMP 48 @@ -1554,6 +1676,15 @@ typedef enum #define SPAR_DIRAC_DTX_BANDS ( SPAR_DTX_BANDS + DIRAC_DTX_BANDS ) #define CLDFB_PAR_WEIGHT_START_BAND 7 + +/*----------------------------------------------------------------------------------* + * Limiter constants + *----------------------------------------------------------------------------------*/ + +#define IVAS_LIMITER_THRESHOLD 32729 /* -0.01 dBFS */ +#define IVAS_LIMITER_ATTACK_SECONDS 0.005f + + #endif /* clang-format on */ /* IVAS_CNST_H */ diff --git a/lib_com/ivas_cov_smooth.c b/lib_com/ivas_cov_smooth.c index d85ea259ac708816ff51284663ea5360bb4723ec..86d421124c24c8b998253b15588aa656d85f8978 100644 --- a/lib_com/ivas_cov_smooth.c +++ b/lib_com/ivas_cov_smooth.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,10 +36,10 @@ #include "debug.h" #endif #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" - +#define BAND_SMOOTH_REST_START_IDX ( 2 ) /*-----------------------------------------------------------------------------------------* * Function ivas_set_up_cov_smoothing() * @@ -47,10 +47,11 @@ *-----------------------------------------------------------------------------------------*/ static void ivas_set_up_cov_smoothing( - ivas_cov_smooth_state_t *pState, + ivas_cov_smooth_state_t *hCovState, ivas_filterbank_t *pFb, const float max_update_rate, - const int16_t min_pool_size + const int16_t min_pool_size, + const int16_t nchan_inp /* i : number of input channels */ #ifdef LBR_SBA_EXTRA_COV_SMOOTH , const int32_t ivas_total_brate @@ -58,63 +59,91 @@ static void ivas_set_up_cov_smoothing( ) { int16_t j, k; - - for ( j = 0; j < pFb->filterbank_num_bands; j++ ) +#ifdef LBR_SBA_DM_COV_FIX + if ( ivas_total_brate < IVAS_24k4 ) { - float update_factor = 0.0f; - - for ( k = 0; k < pFb->fb_bin_to_band.pFb_active_bins_per_band[j]; k++ ) + for ( j = 0; j < pFb->filterbank_num_bands; j++ ) + { + float update_factor; + update_factor = 0.0f; + float *p_bin_to_band; + p_bin_to_band = pFb->fb_bin_to_band.pp_short_stride_bin_to_band[j]; + int16_t active_bins; + active_bins = pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[j]; + + for ( k = 0; k < active_bins; k++ ) + { + update_factor += p_bin_to_band[k]; + } + + hCovState->pSmoothing_factor[j] = update_factor / min_pool_size; + #ifdef LBR_SBA_EXTRA_COV_SMOOTH + float smooth_fact; + if ( ivas_total_brate < IVAS_24k4 ) + { + smooth_fact = 0.5f; + } + else + { + smooth_fact = 0.75; + } + hCovState->pSmoothing_factor[j] *= ( j + 1 ) * smooth_fact; + #else + hCovState->pSmoothing_factor[j] *= ( j + 1 ) * 0.75f; + #endif + + if ( hCovState->pSmoothing_factor[j] > max_update_rate ) + { + hCovState->pSmoothing_factor[j] = max_update_rate; + } + } + } + else +#endif + if ( nchan_inp <= FOA_CHANNELS ) + { + for ( j = 0; j < pFb->filterbank_num_bands; j++ ) { - update_factor += pFb->fb_bin_to_band.pFb_bin_to_band[j][k]; - } + float update_factor; + update_factor = 0.0f; + + for ( k = 0; k < pFb->fb_bin_to_band.pFb_active_bins_per_band[j]; k++ ) + { + update_factor += pFb->fb_bin_to_band.pFb_bin_to_band[j][k]; + } - pState->pSmoothing_factor[j] = update_factor / min_pool_size; + hCovState->pSmoothing_factor[j] = update_factor / min_pool_size; - if ( pState->pSmoothing_factor[j] > max_update_rate ) - { - pState->pSmoothing_factor[j] = max_update_rate; + if ( hCovState->pSmoothing_factor[j] > max_update_rate ) + { + hCovState->pSmoothing_factor[j] = max_update_rate; + } } } - -#ifdef LBR_SBA_DM_COV_FIX - for ( j = 0; j < pFb->filterbank_num_bands; j++ ) + else { - float update_factor; - update_factor = 0.0f; - float *p_bin_to_band; - p_bin_to_band = pFb->fb_bin_to_band.pp_short_stride_bin_to_band[j]; - int16_t active_bins; - active_bins = pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[j]; - - for ( k = 0; k < active_bins; k++ ) - { - update_factor += p_bin_to_band[k]; - } - - pState->pSmoothing_factor[j] = update_factor / min_pool_size; -#ifdef LBR_SBA_EXTRA_COV_SMOOTH - float smooth_fact; - if (ivas_total_brate < IVAS_24k4) - { - smooth_fact = 0.5f; - } - else + for ( j = 0; j < pFb->filterbank_num_bands; j++ ) { - smooth_fact = 0.75; - } - pState->pSmoothing_factor[j] *= ( j + 1 ) * smooth_fact; -#else - pState->pSmoothing_factor[j] *= ( j + 1 ) * 0.75f; -#endif - - if ( pState->pSmoothing_factor[j] > max_update_rate ) - { - pState->pSmoothing_factor[j] = max_update_rate; + float update_factor; + float *p_bin_to_band; + int16_t active_bins; + update_factor = 0.0f; + p_bin_to_band = pFb->fb_bin_to_band.pp_short_stride_bin_to_band[j]; + active_bins = pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[j]; + for ( k = 0; k < active_bins; k++ ) + { + update_factor += p_bin_to_band[k]; + } + hCovState->pSmoothing_factor[j] = update_factor / min_pool_size; + hCovState->pSmoothing_factor[j] *= ( j + 1 ) * 0.75f; + if ( hCovState->pSmoothing_factor[j] > max_update_rate ) + { + hCovState->pSmoothing_factor[j] = max_update_rate; + } } } -#endif + hCovState->prior_bank_idx = -1; - pState->prior_bank_idx = -1; return; } @@ -139,12 +168,12 @@ ivas_error ivas_spar_covar_smooth_enc_open( ivas_cov_smooth_state_t *hCovState; int16_t i, j; - if ( ( hCovState = (ivas_cov_smooth_state_t *) count_malloc( sizeof( ivas_cov_smooth_state_t ) ) ) == NULL ) + if ( ( hCovState = (ivas_cov_smooth_state_t *) malloc( sizeof( ivas_cov_smooth_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder" ); } - if ( ( hCovState->pSmoothing_factor = (float *) count_malloc( sizeof( float ) * cov_smooth_cfg->max_bands ) ) == NULL ) + if ( ( hCovState->pSmoothing_factor = (float *) malloc( sizeof( float ) * cov_smooth_cfg->max_bands ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder" ); } @@ -153,18 +182,20 @@ ivas_error ivas_spar_covar_smooth_enc_open( { for ( j = 0; j < nchan_inp; j++ ) { - if ( ( hCovState->pPrior_cov_real[i][j] = (float *) count_malloc( sizeof( float ) * cov_smooth_cfg->max_bands ) ) == NULL ) + if ( ( hCovState->pPrior_cov_real[i][j] = (float *) malloc( sizeof( float ) * cov_smooth_cfg->max_bands ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder" ); } set_zero( hCovState->pPrior_cov_real[i][j], cov_smooth_cfg->max_bands ); } } + #ifdef LBR_SBA_EXTRA_COV_SMOOTH - ivas_set_up_cov_smoothing( hCovState, pFb, cov_smooth_cfg->max_update_rate, cov_smooth_cfg->min_pool_size, ivas_total_brate ); + ivas_set_up_cov_smoothing( hCovState, pFb, cov_smooth_cfg->max_update_rate, cov_smooth_cfg->min_pool_size, nchan_inp, ivas_total_brate ); #else - ivas_set_up_cov_smoothing( hCovState, pFb, cov_smooth_cfg->max_update_rate, cov_smooth_cfg->min_pool_size ); + ivas_set_up_cov_smoothing( hCovState, pFb, cov_smooth_cfg->max_update_rate, cov_smooth_cfg->min_pool_size, nchan_inp ); #endif + *hCovState_out = hCovState; return IVAS_ERR_OK; @@ -189,19 +220,19 @@ void ivas_spar_covar_smooth_enc_close( if ( hCovState != NULL ) { - count_free( hCovState->pSmoothing_factor ); + free( hCovState->pSmoothing_factor ); hCovState->pSmoothing_factor = NULL; for ( i = 0; i < nchan_inp; i++ ) { for ( j = 0; j < nchan_inp; j++ ) { - count_free( hCovState->pPrior_cov_real[i][j] ); + free( hCovState->pPrior_cov_real[i][j] ); hCovState->pPrior_cov_real[i][j] = NULL; } } - count_free( hCovState ); + free( hCovState ); hCovState_out = NULL; } @@ -217,60 +248,59 @@ void ivas_spar_covar_smooth_enc_close( static void ivas_compute_smooth_cov( ivas_cov_smooth_state_t *hCovState, - ivas_cov_smooth_in_buf_t *pIn_buf, ivas_filterbank_t *pFb, float *pCov_buf[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float *pPrior_cov_buf[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], const float fac, const int16_t start_band, - const int16_t end_band ) + const int16_t end_band, + const int16_t num_ch, + const int16_t transient_det[2] ) { int16_t i, j, k; int16_t prev_idx = hCovState->prior_bank_idx; - int16_t num_ch = pIn_buf->num_ch; float factor = 0; -#ifdef LBR_SBA_DM_COV_FIX - int16_t sm_b = 2; + int16_t sm_b; int16_t non_sm_b_idx; -#endif + sm_b = BAND_SMOOTH_REST_START_IDX; assert( end_band <= pFb->filterbank_num_bands ); - if ( prev_idx == -1 || pIn_buf->reset_cov == 1 ) + if ( prev_idx == -1 || transient_det[1] == 1 ) { -#ifdef LBR_SBA_DM_COV_FIX - non_sm_b_idx = start_band; - if ( prev_idx != -1 ) + for ( i = 0; i < num_ch; i++ ) + { + for ( k = start_band; k < end_band; k++ ) + { + pCov_buf[i][i][k] += ( hCovState->pSmoothing_factor[k] * fac ); + } + } + } + else if ( transient_det[0] == 1 ) + { + non_sm_b_idx = min( sm_b, end_band ); + for ( i = 0; i < num_ch; i++ ) { - non_sm_b_idx = min( sm_b, end_band ); - for ( i = 0; i < num_ch; i++ ) + for ( j = 0; j < num_ch; j++ ) { - for ( j = 0; j < num_ch; j++ ) + if ( i == j ) + { + factor = fac; + } + else + { + factor = 0.0f; + } + + for ( k = start_band; k < non_sm_b_idx; k++ ) { - if ( i == j ) - { - factor = fac; - } - else - { - factor = 0.0f; - } - - for ( k = start_band; k < non_sm_b_idx; k++ ) - { - pCov_buf[i][j][k] = pPrior_cov_buf[i][j][k] + ( hCovState->pSmoothing_factor[k] * ( pCov_buf[i][j][k] - pPrior_cov_buf[i][j][k] + factor ) ); - } + pCov_buf[i][j][k] = pPrior_cov_buf[i][j][k] + ( hCovState->pSmoothing_factor[k] * ( pCov_buf[i][j][k] - pPrior_cov_buf[i][j][k] + factor ) ); } } } -#endif for ( i = 0; i < num_ch; i++ ) { -#ifdef LBR_SBA_DM_COV_FIX for ( k = non_sm_b_idx; k < end_band; k++ ) -#else - for ( k = start_band; k < end_band; k++ ) -#endif { pCov_buf[i][i][k] += ( hCovState->pSmoothing_factor[k] * fac ); } @@ -311,22 +341,23 @@ static void ivas_compute_smooth_cov( void ivas_cov_smooth_process( ivas_cov_smooth_state_t *hCovState, /* i/o: Covariance state handle */ - ivas_cov_smooth_in_buf_t *pIn_buf, + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], ivas_filterbank_t *pFb, /* i/o: FB handle */ const int16_t start_band, - const int16_t end_band ) + const int16_t end_band, + const int16_t num_ch, + const int16_t transient_det[2] ) { int16_t i, j; - int16_t num_ch = pIn_buf->num_ch; int16_t num_bands = end_band - start_band; - ivas_compute_smooth_cov( hCovState, pIn_buf, pFb, pIn_buf->cov_real, hCovState->pPrior_cov_real, 1e-20f, start_band, end_band ); + ivas_compute_smooth_cov( hCovState, pFb, cov_real, hCovState->pPrior_cov_real, 1e-20f, start_band, end_band, num_ch, transient_det ); for ( i = 0; i < num_ch; i++ ) { for ( j = 0; j < num_ch; j++ ) { - mvr2r( &pIn_buf->cov_real[i][j][start_band], &hCovState->pPrior_cov_real[i][j][start_band], num_bands ); + mvr2r( &cov_real[i][j][start_band], &hCovState->pPrior_cov_real[i][j][start_band], num_bands ); } } diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index 9644a45c6c0361239e6831fa0c1a146b7d36d12d..172dbc53650f2b5945e7600a7fdd3937a92b669d 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "ivas_prot.h" #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -60,7 +60,7 @@ ivas_error ivas_dirac_config( ) { IVAS_FORMAT ivas_format; - int16_t sba_order, sba_planar; + int16_t sba_order; int16_t *nSCE, *nCPE, *element_mode, *nchan_transport; int32_t ivas_total_brate; DIRAC_CONFIG_DATA_HANDLE hConfig; @@ -82,8 +82,7 @@ ivas_error ivas_dirac_config( nCPE = &( (Encoder_Struct *) st_ivas )->nCPE; element_mode = &( (Encoder_Struct *) st_ivas )->hEncoderConfig->element_mode_init; nchan_transport = &( (Encoder_Struct *) st_ivas )->nchan_transport; - sba_order = ( (Encoder_Struct *) st_ivas )->hEncoderConfig->sba_order; - sba_planar = ( (Encoder_Struct *) st_ivas )->hEncoderConfig->sba_planar; + sba_order = ( (Encoder_Struct *) st_ivas )->sba_analysis_order; ivas_total_brate = ( (Encoder_Struct *) st_ivas )->hEncoderConfig->ivas_total_brate; Fs = ( (Encoder_Struct *) st_ivas )->hEncoderConfig->input_Fs; band_grouping = ( (Encoder_Struct *) st_ivas )->hDirAC->band_grouping; @@ -92,7 +91,7 @@ ivas_error ivas_dirac_config( sba_mode = ( (Encoder_Struct *) st_ivas )->sba_mode; if ( ( (Encoder_Struct *) st_ivas )->hSpar != NULL ) { - hFbMdft = ( (Encoder_Struct *) st_ivas )->hSpar->hSparFoa->hFbMixer; + hFbMdft = ( (Encoder_Struct *) st_ivas )->hSpar->hFbMixer; } else { @@ -107,8 +106,7 @@ ivas_error ivas_dirac_config( nCPE = &( (Decoder_Struct *) st_ivas )->nCPE; element_mode = &( (Decoder_Struct *) st_ivas )->element_mode_init; nchan_transport = &( (Decoder_Struct *) st_ivas )->nchan_transport; - sba_order = ( (Decoder_Struct *) st_ivas )->sba_order; - sba_planar = ( (Decoder_Struct *) st_ivas )->sba_planar; + sba_order = ( (Decoder_Struct *) st_ivas )->sba_analysis_order; ivas_total_brate = ( (Decoder_Struct *) st_ivas )->hDecoderConfig->ivas_total_brate; Fs = ( (Decoder_Struct *) st_ivas )->hDecoderConfig->output_Fs; band_grouping = ( (Decoder_Struct *) st_ivas )->hDirAC->band_grouping; @@ -117,7 +115,7 @@ ivas_error ivas_dirac_config( sba_mode = ( (Decoder_Struct *) st_ivas )->sba_mode; if ( ( (Decoder_Struct *) st_ivas )->hSpar != NULL ) { - hFbMdft = ( (Decoder_Struct *) st_ivas )->hSpar->hSparFoa->hFbMixer; + hFbMdft = ( (Decoder_Struct *) st_ivas )->hSpar->hFbMixer; } else { @@ -142,8 +140,7 @@ ivas_error ivas_dirac_config( if ( ivas_format == SBA_FORMAT ) /* skip for MASA decoder */ { - if ( ( error = ivas_dirac_sba_config( hQMetaData, nchan_transport, nSCE, nCPE, element_mode, ivas_total_brate, sba_order, sba_planar, - sba_mode, hConfig->nbands - spar_dirac_split_band ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_sba_config( hQMetaData, nchan_transport, nSCE, nCPE, element_mode, ivas_total_brate, sba_order, sba_mode, hConfig->nbands - spar_dirac_split_band ) ) != IVAS_ERR_OK ) { return error; } @@ -178,20 +175,18 @@ ivas_error ivas_dirac_config( if ( sba_mode == SBA_MODE_SPAR ) { ivas_dirac_config_bands( band_grouping, IVAS_MAX_NUM_BANDS, (int16_t) ( Fs * INV_CLDFB_BANDWIDTH + 0.5f ), - dirac_to_spar_md_bands, hQMetaData->useLowerBandRes, hConfig->enc_param_start_band, - hFbMdft ); + dirac_to_spar_md_bands, hQMetaData->useLowerBandRes, hConfig->enc_param_start_band, hFbMdft ); } else { ivas_dirac_config_bands( band_grouping, hConfig->nbands, (int16_t) ( Fs * INV_CLDFB_BANDWIDTH + 0.5f ), - NULL, 0, 0, - hFbMdft ); + NULL, 0, 0, hFbMdft ); } - return error; } + /*------------------------------------------------------------------------- * ivas_dirac_sba_config_bands() * @@ -302,6 +297,7 @@ void ivas_dirac_config_bands( return; } + /*------------------------------------------------------------------------- * ivas_dirac_sba_config() * @@ -316,7 +312,6 @@ ivas_error ivas_dirac_sba_config( int16_t *element_mode, /* i/o: element mode of the core coder */ int32_t sba_total_brate, /* i : SBA total bitrate */ const int16_t sba_order, /* i : Ambisonic (SBA) order */ - const int16_t sba_planar, /* i : SBA planar flag */ const SBA_MODE sba_mode, /* i : SBA mode */ const int16_t nbands /* i : number of frequency bands */ ) @@ -327,12 +322,12 @@ ivas_error ivas_dirac_sba_config( ivas_error error; error = IVAS_ERR_OK; - hQMetaData->is_masa_type_format = 0; + hQMetaData->is_masa_ivas_format = 0; if ( sba_mode == SBA_MODE_SPAR ) { - /*map the bitrate for SID frame*/ - if ( sba_total_brate == IVAS_SID_5k ) + /* map the bitrate for SID frame */ + if ( sba_total_brate == IVAS_SID_5k2 ) { if ( *element_mode == IVAS_SCE ) { @@ -343,7 +338,9 @@ ivas_error ivas_dirac_sba_config( sba_total_brate = ACELP_48k; } } + ivas_set_qmetadata_maxbit_req( hQMetaData, SBA_FORMAT ); + if ( sba_total_brate <= IVAS_16k4 ) { hQMetaData->useLowerRes = 1; @@ -383,7 +380,7 @@ ivas_error ivas_dirac_sba_config( else if ( sba_total_brate <= IVAS_24k4 ) { hQMetaData->bits_frame_nominal = ACELP_16k40 / FRAMES_PER_SEC; - hQMetaData->metadata_max_bits = 106; + hQMetaData->metadata_max_bits = 103; } else if ( sba_total_brate <= IVAS_32k ) { @@ -427,11 +424,11 @@ ivas_error ivas_dirac_sba_config( return error; } - if ( sba_total_brate > IVAS_SID_4k4 ) + if ( sba_total_brate > IVAS_SID_5k2 ) { - *nchan_transport = ivas_dirac_getNumTransportChannels( sba_total_brate, sba_order, sba_planar ); + *nchan_transport = ivas_get_sba_num_TCs( sba_total_brate, sba_order ); } - else if ( sba_total_brate == IVAS_SID_4k4 ) + else if ( sba_total_brate == IVAS_SID_5k2 ) { switch ( *element_mode ) { @@ -571,79 +568,6 @@ ivas_error ivas_dirac_sba_config( } -/*------------------------------------------------------------------------- - * ivas_dirac_getNumTransportChannels() - * - * - *------------------------------------------------------------------------*/ - -/*! r: number of IVAS transport channels */ -int16_t ivas_dirac_getNumTransportChannels( - const int32_t sba_total_brate, /* i : SBA total bitrate */ - const int16_t sba_order, /* i : SBA order */ - const int16_t sba_planar /* i : SBA planar flag */ -) -{ - int16_t num_channels; - - num_channels = 0; - - if ( sba_total_brate >= DIRAC_MIN_BITRATE_8_TRANS_CHAN ) - { - switch ( sba_order ) - { - case 3: - num_channels = sba_planar ? 7 : 8; - break; - case 2: - num_channels = sba_planar ? 5 : 6; - break; - case 1: - num_channels = sba_planar ? 3 : 4; - break; - default: - assert( 0 && "Order not supported!" ); - } - } - else if ( sba_total_brate >= DIRAC_MIN_BITRATE_6_TRANS_CHAN ) - { - switch ( sba_order ) - { - case 3: - case 2: - num_channels = sba_planar ? 5 : 6; - break; - case 1: - num_channels = sba_planar ? 3 : 4; - break; - default: - assert( 0 && "Order not supported!" ); - } - } - else if ( sba_total_brate >= DIRAC_MIN_BITRATE_4_TRANS_CHAN ) - { - if ( sba_planar ) - { - num_channels = 3; - } - else - { - num_channels = 4; - } - } - else if ( sba_total_brate >= DIRAC_MIN_BITRATE_2_TRANS_CHAN ) - { - num_channels = 2; - } - else - { - num_channels = 1; - } - - return num_channels; -} - - /*------------------------------------------------------------------------- * computeDirectionVectors() * diff --git a/lib_com/ivas_entropy_coder_common.c b/lib_com/ivas_entropy_coder_common.c index 6e71b44d0ac26885cefdc7acdd48be8a63407040..a2fa26cad9f53c6a8f50eaf139331277e3f95f8a 100644 --- a/lib_com/ivas_entropy_coder_common.c +++ b/lib_com/ivas_entropy_coder_common.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,10 @@ #include "debug.h" #endif #include "ivas_prot.h" -#include "wmops.h" +#include "ivas_rom_com.h" +#include "math.h" +#include "prot.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------------------------* @@ -91,3 +94,365 @@ void ivas_get_cum_freq_model( return; } + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_map_num_pred_r_to_idx() + * + * Map the ivas_arith_pred_r_consts and ivas_huff_pred_r_consts tables + *-----------------------------------------------------------------------------------------*/ + +int16_t ivas_map_num_pred_r_to_idx( + const int16_t num_quant_points_pred_r, + const int16_t active_w_flag ) +{ + int16_t pred_r_to_idx = -1; + if ( active_w_flag == 0 ) + { + switch ( num_quant_points_pred_r ) + { + case 1: + pred_r_to_idx = PRED_Q_1; + break; + case 7: + pred_r_to_idx = PRED_Q_7; + break; + case 15: + pred_r_to_idx = PRED_Q_15; + break; + case 21: + pred_r_to_idx = PRED_Q_21; + break; + case 31: + pred_r_to_idx = PRED_Q_31; + break; + default: + assert( !"Forbidden value for prediction quantization strategy index" ); + break; + } + } + else + { + switch ( num_quant_points_pred_r ) + { + case 7: + pred_r_to_idx = PRED_Q_7_ACTIVE_W; + break; + case 15: + pred_r_to_idx = PRED_Q_15_ACTIVE_W; + break; + case 21: + pred_r_to_idx = PRED_Q_21_ACTIVE_W; + break; + default: + assert( !"Forbidden value for prediction quantization strategy index" ); + break; + } + } + + return pred_r_to_idx; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_map_num_drct_r_to_idx() + * + * Map the ivas_arith_drct_r_consts and ivas_huff_drct_r_consts tables + *-----------------------------------------------------------------------------------------*/ + +int16_t ivas_map_num_drct_r_to_idx( + const int16_t num_quant_points_drct_r ) +{ + int16_t drct_r_to_idx = -1; + switch ( num_quant_points_drct_r ) + { + case 1: + drct_r_to_idx = DRCT_Q_1; + break; + case 7: + drct_r_to_idx = DRCT_Q_7; + break; + case 9: + drct_r_to_idx = DRCT_Q_9; + break; + case 11: + drct_r_to_idx = DRCT_Q_11; + break; + default: + assert( !"Forbidden value for DRCT quantization strategy index" ); + break; + } + return drct_r_to_idx; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_map_num_decd_r_to_idx() + * + * Map the ivas_arith_decd_r_consts and ivas_huff_decd_r_consts tables + *-----------------------------------------------------------------------------------------*/ + +int16_t ivas_map_num_decd_r_to_idx( + const int16_t num_quant_points_decd_r ) +{ + int16_t decd_r_to_idx = -1; + switch ( num_quant_points_decd_r ) + { + case 1: + decd_r_to_idx = DECD_Q_1; + break; + case 3: + decd_r_to_idx = DECD_Q_3; + break; + case 5: + decd_r_to_idx = DECD_Q_5; + break; + case 7: + decd_r_to_idx = DECD_Q_7; + break; + case 9: + decd_r_to_idx = DECD_Q_9; + break; + case 11: + decd_r_to_idx = DECD_Q_11; + break; + default: + assert( !"Forbidden value for DECD quantization strategy index" ); + break; + } + + return decd_r_to_idx; +} + + +/*---------------------------------------------------------------------------------------- - * + * Function ivas_spar_arith_com_init() + * + * arith coder init + *---------------------------------------------------------------------------------------- - */ + +static void ivas_spar_arith_com_init( + ivas_arith_t *pArith, + const ivas_freq_models_t *pFreq_models, + ivas_arith_t *pArith_diff, + const int16_t q_levels, + const int16_t enc_dec ) +{ + int16_t i, j; + float sum; + + pArith->vals = pFreq_models->vals; + pArith->range = q_levels; + pArith->num_models = pFreq_models->num_models; + pArith->dyn_model_bits = ivas_get_bits_to_encode( pArith->num_models - 1 ); + pArith->pFreq_model = pFreq_models->freq_model[0]; + + ivas_get_cum_freq_model( pArith->pFreq_model, pArith->range, pArith->cum_freq[0] ); + + for ( i = 0; i < pArith->num_models - 1; i++ ) + { + pArith->pAlt_freq_models[i] = pFreq_models->freq_model[i + 1]; + ivas_get_cum_freq_model( pArith->pAlt_freq_models[i], pArith->range, pArith->cum_freq[i + 1] ); + } + + if ( enc_dec == ENC ) + { + sum = 0; + for ( i = 1; i < pArith->range + 1; i++ ) + { + sum += pArith->pFreq_model[i]; + } + + for ( i = 1; i < pArith->range + 1; i++ ) + { + pArith->saved_dist_arr[0][i - 1] = log2f( max( 1e-10f, pArith->pFreq_model[i] ) ); + pArith->saved_dist_arr[0][i - 1] -= log2f( max( 1e-10f, sum ) ); + } + + for ( j = 0; j < pArith->num_models - 1; j++ ) + { + sum = 0; + for ( i = 1; i < pArith->range + 1; i++ ) + { + sum += pArith->pAlt_freq_models[j][i]; + } + + for ( i = 1; i < pArith->range + 1; i++ ) + { + pArith->saved_dist_arr[j + 1][i - 1] = log2f( max( 1e-10f, pArith->pAlt_freq_models[j][i] ) ); + pArith->saved_dist_arr[j + 1][i - 1] -= log2f( max( 1e-10f, sum ) ); + } + } + } + + pArith_diff->vals = pFreq_models->diff_vals; + pArith_diff->range = q_levels; + pArith_diff->num_models = pFreq_models->diff_num_models; + pArith_diff->dyn_model_bits = ivas_get_bits_to_encode( pArith_diff->num_models - 1 ); + pArith_diff->pFreq_model = pFreq_models->diff_freq_model[0]; + + ivas_get_cum_freq_model( pArith_diff->pFreq_model, pArith_diff->range, pArith_diff->cum_freq[0] ); + + for ( i = 0; i < pArith_diff->num_models - 1; i++ ) + { + pArith_diff->pAlt_freq_models[i] = pFreq_models->diff_freq_model[i + 1]; + ivas_get_cum_freq_model( pArith_diff->pAlt_freq_models[i], pArith_diff->range, pArith_diff->cum_freq[i + 1] ); + } + + if ( enc_dec == ENC ) + { + sum = 0; + for ( i = 1; i < pArith_diff->range + 1; i++ ) + { + sum += pArith_diff->pFreq_model[i]; + } + + for ( i = 1; i < pArith_diff->range + 1; i++ ) + { + pArith_diff->saved_dist_arr[0][i - 1] = log2f( max( 1e-10f, pArith_diff->pFreq_model[i] ) ); + pArith_diff->saved_dist_arr[0][i - 1] -= log2f( max( 1e-10f, sum ) ); + } + + for ( j = 0; j < pArith_diff->num_models - 1; j++ ) + { + sum = 0; + for ( i = 1; i < pArith_diff->range + 1; i++ ) + { + sum += pArith_diff->pAlt_freq_models[j][i]; + } + + for ( i = 1; i < pArith_diff->range + 1; i++ ) + { + pArith_diff->saved_dist_arr[j + 1][i - 1] = log2f( max( 1e-10f, pArith_diff->pAlt_freq_models[j][i] ) ); + pArith_diff->saved_dist_arr[j + 1][i - 1] -= log2f( max( 1e-10f, sum ) ); + } + } + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_spar_arith_coeffs_com_init() + * + * Init for Arithm. coding + *-----------------------------------------------------------------------------------------*/ + +void ivas_spar_arith_coeffs_com_init( + ivas_arith_coeffs_t *pArith_coeffs, + ivas_spar_md_com_cfg *pSpar_cfg, + const int16_t table_idx, + const int16_t enc_dec ) +{ + int16_t i, pred_r_index, drct_r_index, decd_r_index; + int16_t num_quant_points_pred_r, num_quant_points_drct_r, num_quant_points_decd_r; + + for ( i = 0; i < MAX_QUANT_STRATS; i++ ) + { + num_quant_points_pred_r = ivas_spar_br_table_consts[table_idx].q_lvls[i][0]; /* 0: pred_r */ + pred_r_index = ivas_map_num_pred_r_to_idx( num_quant_points_pred_r, ivas_spar_br_table_consts[table_idx].active_w ); + ivas_spar_arith_com_init( &pArith_coeffs->pred_arith_re[i], &ivas_arith_pred_r_consts[pred_r_index], + &pArith_coeffs->pred_arith_re_diff[i], pSpar_cfg->quant_strat[i].PR.q_levels[0], enc_dec ); + + num_quant_points_drct_r = ivas_spar_br_table_consts[table_idx].q_lvls[i][1]; /* 1: drct_r */ + drct_r_index = ivas_map_num_drct_r_to_idx( num_quant_points_drct_r ); + ivas_spar_arith_com_init( &pArith_coeffs->drct_arith_re[i], &ivas_arith_drct_r_consts[drct_r_index], + &pArith_coeffs->drct_arith_re_diff[i], pSpar_cfg->quant_strat[i].C.q_levels[0], enc_dec ); + + num_quant_points_decd_r = ivas_spar_br_table_consts[table_idx].q_lvls[i][2]; /* 2: decd_r */ + decd_r_index = ivas_map_num_decd_r_to_idx( num_quant_points_decd_r ); + ivas_spar_arith_com_init( &pArith_coeffs->decd_arith_re[i], &ivas_arith_decd_r_consts[decd_r_index], + &pArith_coeffs->decd_arith_re_diff[i], pSpar_cfg->quant_strat[i].P_r.q_levels[0], enc_dec ); + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_huffman_dec_init_min_max_len() + * + * Find min and max length in codebook and finalize initialization of ivas_huffman_cfg_t. + *-----------------------------------------------------------------------------------------*/ + +static void ivas_huffman_dec_init_min_max_len( + ivas_huffman_cfg_t *p_huff_cfg ) +{ + int16_t i, code_len; + const int16_t *codebook; + + codebook = p_huff_cfg->codebook; + + p_huff_cfg->min_len = p_huff_cfg->sym_len; + p_huff_cfg->max_len = 0; + + for ( i = 0; i < p_huff_cfg->sym_len; i++ ) + { + code_len = codebook[1]; + if ( p_huff_cfg->min_len > code_len ) + { + p_huff_cfg->min_len = code_len; + } + if ( p_huff_cfg->max_len < code_len ) + { + p_huff_cfg->max_len = code_len; + } + codebook = codebook + 3; + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_spar_huff_coeffs_com_init() + * + * Init for Huffman decoding + *-----------------------------------------------------------------------------------------*/ + +void ivas_spar_huff_coeffs_com_init( + ivas_huff_coeffs_t *pHuff_coeffs, + ivas_spar_md_com_cfg *pSpar_cfg, + const int16_t table_idx, + const int16_t enc_dec ) +{ + int16_t i, pred_r_index, drct_r_index, decd_r_index; + int16_t num_quant_points_pred_r, num_quant_points_drct_r, num_quant_points_decd_r; + ivas_huffman_cfg_t *p_huff_cfg; + + for ( i = 0; i < MAX_QUANT_STRATS; i++ ) + { + p_huff_cfg = &pHuff_coeffs->pred_huff_re[i]; + num_quant_points_pred_r = ivas_spar_br_table_consts[table_idx].q_lvls[i][0]; /* 0: pred_r */ + pred_r_index = ivas_map_num_pred_r_to_idx( num_quant_points_pred_r, 0 ); + p_huff_cfg->codebook = &ivas_huff_pred_r_consts[pred_r_index].code_book[0][0]; + if ( enc_dec == DEC ) + { + p_huff_cfg->sym_len = pSpar_cfg->quant_strat[i].PR.q_levels[0]; + ivas_huffman_dec_init_min_max_len( p_huff_cfg ); + } + + p_huff_cfg = &pHuff_coeffs->drct_huff_re[i]; + num_quant_points_drct_r = ivas_spar_br_table_consts[table_idx].q_lvls[i][1]; /* 1: drct_r */ + drct_r_index = ivas_map_num_drct_r_to_idx( num_quant_points_drct_r ); + p_huff_cfg->codebook = &ivas_huff_drct_r_consts[drct_r_index].code_book[0][0]; + if ( enc_dec == DEC ) + { + p_huff_cfg->sym_len = pSpar_cfg->quant_strat[i].C.q_levels[0]; + ivas_huffman_dec_init_min_max_len( p_huff_cfg ); + } + + p_huff_cfg = &pHuff_coeffs->decd_huff_re[i]; + num_quant_points_decd_r = ivas_spar_br_table_consts[table_idx].q_lvls[i][2]; /* 2: decd_r */ + decd_r_index = ivas_map_num_decd_r_to_idx( num_quant_points_decd_r ); + p_huff_cfg->codebook = &ivas_huff_decd_r_consts[decd_r_index].code_book[0][0]; + if ( enc_dec == DEC ) + { + p_huff_cfg->sym_len = pSpar_cfg->quant_strat[i].P_r.q_levels[0]; + ivas_huffman_dec_init_min_max_len( p_huff_cfg ); + } + } + + return; +} diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index 58c45ee5ee0752f962207c834494e6d2070ba3aa..9438ad44a1d309ca433de3e9a420f441e2245dad 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -59,7 +59,8 @@ typedef enum IVAS_ERR_INVALID_CICP_INDEX, IVAS_ERR_INVALID_BITRATE, IVAS_ERR_INVALID_MASA_CONFIG, - IVAS_ERR_TOO_MANY_OBJECT_INPUTS, + IVAS_ERR_TOO_MANY_INPUTS, + IVAS_ERR_MISSING_METADATA, IVAS_ERR_INDEX_OUT_OF_BOUNDS, IVAS_ERR_RECONFIGURE_NOT_SUPPORTED, IVAS_ERR_INVALID_FEC_CONFIG, @@ -80,12 +81,18 @@ typedef enum IVAS_ERR_INVALID_INDEX, IVAS_ERR_NOT_SUPPORTED_OPTION, IVAS_ERR_NOT_IMPLEMENTED, -#ifdef DEBUGGING - IVAS_ERR_INVALID_FORCE_MODE, -#endif + IVAS_ERR_WAITING_FOR_BITSTREAM, IVAS_ERR_FILE_READER_TIMESTAMP_MISMATCH, IVAS_ERR_ISM_FILE_READER_INVALID_METADATA_FORMAT, + IVAS_ERR_ISM_INVALID_METADATA_VALUE, IVAS_ERR_INVALID_MASA_FORMAT_METADATA_FILE, + IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, +#ifdef DEBUGGING + IVAS_ERR_INVALID_FORCE_MODE, +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + IVAS_ERR_INVALID_AGC, +#endif +#endif /*----------------------------------------* * input data errors * @@ -114,6 +121,18 @@ typedef enum IVAS_ERR_BITSTREAM_WRITER_INVALID_FORMAT, IVAS_ERR_BITSTREAM_READER_INVALID_DATA, IVAS_ERR_BITSTREAM_READER_INVALID_FORMAT, + IVAS_ERR_NO_FILE_OPEN, + IVAS_ERR_SAMPLING_RATE_UNKNOWN, + + /*----------------------------------------* + * renderer (lib_rend only) * + *----------------------------------------*/ + + IVAS_ERR_NUM_CHANNELS_UNKNOWN, + IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT, + IVAS_ERR_INVALID_INPUT_ID, + IVAS_ERR_WRONG_NUM_CHANNELS, + IVAS_ERR_INVALID_BUFFER_SIZE, /*----------------------------------------* * unknown error * @@ -125,18 +144,7 @@ typedef enum static inline const char *ivas_error_to_string( ivas_error error_code ) { - /* For error categories that are likely to still have many changes to - * specific error codes, return one string per category */ - if ( ( error_code & 0xF000 ) == 0x1000 ) - { - return "API error"; - } - if ( ( error_code & 0xF000 ) == 0x2000 ) - { - return "data error"; - } - - /* For categories that are unlikely to change, use more specific strings */ + /* Try to match to a specific string */ switch ( error_code ) { case IVAS_ERR_OK: @@ -147,6 +155,20 @@ static inline const char *ivas_error_to_string( ivas_error error_code ) return "Internal error"; case IVAS_ERR_INTERNAL_FATAL: return "Internal fatal error"; + case IVAS_ERR_INVALID_SAMPLING_RATE: + return "Invalid sampling rate"; + case IVAS_ERR_INVALID_OUTPUT_FORMAT: + return "Invalid output format"; + case IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT: + return "Invalid custom loudspeaker layout"; + case IVAS_ERR_INVALID_INPUT_ID: + return "Invalid input ID"; + case IVAS_ERR_WRONG_NUM_CHANNELS: + return "Wrong number of channels"; + case IVAS_ERR_INVALID_BUFFER_SIZE: + return "Invalid buffer size"; + case IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED: + return "Unsupported input/output config pair"; case IVAS_ERR_FAILED_FILE_OPEN: return "File open error"; case IVAS_ERR_FAILED_FILE_WRITE: @@ -161,6 +183,17 @@ static inline const char *ivas_error_to_string( ivas_error error_code ) break; } + /* For error categories that are likely to still have many changes to + * specific error codes, return one string per category */ + if ( ( error_code & 0xF000 ) == 0x1000 ) + { + return "API error"; + } + if ( ( error_code & 0xF000 ) == 0x2000 ) + { + return "data error"; + } + return "Unknown error"; } diff --git a/lib_com/ivas_error_utils.h b/lib_com/ivas_error_utils.h index 412bd075b49c3e7fd575c905e636462345b3bc74..034369656bc8e54c703e986e3479a514eafa1c2b 100644 --- a/lib_com/ivas_error_utils.h +++ b/lib_com/ivas_error_utils.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/ivas_fb_mixer.c b/lib_com/ivas_fb_mixer.c index e9032d274d31d82494f8fb1d3c419b06429766be..3e0d68049a882a32013c749048d986c11953b09f 100644 --- a/lib_com/ivas_fb_mixer.c +++ b/lib_com/ivas_fb_mixer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -110,7 +110,7 @@ ivas_error ivas_fb_set_cfg( { IVAS_FB_CFG *pFb_cfg; - if ( ( pFb_cfg = (IVAS_FB_CFG *) count_malloc( sizeof( IVAS_FB_CFG ) ) ) == NULL ) + if ( ( pFb_cfg = (IVAS_FB_CFG *) malloc( sizeof( IVAS_FB_CFG ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer config" ); } @@ -174,7 +174,8 @@ ivas_error ivas_fb_set_cfg( ivas_error ivas_FB_mixer_open( IVAS_FB_MIXER_HANDLE *hFbMixer_out, /* i/o: FB mixer handle */ const int32_t sampling_rate, /* i : sampling rate */ - IVAS_FB_CFG *fb_cfg /* i : FB config. handle */ + IVAS_FB_CFG *fb_cfg, /* i : FB config. handle */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ) { IVAS_FB_MIXER_HANDLE hFbMixer; @@ -186,14 +187,26 @@ ivas_error ivas_FB_mixer_open( frame_len = (int16_t) ( sampling_rate / FRAMES_PER_SEC ); - if ( ( hFbMixer = (IVAS_FB_MIXER_HANDLE) count_malloc( sizeof( IVAS_FB_MIXER_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); - } + hFbMixer = *hFbMixer_out; - if ( ( hFbMixer->pFb = (ivas_filterbank_t *) count_malloc( sizeof( ivas_filterbank_t ) ) ) == NULL ) + if ( !spar_reconfig_flag ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + if ( ( hFbMixer = (IVAS_FB_MIXER_HANDLE) malloc( sizeof( IVAS_FB_MIXER_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + + if ( fb_cfg->num_out_chans > 0 ) + { + if ( ( hFbMixer->pFb = (ivas_filterbank_t *) malloc( sizeof( ivas_filterbank_t ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + } + else + { + hFbMixer->pFb = NULL; + } } if ( fb_cfg->active_w_mixing == -1 ) @@ -220,12 +233,12 @@ ivas_error ivas_FB_mixer_open( { j = fb_cfg->remix_order[i]; - if ( ( hFbMixer->ppFilterbank_inFR_re[j] = (float *) count_malloc( sizeof( float ) * frame_len ) ) == NULL ) + if ( ( hFbMixer->ppFilterbank_inFR_re[j] = (float *) malloc( sizeof( float ) * frame_len ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); } - if ( ( hFbMixer->ppFilterbank_inFR_im[j] = (float *) count_malloc( sizeof( float ) * frame_len ) ) == NULL ) + if ( ( hFbMixer->ppFilterbank_inFR_im[j] = (float *) malloc( sizeof( float ) * frame_len ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); } @@ -240,9 +253,10 @@ ivas_error ivas_FB_mixer_open( { num_chs_alloc = fb_cfg->num_in_chans; } + for ( i = 0; i < num_chs_alloc; i++ ) { - if ( ( hFbMixer->ppFilterbank_prior_input[i] = (float *) count_malloc( sizeof( float ) * fb_cfg->prior_input_length ) ) == NULL ) + if ( ( hFbMixer->ppFilterbank_prior_input[i] = (float *) malloc( sizeof( float ) * fb_cfg->prior_input_length ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); } @@ -253,7 +267,7 @@ ivas_error ivas_FB_mixer_open( { float *pTemp_mem; - if ( ( pTemp_mem = (float *) count_malloc( sizeof( float ) * fb_cfg->num_out_chans * fb_cfg->num_in_chans * IVAS_MAX_NUM_BANDS ) ) == NULL ) + if ( ( pTemp_mem = (float *) malloc( sizeof( float ) * fb_cfg->num_out_chans * fb_cfg->num_in_chans * IVAS_MAX_NUM_BANDS ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer" ); } @@ -268,74 +282,68 @@ ivas_error ivas_FB_mixer_open( } } - if ( fb_cfg->num_out_chans > 0 ) + if ( !spar_reconfig_flag ) { - const int16_t *pActive_bins_per_band, *pActive_bins_per_band_abs, *pStart_offset, *pStart_offset_abs; + if ( fb_cfg->num_out_chans > 0 ) + { + const int16_t *pActive_bins_per_band, *pActive_bins_per_band_abs, *pStart_offset, *pStart_offset_abs; - num_bands = ivas_get_num_bands( sampling_rate ); + num_bands = ivas_get_num_bands( sampling_rate ); - ivas_get_active_bins( &pActive_bins_per_band, &pActive_bins_per_band_abs, &pStart_offset, &pStart_offset_abs, sampling_rate ); + ivas_get_active_bins( &pActive_bins_per_band, &pActive_bins_per_band_abs, &pStart_offset, &pStart_offset_abs, sampling_rate ); - for ( i = 0; i < num_bands; i++ ) - { - if ( ( hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] = (float *) count_malloc( sizeof( float ) * pActive_bins_per_band_abs[i] ) ) == NULL ) + if ( fb_cfg->active_w_mixing != -1 ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + for ( i = 0; i < num_bands; i++ ) + { + if ( ( hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] = (float *) malloc( sizeof( float ) * pActive_bins_per_band_abs[i] ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + } } - } - if ( sampling_rate != 48000 ) - { - int16_t num_diff_bands, start_diff_band_non48k; + if ( sampling_rate != 48000 ) + { + int16_t num_diff_bands, start_diff_band_non48k; - num_diff_bands = MAX_NUM_BANDS_DIFF_NON48K; - start_diff_band_non48k = num_bands - num_diff_bands; + num_diff_bands = MAX_NUM_BANDS_DIFF_NON48K; + start_diff_band_non48k = num_bands - num_diff_bands; - hFbMixer->num_diff_bands = num_diff_bands; + hFbMixer->num_diff_bands = num_diff_bands; - for ( j = start_diff_band_non48k; j < num_bands; j++ ) - { - if ( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[0][j] = (float *) count_malloc( sizeof( float ) * pActive_bins_per_band[j] ) ) == NULL ) + for ( j = start_diff_band_non48k; j < num_bands; j++ ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); - } + if ( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[0][j] = (float *) malloc( sizeof( float ) * pActive_bins_per_band[j] ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } - if ( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[1][j] = (float *) count_malloc( sizeof( float ) * pActive_bins_per_band[j] ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + if ( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[1][j] = (float *) malloc( sizeof( float ) * pActive_bins_per_band[j] ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } } } } - } - else - { - int16_t k; - - /* ignore all the deeper filter bank stuff for now */ - hFbMixer->num_diff_bands = 0; - hFbMixer->pFb->fb_consts.pFilterbank_bins_per_band = NULL; - hFbMixer->pFb->fb_consts.pFilterbank_bins_start_offset = NULL; - - for ( i = 0; i < 2; i++ ) + else { - for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ ) - { - hFbMixer->pFb->fb_consts.ppFilterbank_FRs[i][k] = NULL; - hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[i][k] = NULL; - } - } - for ( i = 0; i < IVAS_MAX_NUM_FB_BANDS; i++ ) - { - hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] = NULL; + /* ignore all the deeper filter bank stuff for now */ + hFbMixer->num_diff_bands = 0; } } hFbMixer->fb_cfg = fb_cfg; + set_s( hFbMixer->first_frame, 1, hFbMixer->fb_cfg->num_out_chans ); + set_s( hFbMixer->first_frame + hFbMixer->fb_cfg->num_out_chans, 0, IVAS_SPAR_MAX_CH - hFbMixer->fb_cfg->num_out_chans ); - if ( ( error = ivas_filterbank_setup( hFbMixer, sampling_rate ) ) != IVAS_ERR_OK ) + if ( !spar_reconfig_flag ) { - return error; + if ( ( error = ivas_filterbank_setup( hFbMixer, sampling_rate ) ) != IVAS_ERR_OK ) + { + return error; + } } *hFbMixer_out = hFbMixer; @@ -351,8 +359,9 @@ ivas_error ivas_FB_mixer_open( *------------------------------------------------------------------------*/ void ivas_FB_mixer_close( - IVAS_FB_MIXER_HANDLE *hFbMixer_in, /* i/o: FB mixer handle */ - const int32_t sampling_rate /* i : sampling rate in Hz */ + IVAS_FB_MIXER_HANDLE *hFbMixer_in, /* i/o: FB mixer handle */ + const int32_t sampling_rate, /* i : sampling rate in Hz */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ) { IVAS_FB_MIXER_HANDLE hFbMixer; @@ -384,10 +393,10 @@ void ivas_FB_mixer_close( { j = fb_cfg->remix_order[i]; - count_free( hFbMixer->ppFilterbank_inFR_re[j] ); + free( hFbMixer->ppFilterbank_inFR_re[j] ); hFbMixer->ppFilterbank_inFR_re[j] = NULL; - count_free( hFbMixer->ppFilterbank_inFR_im[j] ); + free( hFbMixer->ppFilterbank_inFR_im[j] ); hFbMixer->ppFilterbank_inFR_im[j] = NULL; } } @@ -402,56 +411,64 @@ void ivas_FB_mixer_close( } for ( i = 0; i < num_chs_alloc; i++ ) { - count_free( hFbMixer->ppFilterbank_prior_input[i] ); + free( hFbMixer->ppFilterbank_prior_input[i] ); hFbMixer->ppFilterbank_prior_input[i] = NULL; } if ( ( fb_cfg->active_w_mixing != -1 ) && ( fb_cfg->num_out_chans > 0 ) ) { - count_free( hFbMixer->prior_mixer[0][0] ); + free( hFbMixer->prior_mixer[0][0] ); hFbMixer->prior_mixer[0][0] = NULL; } - if ( fb_cfg->num_out_chans > 0 ) + if ( !spar_reconfig_flag ) { - num_bands = hFbMixer->pFb->filterbank_num_bands; - - for ( i = 0; i < num_bands; i++ ) + if ( fb_cfg->num_out_chans > 0 ) { - count_free( hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] ); - hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] = NULL; - } + num_bands = hFbMixer->pFb->filterbank_num_bands; - if ( sampling_rate != 48000 ) - { - int16_t start_diff_band_non48k; - start_diff_band_non48k = num_bands - hFbMixer->num_diff_bands; + if ( fb_cfg->active_w_mixing != -1 ) + { + for ( i = 0; i < num_bands; i++ ) + { + free( hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] ); + hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] = NULL; + } + } - for ( j = start_diff_band_non48k; j < num_bands; j++ ) + if ( sampling_rate != 48000 ) { - count_free( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[0][j] ); - hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[0][j] = NULL; + int16_t start_diff_band_non48k; + start_diff_band_non48k = num_bands - hFbMixer->num_diff_bands; - count_free( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[1][j] ); - hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[1][j] = NULL; + for ( j = start_diff_band_non48k; j < num_bands; j++ ) + { + free( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[0][j] ); + hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[0][j] = NULL; + + free( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[1][j] ); + hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[1][j] = NULL; + } } } - } - - if ( hFbMixer->pFb != NULL ) - { - count_free( hFbMixer->pFb ); - hFbMixer->pFb = NULL; + if ( hFbMixer->pFb != NULL ) + { + free( hFbMixer->pFb ); + hFbMixer->pFb = NULL; + } } if ( hFbMixer->fb_cfg != NULL ) { - count_free( hFbMixer->fb_cfg ); + free( hFbMixer->fb_cfg ); hFbMixer->fb_cfg = NULL; } - count_free( hFbMixer ); - hFbMixer = NULL; + if ( !spar_reconfig_flag ) + { + free( hFbMixer ); + hFbMixer = NULL; + } } return; @@ -794,7 +811,8 @@ void ivas_fb_mixer_get_in_out_mapping( static int16_t ivas_calculate_abs_fr( ivas_filterbank_t *pFb, - const int32_t sampling_rate ) + const int32_t sampling_rate, + const int16_t alloc_fb_resp ) { int16_t frame_len; float ppFilterbank_FRs_s[L_FRAME48k]; @@ -932,7 +950,7 @@ static int16_t ivas_calculate_abs_fr( temp = 0; } - if ( j < ( abs_active_bins + abs_start_offset ) && j >= abs_start_offset ) + if ( j < ( abs_active_bins + abs_start_offset ) && j >= abs_start_offset && alloc_fb_resp != -1 ) { pFb->fb_bin_to_band.pFb_bin_to_band[i][idx++] = temp; } @@ -949,19 +967,22 @@ static int16_t ivas_calculate_abs_fr( } } - for ( j = 0; j < bands; j++ ) + if ( alloc_fb_resp != -1 ) { - int16_t abs_active_bins = pFb->fb_bin_to_band.pFb_active_bins_per_band[j]; - int16_t abs_start_offset = pFb->fb_bin_to_band.pFb_start_bin_per_band[j]; - - for ( i = 0; i < abs_active_bins; i++ ) + for ( j = 0; j < bands; j++ ) { - pFb->fb_bin_to_band.pFb_bin_to_band[j][i] /= ppFilterbank_FRs_s[i + abs_start_offset]; - /*if(pFb->fb_bin_to_band.pFb_bin_to_band[j][i] > 0.5f) + int16_t abs_active_bins = pFb->fb_bin_to_band.pFb_active_bins_per_band[j]; + int16_t abs_start_offset = pFb->fb_bin_to_band.pFb_start_bin_per_band[j]; + + for ( i = 0; i < abs_active_bins; i++ ) { - num_active_bands = j + 1; - break; - }*/ + pFb->fb_bin_to_band.pFb_bin_to_band[j][i] /= ppFilterbank_FRs_s[i + abs_start_offset]; + /*if(pFb->fb_bin_to_band.pFb_bin_to_band[j][i] > 0.5f) + { + num_active_bands = j + 1; + break; + }*/ + } } } @@ -1028,10 +1049,6 @@ static ivas_error ivas_filterbank_setup( error = IVAS_ERR_OK; - set_s( hFbMixer->first_frame, 1, pCfg->num_out_chans ); - set_s( hFbMixer->first_frame + pCfg->num_out_chans, 0, IVAS_SPAR_MAX_CH - pCfg->num_out_chans ); - - if ( pCfg->num_out_chans > 0 ) { hFbMixer->pFb->filterbank_num_bands = ivas_get_num_bands( sampling_rate ); @@ -1049,10 +1066,6 @@ static ivas_error ivas_filterbank_setup( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Wrong FB in ivas_filterbank_setup()!" ); } } - else - { - hFbMixer->pFb->filterbank_num_bands = 0; - } hFbMixer->cross_fade_end_offset = pCfg->fade_len + pCfg->pcm_offset; hFbMixer->cross_fade_start_offset = hFbMixer->cross_fade_end_offset - pCfg->fade_len; @@ -1088,8 +1101,8 @@ static ivas_error ivas_filterbank_setup( for ( j = 0; j < IVAS_MAX_NUM_FB_BANDS; j++ ) { - pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[j] = 0; /* aka num_active_bins per spar band */ - pFb->fb_bin_to_band.p_short_stride_start_bin_per_band[j] = 0; /* first considered bin index per spar band */ + pFb->fb_bin_to_band.p_short_stride_num_bins_per_band[j] = 0; /* aka num_active_bins per SPAR band */ + pFb->fb_bin_to_band.p_short_stride_start_bin_per_band[j] = 0; /* first considered bin index per SPAR band */ pFb->fb_bin_to_band.pp_short_stride_bin_to_band[j] = NULL; for ( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) { @@ -1105,7 +1118,7 @@ static ivas_error ivas_filterbank_setup( offset += pFb->fb_consts.pFilterbank_bins_per_band[j]; } - ivas_calculate_abs_fr( pFb, sampling_rate ); + ivas_calculate_abs_fr( pFb, sampling_rate, pCfg->active_w_mixing ); } else { @@ -1156,7 +1169,7 @@ static ivas_error ivas_filterbank_setup( pFb->fb_consts.ppFilterbank_FRs[1][j] = (const float *) pFb->fb_consts.ppFilterbank_FRs_non48k[1][j]; } - ivas_calculate_abs_fr( pFb, sampling_rate ); + ivas_calculate_abs_fr( pFb, sampling_rate, pCfg->active_w_mixing ); } } diff --git a/lib_com/ivas_filters.c b/lib_com/ivas_filters.c index 96148e5ca36e307389a66e64956a433adf320950..d89370e7951c9a45b9ebaeeb9ab56b2786c3fd29 100644 --- a/lib_com/ivas_filters.c +++ b/lib_com/ivas_filters.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,11 +38,11 @@ #include "ivas_prot.h" #include "ivas_cnst.h" #include "ivas_stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* - * Static functions declaration + * Local functions declaration *------------------------------------------------------------------------------------------*/ static void ivas_iir_2_filter( ivas_filters_process_state_t *filter_state, float *pIn_Out, const int16_t length, const int16_t stage ); @@ -55,9 +55,9 @@ static void ivas_iir_2_filter( ivas_filters_process_state_t *filter_state, float *-----------------------------------------------------------------------------------------*/ void ivas_filters_init( - ivas_filters_process_state_t *filter_state, - const float *filt_coeff, - const int16_t order ) + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + const float *filt_coeff, /* i : filter coefficients */ + const int16_t order ) /* i : filter order */ { int16_t i; filter_state->order = order; @@ -107,9 +107,9 @@ void ivas_filters_init( *-----------------------------------------------------------------------------------------*/ void ivas_filter_process( - ivas_filters_process_state_t *filter_state, - float *pIn_Out, - const int16_t length ) + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + float *pIn_Out, /* i/o: signal subject to filtering */ + const int16_t length ) /* i : filter order */ { switch ( filter_state->order ) diff --git a/lib_com/ivas_ism_config.c b/lib_com/ivas_ism_com.c similarity index 72% rename from lib_com/ivas_ism_config.c rename to lib_com/ivas_ism_com.c index abd955ce18b0e9eb5b54cd044d0dfce7e87de87a..297e2cfb45b3724438270d7fcf69bb85f52cb77b 100644 --- a/lib_com/ivas_ism_config.c +++ b/lib_com/ivas_ism_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,11 +37,12 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_stat_com.h" #include "ivas_rom_com.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -50,7 +51,7 @@ #define FRMS_PER_SECOND ( 1000000000 / FRAME_SIZE_NS ) -#define BRATE_ISM_INACTIVE 2450 /* CoreCoder bitrate in ISm inactive frames */ +#define BRATE_ISM_INACTIVE 2450 /* CoreCoder bitrate in ISM inactive frames */ #define BITS_ISM_INACTIVE ( BRATE_ISM_INACTIVE / FRMS_PER_SECOND ) #define BETA_ISM_LOW_IMP 0.6f @@ -87,15 +88,15 @@ static void bitbudget_to_brate( *-------------------------------------------------------------------*/ ivas_error ivas_ism_config( - const int32_t ism_total_brate, /* i : ISms total bitrate */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t num_obj, /* i : number of objects */ - ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ - const int16_t localVAD[MAX_NUM_OBJECTS], /* i : local VAD flag */ - const int16_t ism_imp[], /* i : ISM importance flags */ - int32_t element_brate[], /* o : element bitrate per object */ - int32_t total_brate[], /* o : total bitrate per object */ - int16_t nb_bits_metadata[] /* i/o: number of metadata bits */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t nchan_ism, /* i : number of objects */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + const int16_t localVAD[MAX_NUM_OBJECTS], /* i : local VAD flag */ + const int16_t ism_imp[], /* i : ISM importance flags */ + int32_t element_brate[], /* o : element bitrate per object */ + int32_t total_brate[], /* o : total bitrate per object */ + int16_t nb_bits_metadata[] /* i/o: number of metadata bits */ ) { int16_t ch; @@ -128,10 +129,14 @@ ivas_error ivas_ism_config( bits_element[n_ISms - 1] += bits_ism % n_ISms; bitbudget_to_brate( bits_element, element_brate, n_ISms ); - /* count ISm common signalling bits */ + /* count ISM common signaling bits */ if ( hIsmMeta != NULL ) { - nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS + num_obj; + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) + { + nb_bits_metadata[0] += ISM_EXTENDED_METADATA_BITS; + } + nb_bits_metadata[0] += n_ISms * ISM_METADATA_FLAG_BITS + nchan_ism; for ( ch = 0; ch < n_ISms; ch++ ) { @@ -199,7 +204,7 @@ ivas_error ivas_ism_config( diff = 0; for ( ch = 0; ch < n_ISms; ch++ ) { - int32_t limit; + int16_t limit; limit = MIN_BRATE_SWB_BWE / FRMS_PER_SECOND; if ( element_brate[ch] < MIN_BRATE_SWB_STEREO ) /* replicate function set_bw() -> check the coded audio band-width */ @@ -219,12 +224,12 @@ ivas_error ivas_ism_config( else if ( ism_imp[ch] == ISM_LOW_IMP ) { tmp = (int16_t) ( BETA_ISM_LOW_IMP * bits_CoreCoder[ch] ); - tmp = (int16_t) max( limit, bits_CoreCoder[ch] - tmp ); + tmp = max( limit, tmp ); } else if ( ism_imp[ch] == ISM_MEDIUM_IMP ) { tmp = (int16_t) ( BETA_ISM_MEDIUM_IMP * bits_CoreCoder[ch] ); - tmp = (int16_t) max( limit, bits_CoreCoder[ch] - tmp ); + tmp = max( limit, tmp ); } else /* ism_imp[ch] == ISM_HIGH_IMP */ { @@ -289,7 +294,7 @@ ivas_error ivas_ism_config( #ifdef DEBUGGING if ( bits_CoreCoder[ch] == SID_2k40 / FRAMES_PER_SEC ) { - printf( "\nWarning: ISm bitbudget equal to SID!\n" ); + printf( "\nWarning: ISM bitbudget equal to SID!\n" ); } #endif break; @@ -308,7 +313,7 @@ ivas_error ivas_ism_config( tmpL = sum_l( total_brate, n_ISms ) + bits_side * FRMS_PER_SECOND; if ( sum_l( element_brate, n_ISms ) != tmpL ) { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "\nError: Mismatch in ISm bit-budget distribution. Exiting!\n" ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "\nError: Mismatch in ISM bit-budget distribution. Exiting!\n" ); } } #endif @@ -320,7 +325,7 @@ ivas_error ivas_ism_config( /*-------------------------------------------------------------------* * ivas_ism_reset_metadata() * - * Reset ISm metadata parameters + * Reset ISM metadata parameters *-------------------------------------------------------------------*/ void ivas_ism_reset_metadata( @@ -329,15 +334,20 @@ void ivas_ism_reset_metadata( { hIsmMeta->azimuth = 0.0f; hIsmMeta->elevation = 0.0f; + hIsmMeta->yaw = 0.0f; + hIsmMeta->pitch = 0.0f; + hIsmMeta->radius = 1.0f; return; } + /*-------------------------------------------------------------------* * ivas_ism_reset_metadata_API() * - * Reset ISm metadata parameters + * Reset ISM metadata parameters *-------------------------------------------------------------------*/ + void ivas_ism_reset_metadata_API( ISM_METADATA_HANDLE hIsmMeta /* i/o: ISM metadata handle */ ) @@ -348,6 +358,7 @@ void ivas_ism_reset_metadata_API( return; } + /*-------------------------------------------------------------------* * ism_quant_meta() * @@ -356,10 +367,12 @@ void ivas_ism_reset_metadata_API( /*! r: index of the winning codeword */ int16_t ism_quant_meta( - const float val, /* i : scalar value to quantize */ - float *valQ, /* o : quantized value */ - const float borders[], /* i : level borders */ - const int16_t cbsize /* i : codebook size */ + const float val, /* i : scalar value to quantize */ + float *valQ, /* o : quantized value */ + const float borders[], /* i : level borders */ + const float q_step, /* i : quantization step */ + const float q_step_border, /* i : quantization step at the border */ + const int16_t cbsize /* i : codebook size */ ) { int16_t idx, idx_start; @@ -369,19 +382,19 @@ int16_t ism_quant_meta( { qlow = borders[0]; idx_start = 0; - step = ISM_Q_STEP_BORDER; + step = q_step_border; } else if ( val <= borders[2] ) { qlow = borders[1]; - idx_start = (int16_t) ( ( borders[1] - borders[0] ) / ISM_Q_STEP_BORDER ); - step = ISM_Q_STEP; + idx_start = (int16_t) ( ( borders[1] - borders[0] ) / q_step_border ); + step = q_step; } else { qlow = borders[2]; - idx_start = (int16_t) ( cbsize - 1 - ( borders[3] - borders[2] ) / ISM_Q_STEP_BORDER ); - step = ISM_Q_STEP_BORDER; + idx_start = (int16_t) ( cbsize - 1 - ( borders[3] - borders[2] ) / q_step_border ); + step = q_step_border; } idx = idx_start + (int16_t) max( 0.f, min( cbsize - 1, ( ( val - qlow ) / step + 0.5f ) ) ); @@ -399,31 +412,33 @@ int16_t ism_quant_meta( /*! r: dequantized value */ float ism_dequant_meta( - const int16_t idx, /* i : quantizer index */ - const float borders[], /* i : level borders */ - const int16_t cbsize /* i : codebook size */ + const int16_t idx, /* i : quantizer index */ + const float borders[], /* i : level borders */ + const float q_step, /* i : quantization step */ + const float q_step_border, /* i : quantization step at the border */ + const int16_t cbsize /* i : codebook size */ ) { int16_t idx_start; float qlow, step, valQ; - if ( idx <= ( borders[1] - borders[0] ) / ISM_Q_STEP_BORDER ) + if ( idx <= ( borders[1] - borders[0] ) / q_step_border ) { qlow = borders[0]; idx_start = 0; - step = ISM_Q_STEP_BORDER; + step = q_step_border; } - else if ( idx <= cbsize - 1 - ( borders[3] - borders[2] ) / ISM_Q_STEP_BORDER ) + else if ( idx <= cbsize - 1 - ( borders[3] - borders[2] ) / q_step_border ) { qlow = borders[1]; - idx_start = (int16_t) ( ( borders[1] - borders[0] ) / ISM_Q_STEP_BORDER ); - step = ISM_Q_STEP; + idx_start = (int16_t) ( ( borders[1] - borders[0] ) / q_step_border ); + step = q_step; } else { qlow = borders[2]; - idx_start = (int16_t) ( cbsize - 1 - ( borders[3] - borders[2] ) / ISM_Q_STEP_BORDER ); - step = ISM_Q_STEP_BORDER; + idx_start = (int16_t) ( cbsize - 1 - ( borders[3] - borders[2] ) / q_step_border ); + step = q_step_border; } valQ = ( idx - idx_start ) * step + qlow; @@ -440,12 +455,22 @@ float ism_dequant_meta( void ivas_param_ism_config( PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: IVAS Param ISM Config Structure */ +#ifdef NCHAN_ISM_PARAMETER + , + const int16_t nchan_obj /* i : number of ISM channels */ +#endif ) { +#ifdef NCHAN_ISM_PARAMETER + int16_t i; + + hParamIsm->nbands = MAX_PARAM_ISM_NBANDS; +#else int16_t i, num_obj; hParamIsm->nbands = MAX_PARAM_ISM_NBANDS; num_obj = hParamIsm->num_obj; +#endif for ( i = 0; i < hParamIsm->nbands; i++ ) { @@ -453,7 +478,11 @@ void ivas_param_ism_config( } /* for elevation zero compute the max azi quantization indices */ +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_obj; i++ ) +#else for ( i = 0; i < num_obj; i++ ) +#endif { hParamIsm->last_az_diff[i] = 0; hParamIsm->last_az_sgn[i] = 1; @@ -490,3 +519,98 @@ ISM_MODE ivas_ism_mode_select( return ism_mode; } + + +/*--------------------------------------------------------------- + * ivas_ism_metadata_close() + * + * Deallocate ISM metadata handles + * ---------------------------------------------------------------*/ + +void ivas_ism_metadata_close( + ISM_METADATA_HANDLE hIsmMetaData[] /* i/o : object metadata handles */ +) +{ + int16_t n; + + if ( hIsmMetaData == NULL || hIsmMetaData == NULL ) + { + return; + } + + for ( n = 0; n < MAX_NUM_OBJECTS; n++ ) + { + if ( hIsmMetaData[n] != NULL ) + { + free( hIsmMetaData[n] ); + hIsmMetaData[n] = NULL; + } + } + + return; +} + + +#ifdef DISCRETE_ISM_DTX_CNG +/*-------------------------------------------------------------------* + * update_last_metadata() + * + * Store last metadata values + *-------------------------------------------------------------------*/ + +void update_last_metadata( + const int16_t nchan_ism, /* i : number of objects */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + const int16_t updt_flag[] /* i : last metadata update flag */ +) +{ + int16_t ch; + + for ( ch = 0; ch < nchan_ism; ch++ ) + { + if ( updt_flag[ch] == 1 ) + { + hIsmMeta[ch]->last_azimuth = hIsmMeta[ch]->azimuth; + hIsmMeta[ch]->last_elevation = hIsmMeta[ch]->elevation; + } + } + + return; +} + + +/*----------------------------------------------------------------* + * ivas_get_ism_sid_quan_bitbudget() + * + * Set quantization bits based on the number of coded objects + *----------------------------------------------------------------*/ + +void ivas_get_ism_sid_quan_bitbudget( + const int16_t nchan_ism, /* i : number of objects */ + int16_t *nBits_azimuth, /* o : number of Q bits for azimuth */ + int16_t *nBits_elevation, /* o : number of Q bits for elevation */ + float *q_step, /* o : quantization step */ + float *q_step_border, /* o : quantization step at the border */ + int16_t *nBits_coh, /* o : number of Q bits for coherence */ + int16_t *nBits_sce_id /* o : number of Q bits for sce_id_dtx */ +) +{ + *nBits_azimuth = ISM_DTX_AZI_BITS_HIGH; + *nBits_elevation = ISM_DTX_ELE_BITS_HIGH; + *q_step = ISM_Q_STEP_HIGH; + *q_step_border = ISM_Q_STEP_BORDER_HIGH; + *nBits_coh = ISM_DTX_COH_SCA_BITS; + *nBits_sce_id = 1; + + if ( nchan_ism >= 3 ) + { + *nBits_azimuth = ISM_DTX_AZI_BITS_LOW; + *nBits_elevation = ISM_DTX_ELE_BITS_LOW; + *q_step = ISM_Q_STEP_LOW; + *q_step_border = ISM_Q_STEP_BORDER_LOW; + *nBits_sce_id = 2; + } + + return; +} +#endif diff --git a/lib_com/ivas_masa_com.c b/lib_com/ivas_masa_com.c index f98dcd8414a94f1b52c4b04337e0d5d4b3321e7b..3a53b2c682446dd6d53e9b05cc8c16e24d7f0fc3 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- * Local constants @@ -302,6 +302,7 @@ void ivas_masa_set_coding_config( return; } + /*--------------------------------------------------------------- * masa_sample_rate_band_correction() * @@ -313,6 +314,10 @@ void masa_sample_rate_band_correction( int16_t *band_mapping, /* i/o: Band mapping used and modified */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: QMetadata structure for modification */ const int32_t sampling_rate /* i : Sampling rate */ +#ifdef FIX_350_MASA_DELAY_COMP + , + MASA_DECODER_EXT_OUT_META_HANDLE hExtOutMeta /* i/o: MASA decoder metadata ext out buffer */ +#endif ) { uint8_t band, sf; @@ -385,6 +390,28 @@ void masa_sample_rate_band_correction( hQMetaData->twoDirBands[band] = 0; } } +#ifdef FIX_350_MASA_DELAY_COMP + if ( hExtOutMeta != NULL ) + { + /* in decoder, zero the EXT out MASA meta buffer */ + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + for ( band = config->numCodingBands; band < MASA_FREQUENCY_BANDS; band++ ) + { + hExtOutMeta->directionIndex[0][sf][band] = SPH_IDX_FRONT; + hExtOutMeta->directToTotalRatio[0][sf][band] = 0u; + hExtOutMeta->spreadCoherence[0][sf][band] = 0u; + + hExtOutMeta->directionIndex[1][sf][band] = SPH_IDX_FRONT; + hExtOutMeta->directToTotalRatio[1][sf][band] = 0u; + hExtOutMeta->spreadCoherence[1][sf][band] = 0u; + + hExtOutMeta->surroundCoherence[sf][band] = 0u; + hExtOutMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX; + } + } + } +#endif return; } diff --git a/lib_com/ivas_mc_com.c b/lib_com/ivas_mc_com.c index a6ee0069ffff3b9b3d68f8dd7ddccf1ff1a5d0ae..027b68768668a713263e85509179d2a48df6ff0a 100644 --- a/lib_com/ivas_mc_com.c +++ b/lib_com/ivas_mc_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- @@ -115,6 +115,7 @@ MC_MODE ivas_mc_mode_select( return mc_mode; } + /*--------------------------------------------------------------- * ivas_mc_setup_get_num_channels() * @@ -154,6 +155,7 @@ int16_t ivas_mc_ls_setup_get_num_channels( return nchan; } + /*--------------------------------------------------------------- * ivas_mc_map_output_config_to_mc_ls_setup() * @@ -193,6 +195,7 @@ MC_LS_SETUP ivas_mc_map_output_config_to_mc_ls_setup( return mc_ls_setup; } + /*--------------------------------------------------------------- * ivas_mc_map_ls_setup_to_output_config * diff --git a/lib_com/ivas_mc_param_com.c b/lib_com/ivas_mc_param_com.c index 3690c1219f84e50bf0db2f074d9aad3d83bfb9ad..acf7a8eae2c97e5a2a5092ad5d970c734f126de7 100644 --- a/lib_com/ivas_mc_param_com.c +++ b/lib_com/ivas_mc_param_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -141,7 +141,6 @@ void ivas_param_mc_metadata_open( ivas_param_mc_default_icc_map( hMetadataPMC->icc_mapping_conf, hMetadataPMC->icc_mapping[i] ); } - /* init remaining flags and indices */ hMetadataPMC->param_frame_idx = 0; hMetadataPMC->flag_use_adaptive_icc_map = 0; @@ -212,13 +211,12 @@ void ivas_param_mc_metadata_close( { uint16_t i; - /* adaptive ICC mapping */ for ( i = 0; i < 2; i++ ) { if ( hMetadataPMC->icc_map_full[i] ) { - count_free( hMetadataPMC->icc_map_full[i] ); + free( hMetadataPMC->icc_map_full[i] ); hMetadataPMC->icc_map_full[i] = NULL; } } @@ -276,7 +274,7 @@ void ivas_param_mc_create_full_icc_mapping( /* allocate memory for the map */ for ( i = 0; i < 2; i++ ) { - icc_map[i] = (int16_t *) count_malloc( *icc_map_size_full * sizeof( int16_t ) ); + icc_map[i] = (int16_t *) malloc( *icc_map_size_full * sizeof( int16_t ) ); } /* create map (non-LFE ICCs) */ @@ -330,6 +328,99 @@ void ivas_param_mc_default_icc_map( } +/*------------------------------------------------------------------------- + * ivas_param_mc_get_num_param_bands() + * + * + *------------------------------------------------------------------------*/ + +static int16_t ivas_param_mc_get_num_param_bands( + const MC_LS_SETUP mc_ls_setup, /* i : MC ls setup */ + const int32_t ivas_total_brate /* i : IVAS total bitrate */ +) +{ + int16_t num_parameter_bands; + + num_parameter_bands = 0; + + /* parameter bands */ + switch ( mc_ls_setup ) + { + case MC_LS_SETUP_5_1: + switch ( ivas_total_brate ) + { + case IVAS_48k: + num_parameter_bands = 10; + break; + case IVAS_64k: + case IVAS_80k: + num_parameter_bands = 14; + break; + default: + assert( 0 && "PARAM_MC: bitrate for CICP6 not supported!" ); + } + break; + + case MC_LS_SETUP_7_1: + switch ( ivas_total_brate ) + { + case IVAS_48k: + num_parameter_bands = 10; + break; + case IVAS_64k: + case IVAS_80k: + num_parameter_bands = 14; + break; + case IVAS_96k: + num_parameter_bands = 20; + break; + } + break; + case MC_LS_SETUP_5_1_2: + switch ( ivas_total_brate ) + { + case IVAS_48k: + num_parameter_bands = 10; + break; + case IVAS_64k: + case IVAS_80k: + num_parameter_bands = 14; + break; + case IVAS_96k: + num_parameter_bands = 20; + break; + } + break; + case MC_LS_SETUP_5_1_4: + switch ( ivas_total_brate ) + { + case IVAS_96k: + num_parameter_bands = 14; + break; + case IVAS_128k: + num_parameter_bands = 20; + break; + } + break; + case MC_LS_SETUP_7_1_4: + switch ( ivas_total_brate ) + { + case IVAS_128k: + num_parameter_bands = 20; + break; + case IVAS_160k: + num_parameter_bands = 20; + break; + } + break; + default: + assert( 0 && "PARAM_MC: channel configuration not supportet!" ); + } + + return num_parameter_bands; +} + + /*------------------------------------------------------------------------- * Local functions *------------------------------------------------------------------------*/ @@ -346,7 +437,6 @@ static void ivas_param_mc_set_coding_scheme( HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC /* i/o: Parametric MC metadata handle */ ) { - /* quantizer and coding tables */ switch ( mc_ls_setup ) { @@ -427,79 +517,7 @@ static void ivas_param_mc_set_coding_scheme( assert( 0 && "PARAM_MC: channel configuration not supported!" ); } - /* parameter bands */ - switch ( mc_ls_setup ) - { - case MC_LS_SETUP_5_1: - switch ( ivas_total_brate ) - { - case IVAS_48k: - hMetadataPMC->num_parameter_bands = 10; - break; - case IVAS_64k: - case IVAS_80k: - hMetadataPMC->num_parameter_bands = 14; - break; - default: - assert( 0 && "PARAM_MC: bitrate for CICP6 not supported!" ); - } - break; - - case MC_LS_SETUP_7_1: - switch ( ivas_total_brate ) - { - case IVAS_48k: - hMetadataPMC->num_parameter_bands = 10; - break; - case IVAS_64k: - case IVAS_80k: - hMetadataPMC->num_parameter_bands = 14; - break; - case IVAS_96k: - hMetadataPMC->num_parameter_bands = 20; - break; - } - break; - case MC_LS_SETUP_5_1_2: - switch ( ivas_total_brate ) - { - case IVAS_48k: - hMetadataPMC->num_parameter_bands = 10; - break; - case IVAS_64k: - case IVAS_80k: - hMetadataPMC->num_parameter_bands = 14; - break; - case IVAS_96k: - hMetadataPMC->num_parameter_bands = 20; - break; - } - break; - case MC_LS_SETUP_5_1_4: - switch ( ivas_total_brate ) - { - case IVAS_96k: - hMetadataPMC->num_parameter_bands = 14; - break; - case IVAS_128k: - hMetadataPMC->num_parameter_bands = 20; - break; - } - break; - case MC_LS_SETUP_7_1_4: - switch ( ivas_total_brate ) - { - case IVAS_128k: - hMetadataPMC->num_parameter_bands = 20; - break; - case IVAS_160k: - hMetadataPMC->num_parameter_bands = 20; - break; - } - break; - default: - assert( 0 && "PARAM_MC: channel configuration not supportet!" ); - } + hMetadataPMC->num_parameter_bands = ivas_param_mc_get_num_param_bands( mc_ls_setup, ivas_total_brate ); return; } diff --git a/lib_com/ivas_mcmasa_com.c b/lib_com/ivas_mcmasa_com.c index 2441cf7973792d920a5b72a94ecf98317ba1356f..1b7db4ff01a7c1426c65eb74c0cba4ab76cc8eaa 100644 --- a/lib_com/ivas_mcmasa_com.c +++ b/lib_com/ivas_mcmasa_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* @@ -65,6 +65,7 @@ void ivas_mcmasa_setNumTransportChannels( return; } + /*--------------------------------------------------------------------------* * ivas_mcmasa_set_separate_channel_mode() * @@ -91,24 +92,41 @@ void ivas_mcmasa_set_separate_channel_mode( return; } + /*--------------------------------------------------------------------------* - * ivas_mcmasa_mono_brate() + * ivas_mcmasa_split_brate() * - * Set SCE bitrate for McMASA mono separated channel + * Split the total bitrate to elements in McMASA *--------------------------------------------------------------------------*/ -/*! r: McMASA SCE bitrate */ -int32_t ivas_mcmasa_mono_brate( - const int32_t ivas_total_brate /* i : IVAS total bitrate */ +void ivas_mcmasa_split_brate( + const uint8_t separateChannelEnabled, /* i : Transport running in "separate channel" mode */ + const int32_t ivas_total_brate, /* i : Total bitrate available to be split */ + const int16_t nSCE, /* i : Number of SCEs in use (0 or 1) */ + const int16_t nCPE, /* i : Number of CPEs in use (0 or 1) */ + int32_t *brate_sce, /* o : Pointer to SCE element bitrate */ + int32_t *brate_cpe /* o : Pointer to CPE element bitrate */ ) { - /* 25% of total bitrate is used for SCE below 96 kb/s (separated mono channel), otherwise 30% */ - if ( ivas_total_brate < IVAS_96k ) + if ( separateChannelEnabled ) { - return ( const int32_t )( MCMASA_MONOBITRATIO_64k * ivas_total_brate ); + /* 25% of total bitrate is used for SCE below 96 kb/s (separated mono channel), otherwise 30% */ + if ( ivas_total_brate < IVAS_96k ) + { + *brate_sce = (int32_t) ( MCMASA_MONOBITRATIO_64k * ivas_total_brate ); + } + else + { + *brate_sce = (int32_t) ( MCMASA_MONOBITRATIO * ivas_total_brate ); + } + + *brate_cpe = ivas_total_brate - *brate_sce; } else { - return ( const int32_t )( MCMASA_MONOBITRATIO * ivas_total_brate ); + *brate_sce = nSCE > 0 ? ivas_total_brate / ( nCPE + nSCE ) : 0; + *brate_cpe = nCPE > 0 ? ivas_total_brate / ( nCPE + nSCE ) : 0; } + + return; } diff --git a/lib_com/ivas_mct_com.c b/lib_com/ivas_mct_com.c index 97d7636a036a2fcbd4d912d50aefcfceb953b10b..5a6eafed5be5d31471155dbc1311509a506c7a51 100644 --- a/lib_com/ivas_mct_com.c +++ b/lib_com/ivas_mct_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,7 @@ #include "ivas_cnst.h" #include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include @@ -66,11 +66,13 @@ void splitAvailableBitsMCT( int16_t min_chan_bits[MCT_MAX_CHANNELS], min_bits_tot, remaining_bits; int16_t core[MCT_MAX_CHANNELS]; MCT_CHAN_MODE mct_chan_mode[MCT_MAX_CHANNELS]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE int16_t num_lfe; int16_t lfe_channel; num_lfe = 0; lfe_channel = -1; +#endif min_bits_tot = 0; for ( i = 0; i < nchan; i++ ) @@ -85,19 +87,23 @@ void splitAvailableBitsMCT( mct_chan_mode[i] = ( (Decoder_State *) sts[i] )->mct_chan_mode; core[i] = ( (Decoder_State *) sts[i] )->core; } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( mct_chan_mode[i] == MCT_CHAN_MODE_LFE ) { num_lfe++; lfe_channel = i; assert( lfe_channel == LFE_CHANNEL ); } +#endif } - for ( i = 0; i < nchan; i++ ) { - if ( mct_chan_mode[i] != MCT_CHAN_MODE_LFE && mct_chan_mode[i] != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + mct_chan_mode[i] != MCT_CHAN_MODE_LFE && +#endif + mct_chan_mode[i] != MCT_CHAN_MODE_IGNORE ) { min_chan_bits[i] = 0; @@ -129,7 +135,11 @@ void splitAvailableBitsMCT( bits_frame_channel = &( (Decoder_State *) sts[i] )->bits_frame_channel; } - if ( mct_chan_mode[i] != MCT_CHAN_MODE_LFE && mct_chan_mode[i] != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + mct_chan_mode[i] != MCT_CHAN_MODE_LFE && +#endif + mct_chan_mode[i] != MCT_CHAN_MODE_IGNORE ) { assert( split_ratio[i] >= 1 && split_ratio[i] < BITRATE_MCT_RATIO_RANGE ); *bits_frame_channel = split_ratio[i] * remaining_bits / BITRATE_MCT_RATIO_RANGE + min_chan_bits[i]; @@ -163,7 +173,11 @@ void splitAvailableBitsMCT( bits_frame_channel = &( (Decoder_State *) sts[i] )->bits_frame_channel; } - if ( mct_chan_mode[i] != MCT_CHAN_MODE_LFE && mct_chan_mode[i] != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + mct_chan_mode[i] != MCT_CHAN_MODE_LFE && +#endif + mct_chan_mode[i] != MCT_CHAN_MODE_IGNORE ) { *bits_frame_channel -= diff * split_ratio[i] / BITRATE_MCT_RATIO_RANGE; *bits_frame_channel = max( min_chan_bits[i], *bits_frame_channel ); diff --git a/lib_com/ivas_mdct_core_com.c b/lib_com/ivas_mdct_core_com.c index fd80b2d0547f92ebaec5ef7e06dca424ef405c24..afb5303a7aa82c774655b53c89546ef91656433a 100644 --- a/lib_com/ivas_mdct_core_com.c +++ b/lib_com/ivas_mdct_core_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,7 @@ #include "ivas_cnst.h" #include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * ivas_mdct_tcx10_bit_distribution() diff --git a/lib_com/ivas_mdct_imdct.c b/lib_com/ivas_mdct_imdct.c index cc343410c2ea38a833bd2d1e8598d78f58544ac6..5580973ed02eba244e3d2050d1e403598e34dc7c 100644 --- a/lib_com/ivas_mdct_imdct.c +++ b/lib_com/ivas_mdct_imdct.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,19 +38,20 @@ #include "debug.h" #endif #include "ivas_stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* * Local constants *------------------------------------------------------------------------------------------*/ + #define IVAS_IMDCT_SCALING_GAIN 2115.165304808f /*-----------------------------------------------------------------------------------------* * Function ivas_tda() * - * Time domain alias implementation + * Time domain aliasing *-----------------------------------------------------------------------------------------*/ void ivas_tda( @@ -67,6 +68,8 @@ void ivas_tda( pOut[i] = -pIn[len_by_2 - i - 1] + pIn[len_by_2 + i]; pOut[len_by_2 + i] = pIn[length * 2 - i - 1] + pIn[length + i]; } + + return; } @@ -134,11 +137,12 @@ void ivas_mdct( const int16_t length ) { const float *pTwid_re, *pTwid_im; - int16_t len_by_2 = length >> 1; - float re[IVAS_480_PT_LEN]; - float im[IVAS_480_PT_LEN]; - float ivas_mdct_scaling_gain = ivas_get_mdct_scaling_gain( len_by_2 ); - int16_t i; + int16_t i, len_by_2; + float re[IVAS_480_PT_LEN], im[IVAS_480_PT_LEN]; + float ivas_mdct_scaling_gain; + + len_by_2 = length >> 1; + ivas_mdct_scaling_gain = ivas_get_mdct_scaling_gain( len_by_2 ); ivas_get_twid_factors( length, &pTwid_re, &pTwid_im ); diff --git a/lib_com/ivas_mdft_imdft.c b/lib_com/ivas_mdft_imdft.c index ddabf624f4b571ef48e4dfa1a5986174353a4575..e6f276575e1bc9672abd30b6be0c414e2bd9498d 100644 --- a/lib_com/ivas_mdft_imdft.c +++ b/lib_com/ivas_mdft_imdft.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,19 @@ #endif #include "ivas_rom_com.h" #include -#include "wmops.h" +#include "wmc_auto.h" + + +/*-----------------------------------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------------------------------*/ + +#define IVAS_ONE_BY_960 0.001041666666666666f +#define IVAS_ONE_BY_640 0.0015625f +#define IVAS_ONE_BY_320 0.003125f +#define IVAS_ONE_BY_240 0.004166666666666667f +#define IVAS_ONE_BY_160 0.00625f +#define IVAS_ONE_BY_80 0.0125f /*-----------------------------------------------------------------------------------------* @@ -50,38 +62,31 @@ static void ivas_get_mdft_twid_factors( const int16_t length, - const float **ppTwid_re, - const float **ppTwid_im ) + const float **ppTwid ) { switch ( length ) { case L_FRAME48k: - *ppTwid_re = &ivas_mdft_coeff_cos_twid_960[0]; - *ppTwid_im = &ivas_mdft_coeff_sin_twid_960[0]; + *ppTwid = &ivas_mdft_coeff_cos_twid_960[0]; break; case L_FRAME32k: - *ppTwid_re = &ivas_mdft_coeff_cos_twid_640[0]; - *ppTwid_im = &ivas_mdft_coeff_sin_twid_640[0]; + *ppTwid = &ivas_mdft_coeff_cos_twid_640[0]; + break; case L_FRAME16k: - *ppTwid_re = &ivas_mdft_coeff_cos_twid_320[0]; - *ppTwid_im = &ivas_mdft_coeff_sin_twid_320[0]; + *ppTwid = &ivas_mdft_coeff_cos_twid_320[0]; break; case IVAS_240_PT_LEN: - *ppTwid_re = &ivas_mdft_coeff_cos_twid_240[0]; - *ppTwid_im = &ivas_mdft_coeff_sin_twid_240[0]; + *ppTwid = &ivas_mdft_coeff_cos_twid_240[0]; break; case IVAS_160_PT_LEN: - *ppTwid_re = &ivas_mdft_coeff_cos_twid_160[0]; - *ppTwid_im = &ivas_mdft_coeff_sin_twid_160[0]; + *ppTwid = &ivas_mdft_coeff_cos_twid_160[0]; break; case IVAS_80_PT_LEN: - *ppTwid_re = &ivas_mdft_coeff_cos_twid_80[0]; - *ppTwid_im = &ivas_mdft_coeff_sin_twid_80[0]; + *ppTwid = &ivas_mdft_coeff_cos_twid_80[0]; break; case IVAS_40_PT_LEN: - *ppTwid_re = &ivas_mdft_coeff_cos_twid_40[0]; - *ppTwid_im = &ivas_mdft_coeff_sin_twid_40[0]; + *ppTwid = &ivas_mdft_coeff_cos_twid_40[0]; break; default: @@ -222,26 +227,26 @@ void ivas_mdft( float re[L_FRAME48k]; float im[L_FRAME48k]; int16_t j, len_by_2; - const float *pTwid_re, *pTwid_im; - + const float *pTwid; len_by_2 = mdft_length >> 1; - ivas_get_mdft_twid_factors( mdft_length, &pTwid_re, &pTwid_im ); + ivas_get_mdft_twid_factors( mdft_length, + &pTwid ); if ( mdft_length == input_length ) { for ( j = 0; j < mdft_length; j++ ) { - re[j] = pIn[j] * pTwid_re[j]; - im[j] = -pIn[j] * pTwid_im[j]; + re[j] = pIn[j] * pTwid[j]; + im[j] = -pIn[j] * pTwid[mdft_length - j]; } } else { for ( j = 0; j < mdft_length; j++ ) { - re[j] = pIn[j] * pTwid_re[j] - pIn[j + mdft_length] * pTwid_im[j]; - im[j] = -pIn[j] * pTwid_im[j] - pIn[j + mdft_length] * pTwid_re[j]; + re[j] = pIn[j] * pTwid[j] - pIn[j + mdft_length] * pTwid[mdft_length - j]; + im[j] = -pIn[j] * pTwid[mdft_length - j] - pIn[j + mdft_length] * pTwid[j]; } } diff --git a/lib_com/ivas_pca_tools.c b/lib_com/ivas_pca_tools.c index ba6fdfea7c31aa505bd40e7f66225d19d91b9d5e..63285dabb10afe8a6a03c277d0ae8343a223caf8 100644 --- a/lib_com/ivas_pca_tools.c +++ b/lib_com/ivas_pca_tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include #include #include "ivas_rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" @@ -119,7 +119,7 @@ void cov_subfr( static void house_refl( - float *px, + const float *px, const int16_t sizex, float *pu, float *normu ) @@ -136,11 +136,11 @@ static void house_refl( } else { - float _rcp = 1.f / ( *normu ); + float rcp = 1.f / ( *normu ); for ( i = 0; i < sizex; i++ ) { - pu[i] *= _rcp; + pu[i] *= rcp; } if ( pu[0] >= 0.f ) { @@ -152,11 +152,11 @@ static void house_refl( pu[0] -= 1; } - _rcp = 1.f / sqrtf( fabsf( pu[0] ) ); + rcp = inv_sqrt( fabsf( pu[0] ) ); for ( i = 0; i < sizex; i++ ) { - pu[i] *= _rcp; + pu[i] *= rcp; } } @@ -254,8 +254,9 @@ static void house_qr( * * Compute eigenvalue decomposition by QR method *---------------------------------------------------------------------*/ + void eig_qr( - float *A, + const float *A, const int16_t num_iter, float *EV, float *Vals, @@ -389,6 +390,7 @@ void exhst_4x4( * * Convert 4D matrix -> double quaternion *---------------------------------------------------------------------*/ + void mat2dquat( const float *a, float *ql, @@ -481,6 +483,7 @@ void mat2dquat( * * Convert double quaternion -> 4D matrix *---------------------------------------------------------------------*/ + void dquat2mat( const float *ql, const float *qr, @@ -543,6 +546,7 @@ void dquat2mat( * * Shortest path verification (prior to quaternion interpolation) *---------------------------------------------------------------------*/ + void quat_shortestpath( const float *q00, float *q01, @@ -600,7 +604,8 @@ void quat_shortestpath( * Compute determinant of 4D matrix - brute-force version *---------------------------------------------------------------------*/ -float mat_det4( float *m ) +float mat_det4( + const float *m ) { float d; @@ -635,17 +640,14 @@ float mat_det4( float *m ) static void norm_quat( float *q ) { - float norm_q = 0.0f; + float norm_q; int16_t i; - for ( i = 0; i < 4; i++ ) - { - norm_q += q[i] * q[i]; - } + norm_q = dotp( q, q, IVAS_PCA_INTERP ); - norm_q = 1 / sqrtf( norm_q ); + norm_q = inv_sqrt( norm_q ); // VE: TBV: possible division by 0 - for ( i = 0; i < 4; i++ ) + for ( i = 0; i < IVAS_PCA_INTERP; i++ ) { q[i] *= norm_q; } @@ -662,7 +664,7 @@ static void quat_nlerp_preproc( { int16_t i; - for ( i = 0; i < 4; i++ ) + for ( i = 0; i < IVAS_PCA_INTERP; i++ ) { q_slerp[i] = alpha * q0[i] + ( 1.0f - alpha ) * q1[i]; } @@ -703,14 +705,8 @@ static float acos_clip( { float ph; - if ( v > 1.0 ) - { - v = 1.0; - } - if ( v < -1.0 ) - { - v = -1.0; - } + v = check_bounds( v, -1.0f, 1.0f ); + ph = acosf( v ); return ph; @@ -835,7 +831,7 @@ static void q_ang_2surv( static void q_ang_circ( - float a, + const float a, const int16_t N, float *a_q, int16_t *index ) @@ -881,11 +877,12 @@ static void q_ang_circ( static int16_t sel_q( const float *q, - float *q_cand, + const float *q_cand, const int16_t n ) { int16_t i, i_min, j; - float d, d_min, *p, temp; + float d, d_min, temp; + const float *p; i_min = -1; d_min = 1e30f; diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 2c4b0e5ec0763e91b563c0efae666058b4545063..54f39d2763b9556e10022877767478c3a0e299f8 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,6 @@ #include "ivas_stat_com.h" #include "ivas_error_utils.h" - /* clang-format off */ /*----------------------------------------------------------------------------------* @@ -106,7 +105,12 @@ ivas_error mct_enc_reconfigure( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const uint16_t b_nchan_change /* i : flag indicating different channel count */ ); - +ivas_error ivas_spar_md_enc_init +( + ivas_spar_md_enc_state_t *hMdEnc, /* o : MD encoder handle */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ +); ivas_error ivas_sba_enc_reconfigure( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); @@ -119,6 +123,20 @@ void destroy_cpe_enc( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ); +void ivas_mct_enc_close( + MCT_ENC_HANDLE *hMCT /* i/o: MCT encoder structure */ +); + +ivas_error ivas_corecoder_enc_reconfig( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const int16_t nSCE_old, /* i : number of SCEs in previous frame */ + const int16_t nCPE_old, /* i : number of CPEs in previous frame */ + const int16_t nchan_transport_old, /* i : number of TCs in previous frame */ + const int32_t brate_SCE, /* i : bitrate to be set for the SCEs */ + const int32_t brate_CPE, /* i : bitrate to be set for the CPEs */ + const MC_MODE last_mc_mode /* i : switching between MC modes: last mode */ +); + ivas_error ivas_sce_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const int16_t sce_id, /* i : SCE # identifier */ @@ -152,7 +170,6 @@ ivas_error pre_proc_front_ivas( const int16_t n, /* i : channel number */ float old_inp_12k8[], /* o : buffer of old input signal */ float old_inp_16k[], /* o : buffer of old input signal @16kHz */ - float *Etot, /* o : total energy */ float *ener, /* o : residual energy from Levinson-Durbin */ float *relE, /* o : frame relative energy */ float A[NB_SUBFR16k * ( M + 1 )], /* o : A(z) unquantized for the 4 subframes */ @@ -161,7 +178,7 @@ ivas_error pre_proc_front_ivas( float lsp_new[M], /* o : LSPs at the end of the frame */ float lsp_mid[M], /* o : LSPs in the middle of the frame */ int16_t *vad_hover_flag, /* o : VAD hangover flag */ - int16_t *attack_flag, /* o : flag signalling attack */ + int16_t *attack_flag, /* o : flag signaling attack */ float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: real buffer */ float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: imag buffer */ float old_wsp[], /* o : weighted input signal buffer */ @@ -182,15 +199,17 @@ ivas_error pre_proc_front_ivas( const int16_t localVAD_HE_SAD_LR[CPE_CHANNELS], /* i : HE-SAD flag without hangover, LR channels */ float band_energies_LR[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN */ const int16_t flag_16k_smc, /* i : flag to indicate if the OL SMC is run at 16 kHz */ - const int16_t spar_front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ - const int16_t spar_force_front_vad, /* i : flag to force VAD decision */ - const int16_t spar_front_vad_dtx_flag /* i : front-VAD DTX flag to overwrite VAD decision*/ + const int16_t front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ + const int16_t force_front_vad, /* i : flag to force VAD decision */ + const int16_t front_vad_dtx_flag, /* i : front-VAD DTX flag to overwrite VAD decision*/ + const int32_t ivas_total_brate /* i : IVAS total bitrate */ ); ivas_error pre_proc_ivas( Encoder_State *st, /* i/o: encoder state structure */ const int16_t last_element_mode, /* i : last element mode */ const int32_t element_brate, /* i : element bitrate */ + const int32_t last_element_brate, /* i : last element bitrate */ const int16_t input_frame, /* i : frame length */ float old_inp_12k8[], /* i/o: buffer of old input signal */ float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ @@ -209,7 +228,7 @@ ivas_error pre_proc_ivas( const int16_t vad_flag_dtx, /* i : HE-SAD flag with additional DTX HO */ const float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ const float fft_buff[2 * L_FFT], /* i : FFT buffer */ - const int16_t is_mct, /* i : MCT mode flag */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int16_t vad_hover_flag, /* i : VAD hangover flag */ const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ ); @@ -238,6 +257,10 @@ uint32_t ivas_syn_output( int16_t *synth_out /* o : integer 16 bits synthesis signal */ ); +void ivas_initialize_handles_enc( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +); + ivas_error ivas_init_encoder( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ Indice ind_list[][MAX_NUM_INDICES], /* i : indices list */ @@ -266,7 +289,7 @@ ivas_error stereo_dmx_evs_init_encoder( ); void stereo_dmx_evs_close_encoder( - STEREO_DMX_EVS_ENC_HANDLE hStereoDmxEVS /* i/o: Stereo downmix for EVS encoder handle */ + STEREO_DMX_EVS_ENC_HANDLE *hStereoDmxEVS /* i/o: Stereo downmix for EVS encoder handle */ ); ivas_error ivas_dec( @@ -311,6 +334,21 @@ void ivas_mct_dec_close( MCT_DEC_HANDLE *hMCT /* i/o: MCT decoder structure */ ); +ivas_error ivas_corecoder_dec_reconfig( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nSCE_old, /* i : number of SCEs in previous frame */ + int16_t nCPE_old, /* i : number of CPEs in previous frame */ + const int16_t nchan_transport_old, /* i : number of TCs in previous frame */ + const int16_t sba_dirac_stereo_flag_old, /* i : signal stereo rendering using DFT upmix in previous frame */ + const int32_t brate_SCE, /* i : bitrate to be set for the SCEs */ + const int32_t brate_CPE /* i : bitrate to be set for the CPEs */ +); + +ivas_error ivas_hp20_dec_reconfig( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nchan_hp20_old /* i : number of HP20 filters in previous frame*/ +); + ivas_error ivas_sce_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t sce_id, /* i : SCE # identifier */ @@ -363,7 +401,6 @@ ivas_error ivas_core_enc( const int16_t n_CoreChannels, /* i : number of core channels to be coded */ float old_inp_12k8[CPE_CHANNELS][L_INP_12k8], /* i : buffer of old input signal */ float old_inp_16k[CPE_CHANNELS][L_INP], /* i : buffer of old input signal */ - const float Etot[CPE_CHANNELS], /* i : total energy */ float ener[CPE_CHANNELS], /* i : residual energy from Levinson-Durbin */ float A[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )], /* i : A(z) unquantized for the 4 subframes */ float Aw[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )], /* i : weighted A(z) unquantized for subframes */ @@ -381,6 +418,7 @@ ivas_error ivas_core_enc( float enerBuffer[CPE_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ float fft_buff[CPE_CHANNELS][2 * L_FFT], /* i : FFT buffer */ const int16_t tdm_SM_flag, /* i : channel combination scheme flag */ + const int16_t ivas_format, /* i : IVAS format */ const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ ); @@ -461,12 +499,16 @@ void stereo_tcx_core_dec( const int16_t last_element_mode, /* i : last element mode */ const int16_t flag_sec_CNA, /* i : CNA flag for secondary channel */ STEREO_CNG_DEC_HANDLE hStereoCng, /* i : Stereo CNG handle */ - const int16_t nchan_out /* i : number of output channels */ + const int16_t nchan_out, /* i : number of output channels */ + const IVAS_FORMAT ivas_format /* i : IVAS format */ +#ifndef DISCRETE_ISM_DTX_CNG + ,const ISM_MODE ism_mode /* i : ISM mode (only needed if format is ISM) */ +#endif ); void stereo_tcx_init_dec( Decoder_State *st, /* i/o: decoder state structure */ - const int16_t is_mct, /* i : MCT mode flag */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int16_t last_element_mode /* i : element mode of previous frame */ ); @@ -521,9 +563,9 @@ void ivas_decision_matrix_enc( const int16_t last_element_mode /* i : last element mode */ ); -void ivas_signalling_enc( +void ivas_signaling_enc( Encoder_State *st, /* i/o: encoder state structure */ - const int16_t is_MCT, /* i : MCT enabled */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int32_t element_brate, /* i : element bitrate */ const int16_t tdm_SM_flag, /* i : channel combination scheme flag in TD stereo */ const int16_t tdm_Pitch_reuse_flag /* i : primary channel pitch reuse flag in TD stereo*/ @@ -570,6 +612,13 @@ void set_transient_stereo( float currFlatness[] /* i/o: current flatness */ ); +/*! r: preliminary flag to force ACELP */ +int16_t transient_analysis( + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + const float cor_map_LT[], /* i : LT correlation map */ + const float multi_harm_limit /* i : multi harminic threshold */ +); + void ivas_post_proc( SCE_DEC_HANDLE hSCE, /* i/o: SCE decoder structure */ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ @@ -614,33 +663,6 @@ MC_LS_SETUP ivas_mc_map_output_config_to_mc_ls_setup( const AUDIO_CONFIG output_config /* i : output audio configuration */ ); -/*! r: limiter struct handle */ -IVAS_LIMITER_HANDLE ivas_limiter_open( - const int16_t num_channels, /* i : number of I/O channels */ - const int32_t sampling_rate /* i : sampling rate for processing */ -); - -void ivas_limiter_close( - IVAS_LIMITER_HANDLE* phLimiter /* i/o: pointer to limiter handle, can be NULL */ -); - -void ivas_limiter_dec -( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], /* i/o: input/output buffer */ - const int16_t num_channels, /* i : number of channels to be processed */ - const int16_t output_frame, /* i : number of samples per channel in the buffer */ - const int16_t BER_detect /* i : BER detect flag */ -); - -void limiter_process( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - const int16_t output_frame, /* i : number of samples to be processed per channel in the I/O buffer */ - const float threshold, /* i : signal amplitude above which limiting starts to be applied */ - const int16_t BER_detect, /* i : BER detect flag */ - int16_t *strong_saturation_cnt /* i/o: counter of strong saturations (can be NULL) */ -); - void smooth_dft2td_transition( CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ float output[CPE_CHANNELS][L_FRAME48k], /* i/o: synthesis @external Fs */ @@ -684,15 +706,48 @@ void ivas_imdft( const int16_t length /* i : signal length */ ); +void TonalMdctConceal_create_concealment_noise( + float concealment_noise[L_FRAME48k], + CPE_DEC_HANDLE hCPE, + const int16_t L_frameTCX, + const int16_t L_frame, + const int16_t idchan, + const int16_t subframe_idx, + const int16_t core, + const float crossfade_gain, + const TONALMDCTCONC_NOISE_GEN_MODE noise_gen_mode +); + +void TonalMdctConceal_whiten_noise_shape( + Decoder_State *st, + const int16_t L_frame, + const TONALMDCTCONC_NOISE_SHAPE_WHITENING_MODE +); + +/*! r: IGF start line */ +int16_t get_igf_startline( + Decoder_State *st, /* i : decoder state */ + const int16_t L_frame, /* i : length of the frame */ + const int16_t L_frameTCX /* i : full band frame length */ +); + +float rand_triangular_signed( + int16_t *seed ); + +void dtx_read_padding_bits( + DEC_CORE_HANDLE st, + const int16_t num_bits +); + /*----------------------------------------------------------------------------------* - * ISm prototypes + * ISM prototypes *----------------------------------------------------------------------------------*/ ivas_error ivas_ism_config( - const int32_t ism_total_brate, /* i : ISms total bitrate */ - const int16_t num_trans_ch, /* i : number of trans channels */ - const int16_t num_obj, /* i : number of objects */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t nchan_ism, /* i : number of objects */ ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ const int16_t localVAD[MAX_NUM_OBJECTS], /* i : local VAD flag */ const int16_t ism_imp[], /* i : ISM importance flags */ @@ -714,6 +769,8 @@ int16_t ism_quant_meta( const float val, /* i : scalar value to quantize */ float *valQ, /* o : quantized value */ const float borders[], /* i : level borders */ + const float q_step, /* i : quantization step */ + const float q_step_border, /* i : quantization step at the border */ const int16_t cbsize /* i : codebook size */ ); @@ -721,22 +778,27 @@ int16_t ism_quant_meta( float ism_dequant_meta( const int16_t idx, /* i : quantizer index */ const float borders[], /* i : level borders */ + const float q_step, /* i : quantization step */ + const float q_step_border, /* i : quantization step at the border */ const int16_t cbsize /* i : codebook size */ ); -ivas_error set_ism_metadata( - ISM_METADATA_HANDLE hIsmMeta, /* i/o: ISM metadata handle */ - float azimuth, /* i : azimuth */ - float elevation /* i : elevation */ +ivas_error ivas_set_ism_metadata( + ISM_METADATA_HANDLE hIsmMeta, /* o : ISM metadata handle */ + const float azimuth, /* i : azimuth value */ + const float elevation, /* i : elevation value */ + const float radius_meta, /* i : radius */ + const float yaw, /* i : yaw */ + const float pitch /* i : pitch */ ); -ivas_error create_ism_metadata_enc( +ivas_error ivas_ism_metadata_enc_create( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const int16_t n_ISms, /* i : number of objects */ int32_t element_brate_tmp[] /* o : element bitrate per object */ ); -ivas_error create_ism_metadata_dec( +ivas_error ivas_ism_metadata_dec_create( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t n_ISms, /* i : number of objects */ int32_t element_brate_tmp[] /* o : element bitrate per object */ @@ -750,7 +812,10 @@ ivas_error ivas_ism_enc( ); ivas_error ivas_ism_metadata_enc( - const int32_t ism_total_brate, /* i : ISms total bitrate */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ +#ifdef NCHAN_ISM_PARAMETER + const int16_t nchan_ism, /* i : number of ISM channels */ +#endif const int16_t nchan_transport, /* i : number of transport channels */ ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */ @@ -758,18 +823,31 @@ ivas_error ivas_ism_metadata_enc( int16_t nb_bits_metadata[], /* o : number of metadata bits */ const int16_t localVAD[], /* i : VAD flag */ const int16_t ism_mode, /* i : ISM mode */ - const PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Config Handle */ + const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Config Handle */ + const int16_t ism_extended_metadata_flag /* i : Extended metadata flag */ ); ivas_error ivas_ism_metadata_dec( - const int32_t ism_total_brate, /* i : ISms total bitrate */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ +#ifdef NCHAN_ISM_PARAMETER + const int16_t nchan_ism, /* i : number of ISM channels */ +#endif int16_t *nchan_transport, /* o : number of transport channels */ ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ SCE_DEC_HANDLE hSCE[], /* i/o: SCE decoder handles */ const int16_t bfi, /* i : bfi flag */ - int16_t nb_bits_metadata[], /* o : number of metadata bits */ + int16_t nb_bits_metadata[], /* o : number of metadata bits */ ISM_MODE ism_mode, /* i : ISM mode */ +#ifdef DISCRETE_ISM_DTX_CNG + ISM_DTX_DATA_DEC hISMDTX, /* i/o: ISM DTX structure */ +#endif +#ifdef FIX_379_EXT_METADATA + const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Config Handle */ + int16_t *ism_extended_metadata_flag, /* i/o: Extended metadata active in renderer */ + int16_t *ism_extmeta_cnt /* i/o: Number of change frames observed */ +#else const PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Config Handle */ +#endif ); @@ -794,8 +872,12 @@ void ivas_param_ism_enc( ); void ivas_param_ism_enc_close( - DIRAC_ENC_HANDLE hDirAC /* i/o: encoder DirAC handle */ - ,const int32_t input_Fs /* i : input sampling_rate */ + DIRAC_ENC_HANDLE *hDirAC, /* i/o: encoder DirAC handle */ + const int32_t input_Fs /* i : input sampling_rate */ +); + +void ivas_ism_metadata_close( + ISM_METADATA_HANDLE hIsmMetaData[] /* i/o : object metadata handles */ ); void ivas_param_ism_stereo_dmx( @@ -806,6 +888,10 @@ void ivas_param_ism_stereo_dmx( void ivas_param_ism_config( PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: IVAS Param ISM Config Structure */ +#ifdef NCHAN_ISM_PARAMETER + , + const int16_t nchan_ism /* i : number of ISM channels */ +#endif ); ivas_error ivas_ism_enc_config( @@ -813,8 +899,14 @@ ivas_error ivas_ism_enc_config( ); ivas_error ivas_ism_dec_config( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const int16_t num_obj /* i : number of objects in the bitstream */ + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +#ifdef DISCRETE_ISM_DTX_CNG + , + const ISM_MODE last_ism_mode /* i/o: last ISM mode */ +#endif +#ifndef NCHAN_ISM_PARAMETER + ,const int16_t num_obj /* i : number of objects in the bitstream */ +#endif ); ivas_error ivas_param_ism_dec_open( @@ -822,7 +914,7 @@ ivas_error ivas_param_ism_dec_open( ); void ivas_param_ism_dec_close( - DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + DIRAC_DEC_HANDLE *hDirAC, /* i/o: decoder DirAC handle */ const AUDIO_CONFIG output_config /* i : output audio configuration */ ); @@ -835,6 +927,122 @@ void ivas_param_ism_params_to_masa_param_mapping( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); + +/*----------------------------------------------------------------------------------* + * ISM DTX prototypes + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_ism_dtx_open( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +); + +#ifdef DISCRETE_ISM_DTX_CNG +/*! r: indication of DTX frame */ +int16_t ivas_ism_dtx_enc( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + SCE_ENC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t nchan_transport, /* i : number of transport channels */ + int16_t vad_flag[MAX_NUM_OBJECTS], /* i : VAD flag */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + int16_t md_diff_flag[], /* o : metadata differential flag */ + int16_t *sid_flag /* o : indication of SID frame */ +); +#else +/*! r: indication of DTX frame */ +int16_t ivas_ism_dtx_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + int16_t *sid_flag /* o : indication of SID frame */ +); +#endif + +ivas_error ivas_ism_dtx_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int16_t *nb_bits_metadata /* o : number of metadata bits */ +); + +#ifdef DISCRETE_ISM_DTX_CNG +void ivas_ism_metadata_sid_enc( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + const int16_t flag_noisy_speech, /* i : noisy speech flag */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t nchan_transport, /* i : number of transport channels */ + const ISM_MODE ism_mode, /* i : ISM mode */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + const int16_t sid_flag, /* i : indication of SID frame */ + const int16_t md_diff_flag[], /* i : metadata differental flag */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + int16_t nb_bits_metadata[] /* o : number of metadata bits */ +); +#else +void ivas_param_ism_metadata_dtx_enc( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i : ISM metadata handles */ + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Enc Handle */ +#ifdef NCHAN_ISM_PARAMETER + ,const int16_t nchan_ism /* i : number of ISM channels */ +#endif +); +#endif + +#ifdef DISCRETE_ISM_DTX_CNG +void ivas_ism_metadata_sid_dec( + SCE_DEC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int32_t ism_total_brate, /* i : ISms total bitrate */ + const int16_t bfi, /* i : bfi flag */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t nchan_transport, /* i : number of transport channels */ + const ISM_MODE ism_mode, /* i : ISM mode */ + int16_t *flag_noisy_speech, /* o : noisy speech flag */ + int16_t *sce_id_dtx, /* o : SCE DTX ID */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + int16_t nb_bits_metadata[] /* o : number of metadata bits */ +); +#else +void ivas_param_ism_metadata_dtx_dec( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); +#endif + +void ivas_ism_get_sce_id_dtx( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + SCE_ENC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t input_frame /* i : input frame length per channel */ +); + +void ivas_param_ism_compute_noisy_speech_flag( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +); + +void ivas_ism_coh_estim_dtx_enc( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + SCE_ENC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t input_frame /* i : input frame length */ +); + +#ifdef DISCRETE_ISM_DTX_CNG +void update_last_metadata( + const int16_t nchan_ism, /* i : number of objects */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + const int16_t updt_flag[] /* i : last metadata update flag */ +); + +void ivas_get_ism_sid_quan_bitbudget( + const int16_t nchan_ism, /* i : number of objects */ + int16_t *nBits_azimuth, /* o : number of Q bits for azimuth */ + int16_t *nBits_elevation, /* o : number of Q bits for elevation */ + float *q_step, /* o : quantization step */ + float *q_step_border, /* o : quantization step at the border */ + int16_t *nBits_coh, /* o : number of Q bits for coherence */ + int16_t *nBits_sce_id /* o : number of Q bits for sce_id_dtx */ +); +#endif + + /*----------------------------------------------------------------------------------* * DFT Stereo prototypes *----------------------------------------------------------------------------------*/ @@ -856,10 +1064,6 @@ void stereo_enc_itd_init( void stereo_dft_enc_update( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ const int16_t max_bwidth /* i : maximum encoded bandwidth */ -#ifdef DEBUG_MODE_DFT - , - const int16_t res_code_bits /* i : bits for residual coding */ -#endif ); void stereo_dft_enc_destroy( @@ -887,6 +1091,8 @@ float stereo_dft_enc_synthesize( void stereo_dft_enc_process( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const int16_t vad_flag_dtx[], /* i: VAD dtx flags */ + const int16_t vad_hover_flag[], /* i: VAD hangover flags */ const int16_t input_frame /* i : input frame length */ ); @@ -935,7 +1141,7 @@ void stereo_dft_dequantize_itd( void stereo_dft_enc_sid_calc_coh( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ - float coh_crossfade[STEREO_DFT_BAND_MAX / 2], /* i/o: Coherence crossfade memory */ + float prev_cohBand[2*(STEREO_DFT_BAND_MAX/2)], /* i/o: Previous coherence */ int16_t *td_active, /* i/o: TD stereo mode indicator */ int16_t *first_SID, /* i/o: First SID indicator */ float *cohBand /* i/o: Coherence per band */ @@ -960,7 +1166,8 @@ ivas_error stereo_dft_dec_create( STEREO_DFT_DEC_DATA_HANDLE *hStereoDft, /* i/o: decoder DFT stereo handle */ const int32_t element_brate, /* i : element bitrate */ const int32_t output_Fs, /* i : output sampling rate */ - const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ + const int16_t sba_dirac_stereo_flag, /* i : signal stereo output for SBA DirAC */ + const int16_t nchan_transport /* i : number of transport channels */ ); void stereo_dft_dec_reset( @@ -984,7 +1191,7 @@ void stereo_dft_dec_analyze( const int16_t chan, /* i : channel number */ const int16_t input_frame, /* i : input frame size */ const int16_t output_frame, /* i : output frame size */ - const DFT_STEREO_DEC_ANA_TYPE ana_type, /* i : signal type to analyze */ + const DFT_STEREO_DEC_ANA_TYPE ana_type, /* i : signal type to analyze */ const int16_t k_offset, /* i : offset of DFT */ const int16_t delay /* i : delay in samples for input signal */ ); @@ -1003,7 +1210,14 @@ void stereo_dft_dec( float DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */ float *input_mem, /* i/o: mem of buffer DFT analysis */ STEREO_CNG_DEC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ - const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ + const int16_t sba_dirac_stereo_flag, /* i : signal stereo output for SBA DirAC */ +#ifdef SBA2MONO + const int16_t sba_mono_flag, /* i : signal mono output for SBA DirAC */ +#endif + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD handle for upmixing */ + const int16_t cross_fade_start_offset, /* i : SPAR mixer delay compensation */ + const int32_t output_Fs, /* i : Fs for delay calculation */ + const int16_t nchan_transport /* i : number of transpor channels */ ); void stereo_dft_res_ecu( @@ -1044,9 +1258,9 @@ void stereo_dft_res_ecu_burst_att( /*! r: total energy of downmix with maximum swb bandwidth max */ float stereo_dft_dmx_swb_nrg( - const float *dmx_k0, /* i : first subframe spectrum */ - const float *dmx_k1, /* i : second subframe spectrum */ - const int16_t frame_length /* i : frame lanegth */ + const float *dmx_k0, /* i : first subframe spectrum */ + const float *dmx_k1, /* i : second subframe spectrum */ + const int16_t frame_length /* i : frame lanegth */ ); int16_t stereo_dft_sg_recovery( @@ -1067,8 +1281,8 @@ int16_t res_bpf_adapt( ); void bpf_pitch_coherence( - Decoder_State *st, /* i/o: decoder state structure */ - const float pitch_buf[] /* i : pitch for each subframe [0,1,2,3] */ + Decoder_State *st, /* i/o: decoder state structure */ + const float pitch_buf[] /* i : pitch for each subframe [0,1,2,3] */ ); void stereo_dft_dec_read_BS( @@ -1087,7 +1301,9 @@ void stereo_dft_dec_read_BS( void stereo_dft_dec_smooth_parameters( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */ - const int16_t prev_sid_nodata /* i : Previous SID/No data indicator */ + const int16_t prev_sid_nodata, /* i : Previous SID/No data indicator */ + const int16_t active_frame_counter, /* i : Active frame counter */ + const int32_t element_brate /* i : Element bitrate */ ); void stereo_dft_generate_res_pred( @@ -1243,6 +1459,8 @@ void stereo_dft_enc_compute_itd( float *DFT_R, const int16_t k_offset, const int16_t input_frame, + const int16_t vad_flag_dtx[], + const int16_t vad_hover_flag[], float *bin_nrgL, float *bin_nrgR ); @@ -1580,10 +1798,11 @@ ivas_error stereo_set_tdm( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const int16_t input_frame /* i : input frame length per channel */ ); + void stereo_tdm_prep_dwnmx ( - CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ - const float *input1, /* i : right channel input */ - const int16_t input_frame /* i : frame lenght */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const float *input1, /* i : right channel input */ + const int16_t input_frame /* i : frame lenght */ ); int16_t stereo_tdm_ener_analysis( CPE_ENC_HANDLE hCPE, /* i : CPE structure */ @@ -1658,6 +1877,7 @@ void tdm_ol_pitch_comparison( void tdm_configure_enc( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const float Etot_last[CPE_CHANNELS], /* i/o: Energy of last frame */ const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ const int16_t tdm_ratio_idx, /* i : ratio index */ const int16_t tdm_ratio_idx_SM, /* i : ratio index in SM mode */ @@ -1665,7 +1885,7 @@ void tdm_configure_enc( const int16_t nb_bits_metadata /* i : number of metadata bits */ ); -ivas_error signalling_enc_secondary( +ivas_error signaling_enc_secondary( Encoder_State *st, /* i/o: Encoder structure */ const int16_t tdm_SM_flag, /* i : channel combination scheme flag */ const int16_t tdm_Pitch_reuse_flag /* i : primary channel pitch reuse flag */ @@ -1797,6 +2017,8 @@ void deindex_lvq_SHB( void stereo_td_itd_mdct_stereo( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ + const int16_t vad_flag_dtx[], /* i: VAD dtx flags */ + const int16_t vad_hover_flag[], /* i: VAD hangover flags */ const int16_t input_frame /* i : frame length */ ); @@ -1834,7 +2056,7 @@ void EstimateStereoTCXNoiseLevel( const int16_t ignore_chan[], /* i : flag indicating whether the channel should be ignored */ float fac_ns[][NB_DIV], /* o : noise filling level */ int16_t param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */ - const int16_t is_mct /* i : is mct flag */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); void TNSAnalysisStereo( @@ -1844,7 +2066,7 @@ void TNSAnalysisStereo( int16_t tnsSize[MCT_MAX_CHANNELS][NB_DIV], /* i : number of tns parameters put into prm */ int16_t tnsBits[MCT_MAX_CHANNELS][NB_DIV], /* i : number of tns bits in the frame */ int16_t param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */ - const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ + const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ ); void InternalTCXDecoder( @@ -1945,17 +2167,12 @@ void decoder_tcx_invQ( const int16_t **prm_sqQ, int16_t *nf_seed, const int16_t bfi, /* i : Bad frame indicator */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t isMCT, -#endif const int16_t frame_cnt /* i : frame counter in the super frame */ ); void decoder_tcx_noisefilling( Decoder_State *st, /* i/o: coder memory state */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT float concealment_noise[L_FRAME48k], -#endif const float A[], /* i : coefficients NxAz[M+1] */ const int16_t L_frameTCX_glob, const int16_t L_spec, @@ -1968,9 +2185,7 @@ void decoder_tcx_noisefilling( const int16_t *prm_sqQ, int16_t nf_seed, const int16_t bfi, /* i : Bad frame indicator */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t isMCT, -#endif + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int16_t frame_cnt /* i : frame counter in the super frame */ ); @@ -2012,13 +2227,15 @@ void decoder_tcx_imdct( const int16_t left_rect, float x[N_MAX], float xn_buf[], - const uint16_t kernelType, /* i : TCX transform kernel type */ + const uint16_t kernelType, /* i : TCX transform kernel type */ const int16_t fUseTns, /* i : flag that is set if TNS data is present */ float synth[], /* i/o: synth[-M..L_frame] */ float synthFB[], const int16_t bfi, /* i : Bad frame indicator */ const int16_t frame_cnt, /* i : frame counter in the super frame */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE const int16_t isLFE, /* i : is LFE */ +#endif const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ ); @@ -2053,7 +2270,8 @@ void decoder_tcx_IGF_stereo( const int16_t L_frame, /* i : frame length */ const int16_t left_rect, /* i : left part is rectangular */ const int16_t k, /* i : Subframe index */ - const int16_t bfi /* i : bad frame indicator */ + const int16_t bfi, /* i : bad frame indicator */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); void ms_processing( @@ -2086,7 +2304,8 @@ void IGFDecApplyStereo( const int16_t igfGridIdx, /* i : in case of CELP->TCX switching, use 1.25 framelength */ const int16_t *coreMsMask, const int16_t restrict_hopsize, - const int16_t bfi /* i : frame loss == 1, frame good == 0 */ + const int16_t bfi, /* i : frame loss == 1, frame good == 0 */ + const int16_t bfi_apply_damping /* i : decoder element mode */ ); void IGFEncStereoEncoder( @@ -2124,7 +2343,7 @@ void stereo_coder_tcx( float *mdst_spectrum[CPE_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ float *inv_spectrum[CPE_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ float *inv_mdst_spectrum[CPE_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ - const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ + const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ ); void stereo_decoder_tcx( @@ -2137,10 +2356,11 @@ void stereo_decoder_tcx( const int16_t core_l, /* i : core for left channel (TCX20/TCX10) */ const int16_t core_r, /* i : core for right channel (TCX20/TCX10) */ const int16_t igf, /* i : flag for IGF activity */ - const int16_t L_frame, /* i : TCX frame length */ - const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ - const int16_t last_core_l, /* i : last core for left channel */ - const int16_t last_core_r, /* i : last core for right channel */ + const int16_t L_frameTCX_l, /* i : TCX frame length of left channel */ + const int16_t L_frameTCX_r, /* i : TCX frame length of right channel */ + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t last_core_l, /* i : last core for left channel */ + const int16_t last_core_r, /* i : last core for right channel */ const int16_t tmp_plc_upmix /* i : indicates temp upmix for PLC decision */ ); @@ -2152,10 +2372,11 @@ void stereo_mdct_core_dec( ); void splitAvailableBits( - const int16_t total_bits, /* i : total available bits for TCX coding */ - const int16_t split_ratio, /* i : split ratio */ - int16_t *bits_ch0, /* o : bits for channel 0 */ - int16_t *bits_ch1 /* o : bits for channel 1 */ + const int16_t total_bits, /* i : total available bits for TCX coding */ + const int16_t split_ratio, /* i : split ratio */ + const int16_t isSBAStereoMode, /* i : signal core coding for SBA */ + int16_t *bits_ch0, /* o : bits for channel 0 */ + int16_t *bits_ch1 /* o : bits for channel 1 */ ); int16_t write_stereo_to_bitstream @@ -2163,14 +2384,15 @@ int16_t write_stereo_to_bitstream STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: Stereo MDCT encoder structure */ Encoder_State **sts, /* i/o: Encoder state structure */ int16_t ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ - const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ BSTR_ENC_HANDLE hBstr /* i/o: bitstream handle */ ); void parse_stereo_from_bitstream( STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo decoder structure */ Decoder_State **sts, /* i/o: decoder state structure */ - const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t isSBAStereoMode, /* i : flag core coding for SBA */ Decoder_State *st0, /* i/o: decoder state structure for Bstr */ int16_t ms_mask[NB_DIV][MAX_SFB] /* o : bandwise MS mask */ ); @@ -2323,7 +2545,7 @@ ivas_error front_vad( Encoder_State *st, /* i/o: encoder state structure */ const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ FRONT_VAD_ENC_HANDLE *hFrontVads, /* i/o: front-VAD handles */ - const int16_t hMCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int16_t input_frame, /* i : frame length */ int16_t vad_flag_dtx[], /* o : HE-SAD flag with additional DTX HO */ float fr_bands[][2 * NB_BANDS], /* i : energy in frequency bands */ @@ -2357,7 +2579,8 @@ void stereo_cng_upd_counters( const int32_t element_mode, /* i : element mode */ const int16_t nbands, /* i : Number of bands in active */ const float sidSideGain[], /* i : SID side gains */ - const int16_t burst_ho_count /* i : Hang-over count */ + const int16_t burst_ho_count, /* i : Hang-over count */ + int16_t *coh_fade_counter /* i : Coherence fade counter */ ); void stereo_cng_init_dec( @@ -2486,14 +2709,16 @@ float lin_interp( const int16_t flag_sat /* i : flag to indicate whether to apply saturation */ ); -void check_bounds( - float *value, /* i/o: Input value / Adjusted value */ +/*! r: Adjusted value */ +float check_bounds( + const float value, /* i : Input value */ const float low, /* i : Low limit */ const float high /* i : High limit */ ); -void check_bounds_s( - int16_t *value, /* i/o: Input value / Adjusted value */ +/*! r: Adjusted value */ +int16_t check_bounds_s( + const int16_t value, /* i : Input value */ const int16_t low, /* i : Low limit */ const int16_t high /* i : High limit */ ); @@ -2503,7 +2728,9 @@ ivas_error stereo_memory_enc( const int32_t input_Fs, /* i : input sampling rate */ const int16_t max_bwidth, /* i : maximum audio bandwidth */ float *tdm_last_ratio, /* o : TD stereo last ratio */ - const IVAS_FORMAT ivas_format /* i : IVAS format */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const int16_t nchan_transport /* i : number transport chans */ + ); ivas_error stereo_memory_dec( @@ -2512,6 +2739,7 @@ ivas_error stereo_memory_dec( const int16_t nb_bits_metadata, /* i : number of metadata bits */ const int32_t output_Fs, /* i : output sampling rate */ const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const MC_MODE mc_mode, /* i : MC mode */ const int16_t nchan_transport /* i : number of transport channels */ ); @@ -2562,140 +2790,148 @@ int16_t read_GR0( *----------------------------------------------------------------------------------*/ void ivas_mdct_core_whitening_enc( - CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ - float old_wsp[CPE_CHANNELS][L_WSP], /* i : 12.8kHz weighted speech (for LTP */ - float pitch_buf[CPE_CHANNELS][NB_SUBFR16k], /* o : floating pitch for each subframe */ - float *mdst_spectrum_long[CPE_CHANNELS], /* o : buffer for MDST spectrum */ - int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* o : buffer TNS bits */ - float *orig_spectrum_long[CPE_CHANNELS], /* o : origingal spectrum w/o whitening */ - int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* o : size of TNS */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to parameter array */ - BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ - int16_t *LFE_off, /* o : flag if LFE has content */ - const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ - const int16_t nChannels /* i : total number of coded channels */ + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ + float old_wsp[CPE_CHANNELS][L_WSP], /* i : 12.8kHz weighted speech (for LTP */ + float pitch_buf[CPE_CHANNELS][NB_SUBFR16k], /* o : floating pitch for each subframe */ + float *mdst_spectrum_long[CPE_CHANNELS], /* o : buffer for MDST spectrum */ + int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* o : buffer TNS bits */ + float *orig_spectrum_long[CPE_CHANNELS], /* o : origingal spectrum w/o whitening */ + int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* o : size of TNS */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to parameter array */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + int16_t *LFE_off, /* o : flag if LFE has content */ +#endif + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t nChannels /* i : total number of coded channels */ ); void ivas_mct_core_enc( - const IVAS_FORMAT ivas_format, /* i : IVAS format */ - MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ - CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */ - const int16_t nChannels, /* i : number of channels to be coded */ - const int32_t ivas_total_brate, /* i : IVAS total bitrate */ - const int16_t switch_bw, /* i : flag bandwidth switch occurance */ - const int16_t lfe_bits, /* i : bits spent for LFE */ - const SBA_MODE sba_mode /* i : SBA mode */ -#ifdef FIX_I1_113 - , - const int16_t sba_order -#endif + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */ + const int16_t nChannels, /* i : number of channels to be coded */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t switch_bw, /* i : flag bandwidth switch occurance */ + const int16_t lfe_bits, /* i : bits spent for LFE */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ); void ivas_mdct_quant_coder( - CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ - const int16_t LFE_off, /* i : flag if LFE has content */ - int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ - int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ - const int16_t is_mct /* i : is mct flag */ + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE has content */ +#endif + int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); void apply_MCT_enc( - MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ - Encoder_State **sts, /* i/o: encoder state structure */ - float *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ - float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ - float *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ - const int16_t nchan /* i : number of channels */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ + float *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ + float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ + float *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ + const int16_t nchan /* i : number of channels */ ); void write_mct_bitstream( - Encoder_State **sts, /* i/o: encoder state structure */ - MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ - const int16_t nchan /* i : number of channels */ + Encoder_State **sts, /* i/o: encoder state structure */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + const int16_t nchan /* i : number of channels */ ); void splitAvailableBitsMCT( - void **sts, /* i/o: encoder/decoder state structure */ - const int16_t total_bits, /* i : total number of available bits */ - const int16_t split_ratio[MCT_MAX_CHANNELS], /* i : ratio for splitting the bits */ - const int16_t enc_dec, /* i : encoder or decoder flag */ - const int16_t nchan /* i : number of channels */ + void **sts, /* i/o: encoder/decoder state structure */ + const int16_t total_bits, /* i : total number of available bits */ + const int16_t split_ratio[MCT_MAX_CHANNELS], /* i : ratio for splitting the bits */ + const int16_t enc_dec, /* i : encoder or decoder flag */ + const int16_t nchan /* i : number of channels */ ); void getChannelEnergies( - Encoder_State **sts, /* i : Encoder state structure */ - float nrg[MCT_MAX_CHANNELS], /* o : energies */ - const int16_t nchan /* i : number of channels */ + Encoder_State **sts, /* i : Encoder state structure */ + float nrg[MCT_MAX_CHANNELS], /* o : energies */ + const int16_t nchan /* i : number of channels */ ); void mctStereoIGF_enc( - MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ - Encoder_State **sts, /* i/o: encoder state structure */ - float *orig_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : MDCT spectrum for ITF */ - float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ - float *powerSpecMsInv[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ - float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ - const int16_t sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ + float *orig_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : MDCT spectrum for ITF */ + float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate */ + float *powerSpecMsInv[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect. */ + float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ + const int16_t sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ ); void ivas_mdct_dec_side_bits_frame_channel( - CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ - int16_t param_lpc[MCT_MAX_CHANNELS][NPRM_LPC_NEW], /* o : lpc_parameters */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to param buffer */ - Decoder_State *st0, /* i : pointer to bitstream handle */ - int16_t *LFE_off, /* o : flag if LFE has content */ - int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* o : number of bits for TNS */ - int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i/o: parameters buffer */ - const int16_t MCT_flag, /* i : MCT tool active(1) or deactive (0) */ - const int16_t odd_channel_cpe /* i : flag cpe with odd nb of tc channels */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ + int16_t param_lpc[MCT_MAX_CHANNELS][NPRM_LPC_NEW], /* o : lpc_parameters */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to param buffer */ + Decoder_State *st0, /* i : pointer to bitstream handle */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + int16_t *LFE_off, /* o : flag if LFE has content */ +#endif + int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* o : number of bits for TNS */ + int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i/o: parameters buffer */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t odd_channel_cpe /* i : flag cpe with odd nb of tc channels */ ); void ivas_mct_side_bits( - MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ - CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE decoder structure */ - const int16_t nCPE, /* i : number of CPEs */ - Decoder_State *st0, /* i : decoder handle for Bstr */ - const int16_t bfi, /* i : BFI flag */ - uint16_t *bitstream, /* o : bitstream indices */ - const int32_t ivas_total_brate, /* i : IVAS total bitrate */ - const int16_t nb_bits_metadata /* i : number of metadata bits */ + MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ + CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE decoder structure */ + const int16_t nCPE, /* i : number of CPEs */ + Decoder_State *st0, /* i : decoder handle for Bstr */ + const int16_t bfi, /* i : BFI flag */ + uint16_t *bitstream, /* o : bitstream indices */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nb_bits_metadata /* i : number of metadata bits */ ); void ivas_mdct_core_invQ( - CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ - const int16_t LFE_off, /* i : flag if LFE content */ - int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* i : number of TNS bits */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to param buffer */ - int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW], /* i : lpc parameters */ - int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i : param buffer */ - int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flag TNS enabled */ - STnsData tnsData[CPE_CHANNELS][NB_DIV], /* i : TNS parameter */ - float *x_0[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ - float *x[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ - float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* i : LP coefficients */ - int16_t ms_mask[NB_DIV][MAX_SFB], /* i : M/S mask */ - const int16_t isMCT /* i : MCT flag */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE content */ +#endif + int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* i : number of TNS bits */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to param buffer */ + int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW], /* i : lpc parameters */ + int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i : param buffer */ + int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flag TNS enabled */ + STnsData tnsData[CPE_CHANNELS][NB_DIV], /* i : TNS parameter */ + float *x_0[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ + float *x[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ + float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* i : LP coefficients */ + int16_t ms_mask[NB_DIV][MAX_SFB], /* i : M/S mask */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); void ivas_mdct_core_reconstruct( - CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ - float *x[][NB_DIV], /* i/o: pointers to synthesis @internal_FS */ - float signal_outFB[CPE_CHANNELS][L_FRAME_PLUS], /* o : synthesis @output_FS */ - const int16_t LFE_off, /* i : flag if LFE content */ - int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flage TNS enabled */ - const int16_t isMCT /* i : MCT flag */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ + float *x[][NB_DIV], /* i/o: pointers to synthesis @internal_FS */ + float signal_outFB[CPE_CHANNELS][L_FRAME_PLUS], /* o : synthesis @output_FS */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE content */ +#endif + int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flage TNS enabled */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); void ivas_mdct_core_tns_ns( - CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ - const int16_t LFE_off, /* i : flag if LFE has content */ - int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : two entries for each channel in TCX10*/ - STnsData tnsData[CPE_CHANNELS][NB_DIV], /* o : TNS parameter */ - float *x[CPE_CHANNELS][NB_DIV], /* o : synthesis @internal_FS */ - float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* o : LP coefficients */ - const int16_t isMCT /* i : MCT flag */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE has content */ +#endif + int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : two entries for each channel in TCX10 */ + STnsData tnsData[CPE_CHANNELS][NB_DIV], /* o : TNS parameter */ + float *x[CPE_CHANNELS][NB_DIV], /* o : synthesis @internal_FS */ + float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* o : LP coefficients */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); void ivas_mct_core_dec( @@ -2724,10 +2960,6 @@ void mctStereoIGF_dec( const int16_t bfi /* i : bad frame flag */ ); -void ivas_mct_enc_close( - MCT_ENC_HANDLE hMCT /* i/o: MCT encoder structure */ -); - void ivas_mdct_tcx10_bit_distribution( int16_t target_bitsTCX10[NB_DIV], /* o : target bit distribution */ const int16_t bits_frame_channel, /* i : bits frame channel */ @@ -2761,8 +2993,7 @@ void reset_metadata_spatial( int32_t *total_brate, /* o : total bitrate */ const int32_t core_brate, /* i : core bitrate */ const int16_t nb_bits_metadata, /* i : number of meatdata bits */ - const SBA_MODE sba_mode, /* i : SBA mode */ - const int16_t element_mode /* i : element mode */ + const SBA_MODE sba_mode /* i : SBA mode */ ); /*! r: number of bits written */ @@ -2897,7 +3128,7 @@ int16_t quantize_phi_chan_compand( float phi, /* i : azimuth value */ float *phi_hat, /* o : quantized azimuth */ const int16_t n, /* i : azimuth codebook size */ - const int16_t theta_flag, /* i : flag signalling high elevation */ + const int16_t theta_flag, /* i : flag signaling high elevation */ const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ ); @@ -2961,7 +3192,7 @@ uint16_t ivas_qmetadata_reorder_generic( ); int16_t ivas_qmetadata_dereorder_generic( - const uint16_t uns_value /* i : unsigned value to reorder */ + const uint16_t uns_value /* i : unsigned value to reorder */ ); /*! r: projected azimuth index */ @@ -2992,16 +3223,20 @@ void ivas_dirac_param_est_enc( float data_f[][L_FRAME48k], float **pp_fr_real, float **pp_fr_imag, - const int16_t input_frame + const int16_t input_frame, + const SBA_MODE sba_mode ); + /*----------------------------------------------------------------------------------* - * SBA mode prototypes + * SBA format prototypes *----------------------------------------------------------------------------------*/ /*! r: SBA format mode */ -int16_t ivas_sba_mode_select( +SBA_MODE ivas_sba_mode_select( +#ifndef LBR_SBA const int32_t ivas_total_brate /* i : IVAS total bitrate */ +#endif ); void ivas_sba_config( @@ -3012,9 +3247,14 @@ void ivas_sba_config( const int16_t sba_planar, /* i : SBA planar flag */ int16_t *nSCE, /* o : number of SCEs */ int16_t *nCPE, /* o : number of CPEs */ - int16_t *element_mode, /* o : element mode of the core coder */ - const SBA_MODE sba_mode /* i : SBA mode */ + int16_t *element_mode /* o : element mode of the core coder */ +); + +#ifdef FIX_386_CORECODER_RECONFIG +void ivas_sba_set_cna_cng_flag( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); +#endif ivas_error ivas_sba_dec_reconfigure( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ @@ -3026,15 +3266,26 @@ void ivas_init_dec_get_num_cldfb_instances( int16_t *numCldfbSyntheses /* o : number of CLDFB synthesis instances */ ); +ivas_error ivas_cldfb_dec_reconfig( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nchan_transport_old, /* i : number of TCs in previous frame */ + int16_t numCldfbAnalyses_old, /* i : number of CLDFB analysis instances in previous frame */ + const int16_t numCldfbSyntheses_old /* i : number of CLDFB synthesis instances in previous frame */ +); + +/*! r: Ambisonic (SBA) order */ int16_t ivas_sba_get_order( const int16_t nb_channels, /* i : Number of ambisonic channels */ const int16_t sba_planar /* i : SBA planar flag */ ); -int16_t ivas_sba_get_order_transport( - const int16_t nchan_transport /* i : Number of transport channels */ +/*! r: Ambisonic (SBA) order used for analysis and coding */ +int16_t ivas_sba_get_analysis_order( + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ); +/*! r: number of Ambisonic channels */ int16_t ivas_sba_get_nchan( const int16_t sba_order, /* i : Ambisonic (SBA) order */ const int16_t sba_planar /* i : SBA planar flag */ @@ -3045,6 +3296,12 @@ int16_t ivas_sba_get_nchan_metadata( const int16_t sba_order /* i : Ambisonic (SBA) order */ ); +/*! r: flag indicating to code SPAR HOA MD for all bands */ +int16_t ivas_sba_get_spar_hoa_md_flag( + const int16_t sba_order, /* i : Ambisonic (SBA) order */ + const int32_t ivas_total_brate /* i : IVAS total bitrate */ +); + void ivas_sba_zero_vert_comp( float sba_data[][L_FRAME48k], /* i/o: SBA data frame */ const int16_t sba_order, /* i : Ambisonic (SBA) order */ @@ -3058,15 +3315,6 @@ void ivas_sba_getTCs( const int16_t input_frame /* i : frame length */ ); -ivas_error ivas_sba_linear_renderer( - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ - const int16_t output_frame, /* i : output frame length per channel */ - const int16_t nchan_in, /* i : number of input ambisonics channels */ - const AUDIO_CONFIG output_config, /* i : output audio configuration */ - const IVAS_OUTPUT_SETUP output_setup, /* i : output format setup */ - const float hoa_dec_mtx[] /* i : hoa decoding mtx */ -); - int16_t ivas_sba_remapTCs( float sba_data[][L_FRAME48k], /* i/o: SBA signals */ Decoder_Struct *st_ivas, /* i/o: decoder struct */ @@ -3076,23 +3324,37 @@ int16_t ivas_sba_remapTCs( void ivas_sba_dirac_stereo_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ float output[CPE_CHANNELS][L_FRAME48k], /* o : output synthesis signal */ - const int16_t output_frame /* i : output frame length per channel */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t mcmasa /* i : McMASA flag */ ); void ivas_sba_dirac_stereo_config( STEREO_DFT_CONFIG_DATA_HANDLE hConfig /* o : DFT stereo configuration */ ); +#ifdef SBA2MONO +int16_t ivas_get_sba_dirac_stereo_flag( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); +#endif + void ivas_sba_dirac_stereo_smooth_parameters( - STEREO_DFT_DEC_DATA_HANDLE hStereoDft /* i/o: encoder DFT stereo handle */ + STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD handle for upmixing */ + const int16_t cross_fade_start_offset, /* i : SPAR mixer delay compensation */ + const int32_t output_Fs /* i : Fs for delay calculation */ ); -ivas_error ivas_sba_get_hoa_dec_matrix( - const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ - float **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ - const int16_t ambisonics_order /* i : Ambisonics order */ +void ivas_sba2mc_cldfb( + IVAS_OUTPUT_SETUP hInSetup, /* i : Format of input layout */ + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb real part */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb imag part */ + const int16_t nb_channels_out, /* i : nb of output channels */ + const int16_t nb_bands, /* i : nb of CLDFB bands to process */ + const float *hoa_dec_mtx /* i : HOA decoding mtx */ ); + /*----------------------------------------------------------------------------------* * DirAC prototypes *----------------------------------------------------------------------------------*/ @@ -3106,19 +3368,19 @@ ivas_error ivas_dirac_enc_reconfigure( ); void ivas_dirac_enc_close( - DIRAC_ENC_HANDLE hDirAC, /* i/o: encoder DirAC handle */ + DIRAC_ENC_HANDLE *hDirAC, /* i/o: encoder DirAC handle */ const int32_t input_Fs /* i : input sampling_rate */ ); void ivas_dirac_enc( - DIRAC_ENC_HANDLE hDirAC, /* i/o: encoder DirAC handle */ - IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ - BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */ - int16_t *nb_bits_metadata, /* o : number of metadata bits written */ - const int16_t Opt_DTX_ON, /* i : flag signalling DTX on */ - float data_f[][L_FRAME48k], /* i/o: input: ACN/SN3D, output: omni, stereo DMX or FOA */ - const int16_t input_frame, /* i : input frame length */ - const int16_t sba_planar /* i : SBA planar flag */ + DIRAC_ENC_HANDLE hDirAC, /* i/o: encoder DirAC handle */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ + BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */ + int16_t *nb_bits_metadata, /* o : number of metadata bits written */ + const int16_t Opt_DTX_ON, /* i : flag signaling DTX on */ + float data_f[][L_FRAME48k], /* i/o: SBA channels */ + const int16_t input_frame, /* i : input frame length */ + const int16_t sba_planar /* i : SBA planar flag */ ); ivas_error ivas_dirac_config( @@ -3144,18 +3406,10 @@ ivas_error ivas_dirac_sba_config( int16_t *element_mode, /* o : element mode of the core coder */ int32_t sba_total_brate, /* i : SBA total bitrate */ const int16_t sba_order, /* i : Ambisonic (SBA) order */ - const int16_t sba_planar, /* i : SBA planar flag */ const SBA_MODE sba_mode, /* i : SBA mode */ const int16_t nbands /* i : number of frequency bands */ ); -/*! r: number of IVAS transport channels */ -int16_t ivas_dirac_getNumTransportChannels( - const int32_t sba_total_brate, /* i : SBA total bitrate */ - const int16_t sba_order, /* i : SBA order */ - const int16_t sba_planar /* i : SBA Planar flag */ -); - ivas_error ivas_dirac_dec_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); @@ -3166,7 +3420,7 @@ ivas_error ivas_dirac_dec_config( ); void ivas_dirac_dec_close( - DIRAC_DEC_HANDLE hDirAC /* i/o: decoder DirAC handle */ + DIRAC_DEC_HANDLE *hDirAC /* i/o: decoder DirAC handle */ ); void ivas_dirac_dec_read_BS( @@ -3189,49 +3443,8 @@ void ivas_dirac_dec( ); ivas_error ivas_dirac_dec_init_binaural_data( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -); - -void ivas_dirac_dec_close_binaural_data( - DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle */ -); - -void ivas_dirac_dec_binaural( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ - const int16_t nchan_transport /* i : number of transport channels */ -); - -ivas_error ivas_binaural_reverb_open( - REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ - const int16_t numBins, /* i : number of CLDFB bins */ - const int16_t numCldfbSlotsPerFrame /* i : number of CLDFB slots per frame, i.e., reverberator block size */ -); - -void ivas_binaural_reverb_close( - REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */ -); - -void ivas_binaural_reverb_setReverbTimes( - REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ - const int32_t output_Fs, /* i : sampling_rate */ - const float *revTimes, /* i : reverberation times T60 for each CLDFB bin in seconds */ - const float *revEnes /* i : spectrum for reverberated sound at each CLDFB bin */ -); - -void ivas_binaural_reverb_setPreDelay( - REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ - const int16_t delaySamples /* i : reverb pre-delay in CLDFB slots */ -); - -void ivas_binaural_reverb_processFrame( - REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ - const int16_t numInChannels, /* i : num input channels to be processed */ - float inReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real */ - float inImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ - float outReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ - float outImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data imag */ - const uint8_t offsetSamplesIO /* i : number of offset samples */ + HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ ); void computeDiffuseness_mdft( @@ -3260,7 +3473,7 @@ void computeDiffuseness( float *diffuseness ); -void ivas_dirac_dec_onset_detection_open( +ivas_error ivas_dirac_dec_onset_detection_open( const int16_t num_channels, const int16_t num_freq_bands, const int16_t max_band_decorr, @@ -3276,7 +3489,7 @@ void ivas_dirac_dec_onset_detection_process( DIRAC_ONSET_DETECTION_STATE h_dirac_onset_detection_state ); -void ivas_dirac_dec_decorr_open( +ivas_error ivas_dirac_dec_decorr_open( DIRAC_DECORR_PARAMS **ph_freq_domain_decorr_ap_params, DIRAC_DECORR_STATE **ph_freq_domain_decorr_ap_state, const int16_t num_freq_bands, @@ -3309,7 +3522,7 @@ void ivas_dirac_dec_decorr_close( ); -void ivas_dirac_dec_output_synthesis_open( +ivas_error ivas_dirac_dec_output_synthesis_open( DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const RENDERER_TYPE renderer_type, /* i : renderer type */ const int16_t nchan_transport, /* i : number of transport channels */ @@ -3332,24 +3545,26 @@ void ivas_dirac_dec_output_synthesis_process_slot( const float *p_Rmat, /* i : rotation matrix */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t index_slot + const int16_t nchan_transport /* i : number of transport channels */ +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES + , const int16_t index_slot +#endif ); void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const int16_t nchan_transport, /* i : number of transport channels */ const float *onset_filter ); void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ - float *reference_power_smooth - , float qualityBasedSmFactor + float *reference_power_smooth, + float qualityBasedSmFactor ); void ivas_dirac_dec_get_response( @@ -3386,8 +3601,10 @@ void ivas_dirac_dec_compute_directional_responses( DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES const int16_t direction_idx, /* i : index for direction (azi and ele) */ const int16_t subframe_idx, /* i : subframe index */ +#endif const float *surCohRatio, const int16_t shd_rot_max_order, /* i : split-order rotation method */ const float *p_Rmat /* i : rotation matrix */ @@ -3430,8 +3647,12 @@ ivas_error ivas_param_mc_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); +ivas_error ivas_param_mc_enc_reconfig( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +); + void ivas_param_mc_enc_close( - PARAM_MC_ENC_HANDLE hParamMC, /* i/o: Parametric MC encoder handle */ + PARAM_MC_ENC_HANDLE *hParamMC, /* i/o: Parametric MC encoder handle */ const int32_t input_Fs /* i : input sampling rate */ ); @@ -3446,7 +3667,11 @@ ivas_error ivas_param_mc_dec_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); -void ivas_param_mc_dec_close( +ivas_error ivas_param_mc_dec_reconfig( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +void ivas_param_mc_dec_close( PARAM_MC_DEC_HANDLE *hParamMC /* i/o: Parametric MC decoder handle */ ); @@ -3578,7 +3803,7 @@ int16_t svd( const int16_t nChannelsC /* i : number of columns in the matrix to be decomposed */ ); -void ivas_dirac_dec_output_synthesis_cov_open( +ivas_error ivas_dirac_dec_output_synthesis_cov_open( DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */ DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state, /* i/o: handle for the covariance synthesis state */ const int16_t max_band_decorr, /* i : uppermost frequency band where decorrelation is applied */ @@ -3657,12 +3882,14 @@ void FdCngDecodeDiracMDCTStereoSID( ivas_error ivas_spar_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ + ,const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ); void ivas_spar_enc_close( - SPAR_ENC_HANDLE hSpar, /* i/o: SPAR encoder handle */ + SPAR_ENC_HANDLE *hSpar, /* i/o: SPAR encoder handle */ const int32_t input_Fs, /* i : input sampling rate */ - const int16_t nchan_inp /* i : number of input channels */ + const int16_t nchan_inp, /* i : number of input channels */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ); ivas_error ivas_spar_enc( @@ -3674,12 +3901,14 @@ ivas_error ivas_spar_enc( ); ivas_error ivas_spar_dec_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ); void ivas_spar_dec_close( - SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ - const int32_t output_Fs /* i : output sampling rate */ + SPAR_DEC_HANDLE *hSpar, /* i/o: SPAR decoder handle */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ); ivas_error ivas_spar_dec( @@ -3700,26 +3929,35 @@ void ivas_spar_config( void ivas_sba_upmixer_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ float output[][L_FRAME48k], /* i/o: transport/output audio channels */ - const int16_t nchan_remapped, /* i : num channels after remapping of TCs */ const int16_t output_frame /* i : output frame length */ ); +ivas_error ivas_sba_linear_renderer( + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t nchan_in, /* i : number of input ambisonics channels */ + const AUDIO_CONFIG output_config, /* i : output audio configuration */ + const IVAS_OUTPUT_SETUP output_setup, /* i : output format setup */ + const float hoa_dec_mtx[] /* i : HOA decoding mtx */ +); + void ivas_sba_mix_matrix_determiner( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ - float in_out[][L_FRAME48k], /* i/o: transport/output audio channels */ + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + float output[][L_FRAME48k], /* i/o: transport/output audio channels */ + const int16_t bfi, /* i : BFI flag */ const int16_t nchan_remapped, /* i : num channels after remapping of TCs */ const int16_t output_frame /* i : output frame length */ ); -void ivas_sba_prototype_renderer( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ - float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: Input audio in CLDFB domain, real */ - float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: Input audio in CLDFB domain, imag */ - const int16_t firstSubframe, /* i: First subframe to map */ - const int16_t nSubframes /* i: Number of subframes to map */ +/* AGC */ +/*! r: AGC enable flag */ +int16_t ivas_agc_enc_get_flag( +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + int16_t agc_configuration, /* i : AGC configuration from command-line */ +#endif + int16_t nchan_transport /* i : number of transport channels */ ); -/* AGC */ ivas_error ivas_spar_agc_enc_open( ivas_agc_enc_state_t **hAgcEnc, /* i/o: AGC decoder handle */ const int32_t input_Fs, /* i : input sampling rate */ @@ -3798,18 +4036,18 @@ int16_t ivas_get_spar_table_idx( int16_t *ind /* o : indice */ ); -int16_t ivas_get_spar_num_TCs( +/*! r: number of transport channels */ +int16_t ivas_get_sba_num_TCs( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t sba_order /* i : IVAS SBA order */ ); -void ivas_spar_set_bitrate_config( - ivas_spar_foa_md_com_cfg *pSpar_md_cfg, /* i/o: SPAR MD config. handle */ +void ivas_spar_set_bitrate_config( + ivas_spar_md_com_cfg *pSpar_md_cfg, /* i/o: SPAR MD config. handle */ const int16_t table_idx, /* i : config. table index */ - const int16_t num_bands /* i : number of bands */ + const int16_t num_bands /* i : number of bands */ ); -#ifdef FIX_I1_113 void ivas_spar_bitrate_dist( int32_t core_brates_act[], /* o : bitrates per core-coder */ const int16_t nAvailBits, /* i : number of available bits */ @@ -3817,50 +4055,48 @@ void ivas_spar_bitrate_dist( const int16_t sba_order, /* i : Ambisonic (SBA) order */ const int16_t bwidth /* i : audio bandwidth */ ); -#endif -void ivas_mdct( const float *pIn, float *pOut, const int16_t length ); -void ivas_dct_windowing( const int16_t fade_len, const int16_t full_len, const int16_t dct_len, const int16_t zero_pad_len, const float *pWindow_coeffs, const int16_t frame_len, float *pOut_buf, float *pBuffer_prev, float *pTemp_lfe ); -void ivas_tda( const float *pIn, float *pOut, const int16_t length ); -void ivas_imdct( const float *pIn, float *pOut, const int16_t length ); -void ivas_itda( const float *re, float *pOut, const int16_t length ); +void ivas_mdct( + const float *pIn, + float *pOut, + const int16_t length +); -/* FOA module */ -ivas_error ivas_spar_foa_enc_open( - ivas_spar_foa_enc_state_t **hSparFoa, /* i/o: SPAR FOA encoder handle */ - const ENCODER_CONFIG_HANDLE hEncoderConfig /* i : configuration structure */ +void ivas_dct_windowing( + const int16_t fade_len, + const int16_t full_len, + const int16_t dct_len, + const int16_t zero_pad_len, + const float *pWindow_coeffs, + const int16_t frame_len, + float *pOut_buf, + float *pBuffer_prev, + float *pTemp_lfe ); -void ivas_spar_foa_enc_close( - ivas_spar_foa_enc_state_t **hSparFoa, /* i/o: SPAR FOA encoder handle */ - const int32_t input_Fs, /* i : input sampling rate */ - const int16_t nchan_inp /* i : number of input channels */ +void ivas_tda( + const float *pIn, + float *pOut, + const int16_t length ); -ivas_error ivas_spar_foa_enc_process( - Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ - const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ - BSTR_ENC_HANDLE hMetaData, /* i/o: MetaData handle */ - const int16_t front_vad_flag, /* i : front-VAD decision */ - float ppPcm_in[][L_FRAME48k] /* i/o: input/transport audio channels */ +void ivas_imdct( + const float *pIn, + float *pOut, + const int16_t length ); -ivas_error ivas_spar_foa_dec_open( - ivas_spar_foa_dec_state_t **hSparFoa, /* i/o: SPAR FOA decoder handle */ - const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t nchan_internal /* i : number of internal channels */ +void ivas_itda( + const float *re, + float *pOut, + const int16_t length ); void ivas_spar_get_cldfb_gains( - ivas_spar_foa_dec_state_t *hSparFoa, + SPAR_DEC_HANDLE hSpar, HANDLE_CLDFB_FILTER_BANK cldfbAnaDec0, HANDLE_CLDFB_FILTER_BANK cldfbSynDec0, - const DECODER_CONFIG_HANDLE hDecoderConfig -); - -void ivas_spar_foa_dec_close( - ivas_spar_foa_dec_state_t **hSparFoa, /* i/o: SPAR FOA decoder handle */ - const int32_t output_Fs /* i : output sampling rate */ + const DECODER_CONFIG_HANDLE hDecoderConfig ); /* !r: 1 if prediction residual channel */ @@ -3869,29 +4105,33 @@ int16_t ivas_is_res_channel( const int16_t nchan_transport /* i : number of transport channels (1-4) */ ); -void ivas_spar_foa_dec_upmixer( +void ivas_spar_dec_upmixer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ float output[][L_FRAME48k], /* i/o: input/output audio channels */ const int16_t nchan_internal, /* i : number of internal channels */ const int16_t output_frame /* i : output frame length */ ); -/* FOA MD module */ -ivas_error ivas_spar_foa_md_enc_open( - ivas_spar_foa_md_enc_state_t **hMdEnc, /* i/o: SPAR MD encoder handle */ - const ENCODER_CONFIG_HANDLE hEncoderConfig /* i : configuration structure */ +/* MD module */ +ivas_error ivas_spar_md_enc_open( + ivas_spar_md_enc_state_t **hMdEnc, /* i/o: SPAR MD encoder handle */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ); -void ivas_spar_foa_md_enc_close( - ivas_spar_foa_md_enc_state_t **hMdEnc /* i/o: SPAR MD encoder handle */ +void ivas_spar_md_enc_close( + ivas_spar_md_enc_state_t **hMdEnc /* i/o: SPAR MD encoder handle */ ); -ivas_error ivas_spar_foa_md_enc_process( - ivas_spar_foa_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ +ivas_error ivas_spar_md_enc_process( + ivas_spar_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ - ivas_spar_foa_md_enc_in_buf_t *pIn_buf, + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], BSTR_ENC_HANDLE hMetaData, /* i/o: MetaData handle */ - const int16_t dtx_silence_mode + const int16_t dtx_vad, + const int16_t nchan_inp, + const int16_t sba_order /* i : Ambisonic (SBA) order */ #ifdef LBR_SBA , const float *prior_mixer[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH] /* i : prior mixer_matrix */ @@ -3912,7 +4152,7 @@ void ivas_compute_spar_params( #ifdef LBR_SBA const int16_t active_w_vlbr, #endif - ivas_spar_foa_md_com_cfg *hSparCfg, + ivas_spar_md_com_cfg *hSparCfg, ivas_spar_md_t *hSparMd, float *pWscale, const int16_t from_dirac @@ -3926,7 +4166,7 @@ void ivas_create_fullr_dmx_mat( const int16_t start_band, const int16_t end_band, const int16_t active_w, - ivas_spar_foa_md_com_cfg *hMdCfg + ivas_spar_md_com_cfg *hMdCfg ); void ivas_calc_c_p_coeffs( @@ -3949,7 +4189,7 @@ void ivas_get_spar_md_from_dirac( const int16_t n_ts, float ***mixer_mat, ivas_spar_md_t *hSpar_md, - ivas_spar_foa_md_com_cfg *hSpar_md_cfg, + ivas_spar_md_com_cfg *hSpar_md_cfg, const int16_t start_band, const int16_t end_band, const int16_t order, @@ -3962,38 +4202,36 @@ void ivas_get_spar_md_from_dirac( #endif ); -ivas_error ivas_spar_foa_md_dec_open( - ivas_spar_foa_md_dec_state_t **hMdDec_out, /* i/o: SPAR MD decoder handle */ +ivas_error ivas_spar_md_dec_open( + ivas_spar_md_dec_state_t **hMdDec_out, /* i/o: SPAR MD decoder handle */ const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t num_channels /* i : number of internal channels */ + const int16_t num_channels, /* i : number of internal channels */ + const int16_t sba_order, /* i : SBA order */ + const int16_t sid_format /* i : SID format */ ); -void ivas_spar_foa_md_dec_close( - ivas_spar_foa_md_dec_state_t **hMdDec /* i/o: SPAR MD decoder handle */ -); - -void ivas_spar_foa_dec_MD( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - Decoder_State *st0 /* i/o: decoder state structure - for bitstream handling*/ +void ivas_spar_md_dec_close( + ivas_spar_md_dec_state_t **hMdDec /* i/o: SPAR MD decoder handle */ ); void ivas_spar_get_parameters( - ivas_spar_foa_dec_state_t *hSparFoa, /* i/o: SPAR FOA decoder handle */ - const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t ts, /* i : time slot index */ - const int16_t num_ch_out, /* i : number of channels out */ - const int16_t num_ch_in, /* i : number of channels in */ - const int16_t num_spar_bands, /* i : number of SPAR bands */ - float par_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS] /* o : mixing matrix */ + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ + const int16_t ts, /* i : time slot index */ + const int16_t num_ch_out, /* i : number of channels out */ + const int16_t num_ch_in, /* i : number of channels in */ + const int16_t num_spar_bands, /* i : number of SPAR bands */ + float par_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS] /* o : mixing matrix */ ); -ivas_error ivas_spar_foa_md_dec_init( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ +ivas_error ivas_spar_md_dec_init( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t num_channels /* i : number of internal channels */ + const int16_t num_channels, /* i : number of internal channels */ + const int16_t sba_order /* i : SBA order */ ); -void ivas_spar_foa_md_dec_process( +void ivas_spar_md_dec_process( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ const int16_t num_bands_out, /* i : number of output bands */ @@ -4002,30 +4240,31 @@ void ivas_spar_foa_md_dec_process( void ivas_spar_to_dirac( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const int16_t dtx_vad, /* i : DTX frame flag */ const int16_t num_bands_out /* i : number of output bands */ #ifdef LBR_SBA - , const int16_t bw /* i : band joining factor */ + , + const int16_t bw /* i : band joining factor */ #endif ); -void ivas_spar_foa_update_md_hist( - ivas_spar_foa_md_dec_state_t *hMdDec /* i/o: SPAR MD decoder handle */ +void ivas_spar_update_md_hist( + ivas_spar_md_dec_state_t *hMdDec /* i/o: SPAR MD decoder handle */ ); -void ivas_spar_foa_smooth_md_dtx( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ +void ivas_spar_smooth_md_dtx( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const int16_t num_bands_out /* i : number of output bands */ ); -void ivas_spar_foa_setup_md_smoothing( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ +void ivas_spar_setup_md_smoothing( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const int16_t num_bands_out /* i : number of output bands */ ); -void ivas_spar_foa_dec_gen_umx_mat( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ +void ivas_spar_dec_gen_umx_mat( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const int16_t nchan_transport, /* i : number of transport channels */ const int16_t num_bands_out, /* i : number of output bands */ const int16_t bfi /* i : bad frame indicator */ @@ -4050,12 +4289,17 @@ void ivas_spar_covar_enc_close( void ivas_enc_cov_handler_process( ivas_enc_cov_handler_state_t *hCovEnc, /* i/o: SPAR Covar. encoder handle */ - ivas_enc_cov_handler_in_buf_t *pIn_buf, + float **ppIn_FR_real, + float **ppIn_FR_imag, float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], ivas_filterbank_t *pFb, /* i/o: FB handle */ const int16_t start_band, - const int16_t end_band ); + const int16_t end_band, + const int16_t nchan_inp, + const int16_t dtx_vad, + const int16_t transient_det[2] +); ivas_error ivas_spar_covar_smooth_enc_open( ivas_cov_smooth_state_t **hCovState, /* i/o: SPAR Covar. smoothing handle */ @@ -4064,7 +4308,7 @@ ivas_error ivas_spar_covar_smooth_enc_open( const int16_t nchan_inp /* i : number of input channels */ #ifdef LBR_SBA_EXTRA_COV_SMOOTH , - const int32_t ivas_total_brate /* i : IVAS total bitrate */ + const int32_t ivas_total_brate /* i : IVAS total bitrate */ #endif ); @@ -4075,30 +4319,33 @@ void ivas_spar_covar_smooth_enc_close( void ivas_cov_smooth_process( ivas_cov_smooth_state_t *hCovState, /* i/o: Covariance state handle */ - ivas_cov_smooth_in_buf_t *pIn_buf, + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], ivas_filterbank_t *pFb, /* i/o: FB handle */ const int16_t start_band, - const int16_t end_band + const int16_t end_band, + const int16_t num_ch, + const int16_t transient_det[2] ); /* Transient detector module */ -ivas_error ivas_spar_transient_det_open( - ivas_trans_det_state_t **hTranDet, /* i/o: SPAR TD handle */ +ivas_error ivas_transient_det_open( + ivas_trans_det_state_t **hTranDet, /* i/o: Transient detector handle */ const int32_t sampling_rate /* i : sampling rate */ ); -void ivas_spar_transient_det_close( - ivas_trans_det_state_t **hTranDet /* i/o: SPAR TD handle */ +void ivas_transient_det_close( + ivas_trans_det_state_t **hTranDet /* i/o: Transient detector handle */ ); -int16_t ivas_transient_det_process( +void ivas_transient_det_process( ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ float *pIn_pcm, /* i : input audio channels */ - const int16_t frame_len /* i : frame length in samples */ + const int16_t frame_len, /* i : frame length in samples */ + int16_t transient_det[2] /* o : transient det outputs */ ); void ivas_td_decorr_get_ducking_gains( - ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ + ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ float *pIn_pcm, float *pIn_duck_gains, float *pOut_duck_gains, @@ -4106,15 +4353,15 @@ void ivas_td_decorr_get_ducking_gains( const int16_t tdet_flag ); -ivas_error ivas_spar_td_decorr_dec_open( - ivas_td_decorr_state_t **hTdDecorr, /* i/o: SPAR Covar. decoder handle */ +ivas_error ivas_td_decorr_dec_open( + ivas_td_decorr_state_t **hTdDecorr, /* i/o: TD decorrelator handle */ const int32_t output_Fs, /* i : output sampling rate */ const int16_t nchan_internal, /* i : number of internal channels */ const int16_t ducking_flag /* i : ducking flag */ ); -void ivas_spar_td_decorr_dec_close( - ivas_td_decorr_state_t **hTdDecorr /* i/o: SPAR Covar. decoder handle */ +void ivas_td_decorr_dec_close( + ivas_td_decorr_state_t **hTdDecorr /* i/o: TD decorrelator handle */ ); void ivas_td_decorr_process( @@ -4149,7 +4396,7 @@ void ivas_td_decorr_process( /* PCA */ -void init_pca_enc( +void ivas_pca_enc_init( PCA_ENC_STATE *hPCA /* i/o: PCA encoder structure */ ); @@ -4167,7 +4414,7 @@ void ivas_pca_read_bits( PCA_DEC_STATE *hPCA /* i/o: PCA encoder structure */ ); -void init_pca_dec( +void ivas_pca_dec_init( PCA_DEC_STATE *hPCA /* i/o: PCA decoder structure */ ); @@ -4196,7 +4443,7 @@ void cov_subfr( ); void eig_qr( - float *A, + const float *A, const int16_t num_iter, float *EV, float *Vals, const int16_t n @@ -4209,7 +4456,7 @@ void exhst_4x4( ); float mat_det4( - float *m + const float *m ); /* quaternion utilities */ @@ -4257,13 +4504,11 @@ int16_t ivas_get_bits_to_encode( ); void ivas_huffman_encode( ivas_huffman_cfg_t *huff_cfg, int16_t in, int16_t *hcode, int16_t *hlen ); -void ivas_huff_coeffs_enc_init( ivas_huff_coeffs_t *pHuff_coeffs, const int16_t table_idx ); -void ivas_arith_coeffs_enc_init( ivas_arith_coeffs_t *pArith_coeffs, ivas_spar_foa_md_com_cfg *pSpar_cfg, const int16_t table_idx ); +void ivas_spar_huff_coeffs_com_init( ivas_huff_coeffs_t *pHuff_coeffs, ivas_spar_md_com_cfg *pSpar_cfg, const int16_t table_idx, const int16_t enc_dec ); +void ivas_spar_arith_coeffs_com_init( ivas_arith_coeffs_t *pArith_coeffs, ivas_spar_md_com_cfg *pSpar_cfg, const int16_t table_idx, const int16_t enc_dec ); void ivas_arith_encode_cmplx_cell_array(ivas_arith_t *pArith_re, ivas_arith_t *pArith_re_diff, const int16_t *pDo_diff, const int16_t nB, int16_t *pSymbol_re, int16_t *pSymbol_old_re, ivas_cell_dim_t *pCell_dims, BSTR_ENC_HANDLE hMetaData, const int16_t any_diff); ivas_error ivas_huffman_decode( ivas_huffman_cfg_t *huff_cfg, Decoder_State *st0, int16_t *dec_out ); void ivas_arith_decode_cmplx_cell_array( ivas_arith_t *pArith_re, ivas_arith_t *pArith_re_diff, Decoder_State *st0, ivas_cell_dim_t *pCell_dims, int16_t *pDo_diff, const int16_t nB, int16_t *pSymbol_re, int16_t *pSymbol_re_old ); -void ivas_arith_coeffs_dec_init( ivas_arith_coeffs_t *pArith_coeffs, ivas_spar_foa_md_com_cfg *pSpar_cfg, const int16_t table_idx ); -void ivas_huff_coeffs_dec_init( ivas_huff_coeffs_t *pHuff_coeffs, ivas_spar_foa_md_com_cfg *pSpar_cfg, const int16_t table_idx ); void ivas_ari_start_decoding_14bits_ext_1_lfe( Decoder_State *st, Tastat *s, int16_t *extra_bits_read ); uint16_t ivas_ari_decode_14bits_bit_ext_1_lfe( Decoder_State *st, Tastat *s, const uint16_t *cum_freq, int16_t *extra_bits_read ); @@ -4273,22 +4518,24 @@ void ivas_ari_encode_14bits_ext( BSTR_ENC_HANDLE hBstr, Tastat *s, int32_t symbo void ivas_wrap_arround( int16_t *pArr, const int16_t min_val, const int16_t max_val, const int16_t length ); void ivas_get_cum_freq_model( const int16_t *pFreq_model, const int16_t length, int16_t *pCum_freq_model ); +int16_t ivas_map_num_pred_r_to_idx( const int16_t num_quant_points_pred_r, const int16_t active_w_flag ); +int16_t ivas_map_num_drct_r_to_idx( const int16_t num_quant_points_drct_r ); +int16_t ivas_map_num_decd_r_to_idx( const int16_t num_quant_points_decd_r ); /* Quantization utilities */ -void ivas_quantise_real_values( - float **values, - const int16_t q_levels, - const float min_value, - const float max_value, - int16_t **index, - float **quant, - const int16_t dim1, - const int16_t dim2 +void ivas_quantise_real_values( + const float *values, + const int16_t q_levels, + const float min_value, + const float max_value, + int16_t *index, + float *quant, + const int16_t dim ); -void ivas_spar_foa_get_uniform_quant_strat( - ivas_spar_foa_md_com_cfg *pSpar_md_com_cfg, - const int16_t table_idx +void ivas_spar_get_uniform_quant_strat( + ivas_spar_md_com_cfg *pSpar_md_com_cfg, + const int16_t table_idx ); void ivas_spar_quant_dtx_init( @@ -4296,11 +4543,11 @@ void ivas_spar_quant_dtx_init( float *min_max ); -void ivas_map_prior_coeffs_quant( - ivas_spar_md_prev_t *pSpar_md_prior, - ivas_spar_foa_md_com_cfg *pSpar_md_cfg, - const int16_t qsi, - const int16_t nB +void ivas_map_prior_coeffs_quant( + ivas_spar_md_prev_t *pSpar_md_prior, + ivas_spar_md_com_cfg *pSpar_md_cfg, + const int16_t qsi, + const int16_t nB ); void ivas_copy_band_coeffs_idx_to_arr( @@ -4332,7 +4579,7 @@ ivas_error ivas_masa_dec_open( ); void ivas_masa_dec_close( - MASA_DECODER_HANDLE hMasa /* i/o: MASA metadata structure */ + MASA_DECODER_HANDLE *hMasa /* i/o: MASA metadata structure */ ); ivas_error ivas_masa_decode( @@ -4350,9 +4597,12 @@ ivas_error ivas_masa_enc_open( ); void ivas_masa_enc_close( - MASA_ENCODER_HANDLE hMasa, /* i/o: MASA metadata structure */ + MASA_ENCODER_HANDLE *hMasa /* i/o: MASA metadata structure */ + #ifndef FIX_350_MASA_DELAY_COMP + , const int16_t nchan_transport, /* i : Number of transport channels */ const IVAS_FORMAT ivas_format /* i : IVAS format */ + #endif ); void ivas_masa_enc_reconfigure( @@ -4363,7 +4613,7 @@ ivas_error ivas_masa_dec_reconfigure( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); -void ivas_masa_encode( +ivas_error ivas_masa_encode( MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */ @@ -4406,10 +4656,10 @@ void ivas_masa_set_coding_config( /*! r: Surround coherence significant flag */ uint8_t ivas_masa_surrcoh_signicant( - float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Surround coherence */ - float diffuse_to_total_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Diffuse to total ratio */ - const int16_t nSubFrames, /* i : Number of sub frames */ - const int16_t nBands /* i : Number of frequency bands */ + float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Surround coherence */ + float diffuse_to_total_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Diffuse to total ratio */ + const int16_t nSubFrames, /* i : Number of sub frames */ + const int16_t nBands /* i : Number of frequency bands */ ); void masa_compensate_two_dir_energy_ratio_index( @@ -4434,6 +4684,9 @@ void masa_sample_rate_band_correction( int16_t *band_mapping, /* i/o: Band mapping used and modified */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: QMetadata structure for modification */ const int32_t sampling_rate /* i : sampling rate */ +#ifdef FIX_350_MASA_DELAY_COMP + , MASA_DECODER_EXT_OUT_META_HANDLE hExtOutMeta /* i/o: MASA decoder metadata ext out buffer */ +#endif ); void invdct4_transform( @@ -4457,52 +4710,38 @@ void ivas_masa_prerender( void ivas_spar_param_to_masa_param_mapping( Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ - float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: Input audio in CLDFB domain, real */ - float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: Input audio in CLDFB domain, imag */ - const int16_t firstSubframe, /* i: First subframe to map */ - const int16_t nSubframes /* i: Number of subframes to map */ -); - - -/*----------------------------------------------------------------------------------* - * output setup prototypes - *----------------------------------------------------------------------------------*/ - -/*! r: number of output channels */ -int16_t audioCfg2channels( - const AUDIO_CONFIG output_config /* i : output audio configuration */ -); - -void ivas_output_init( - IVAS_OUTPUT_SETUP *hOutSetup, /* o : output setup structure */ - const AUDIO_CONFIG output_config /* i : output audio configuration */ + float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ + float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, imag */ + const int16_t firstSubframe, /* i : First subframe to map */ + const int16_t nSubframes /* i : Number of subframes to map */ ); /*---------------------------------------------------------------------------------* - * Binaural Renderer Prototypes + * Binaural FastConv Renderer Prototypes *-----------------------------------------------------------------------------------*/ ivas_error ivas_binRenderer_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); void ivas_binRenderer_close( - BINAURAL_RENDERER_HANDLE *hBinRenderer /* i/o: decoder binaural renderer handle */ + BINAURAL_RENDERER_HANDLE *hBinRenderer /* i/o: decoder binaural renderer handle */ ); +#ifdef DEBUGGING void ivas_binaural_cldfb( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ ); - +#endif void ivas_binRenderer( - BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */ - HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */ - float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ - float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX] /* i : LS signals */ + BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */ + HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i/o: head track handle */ + float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ + float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX] /* i : LS signals */ ); void ivas_binaural_add_LFE( @@ -4511,75 +4750,6 @@ void ivas_binaural_add_LFE( float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ ); -void QuatToRotMat( - const Quaternion quat, /* i : quaternion describing the rotation */ - float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ -); - -void Quat2Euler( - const Quaternion quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ -); - -void rotateAziEle( - float azi_in, /* i : output elevation */ - float ele_in, /* i : input elevation */ - int16_t *azi, /* o : rotated azimuth */ - int16_t *ele, /* o : rotated elevation */ - float Rmat[3][3], /* i : real-space rotation matrix */ - const int16_t isPlanar /* i : is roation planar and elevation meaningless? */ -); - -void rotateAziEle_DirAC( - int16_t *azi, /* i/o: array of azimuth values */ - int16_t *ele, /* i/o: array of elevation values */ - const int16_t band1, /* i : bands to work on (lower limit) */ - const int16_t band2, /* i : bands to work on (upper bound) */ - const float *p_Rmat /* i : pointer to real-space rotation matrix */ -); - -ivas_error ivas_headTrack_open( - HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* o : head track handle */ -); - -void rotateFrame_shd( - HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ - float output[][L_FRAME48k], /* i/o: unrotated HOA3 signal buffer in TD */ - const int32_t output_fs, /* i : output sampling frequency */ - const int16_t subframe_len, /* i : subframe length per channel */ - const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ - const int16_t subframe_idx /* i : subframe index */ -); - -void rotateFrame_sd( - HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ - float output[][L_FRAME48k], /* i/o: unrotated SD signal buffer in TD */ - const int32_t output_fs, /* i : output sampling frequency */ - const int16_t subframe_len, /* i : subframe length per channel */ - const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ - const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ - const int16_t subframe_idx /* i : subframe index */ -); - -void rotateFrame_shd_cldfb( - float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */ - float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ - float Rmat[3][3], /* i : real-space rotation matrix */ - const int16_t nInChannels, /* i : number of channels */ - const int16_t shd_rot_max_order /* i : split-order rotation method */ -); - -void rotateFrame_sd_cldfb( - HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ - float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */ - float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ - const IVAS_OUTPUT_SETUP_HANDLE hOutputSetup, /* i : output format setup number of channels */ - const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ - const int16_t nb_band /* i : number of CLDFB bands to process */ -); - /*----------------------------------------------------------------------------------* * renderer prototypes @@ -4595,6 +4765,13 @@ void ivas_ism_render( const int16_t output_frame /* i : output frame length per channel */ ); +void ivas_ism_get_stereo_gains( + const float azimuth, /* i : object azimuth */ + const float elevation, /* i : object elevation */ + float *left_gain, /* o : left channel gain */ + float *right_gain /* o : right channel gain */ +); + void ivas_mc2sba( IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ float buffer_td[][L_FRAME48k], /* i/o: MC signals (on input) and the HOA3 (on output) */ @@ -4603,27 +4780,18 @@ void ivas_mc2sba( const float gain_lfe /* i : gain for LFE, 0=ignore LFE */ ); -void ivas_sba2mc_cldfb( - IVAS_OUTPUT_SETUP hInSetup, /* i : Format of input layout */ - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb real part */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb imag part */ - const int16_t nb_channels_out, /* i : nb of output channels */ - const int16_t nb_bands, /* i : nb of CLDFB bands to process */ - const float *hoa_dec_mtx /* i : hoa decoding mtx */ -); - void ivas_ism2sba( float buffer_td[][L_FRAME48k], /* i/o: TD signal buffers */ ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ const ISM_METADATA_HANDLE hIsmMetaData[], /* i : object metadata */ - const int16_t num_objects, /* i : number of objects */ + const int16_t nchan_ism, /* i : number of objects */ const int16_t output_frame, /* i : output frame length per channel */ const int16_t sba_order /* i : SBA order */ ); /*----------------------------------------------------------------------------------* - * Amplitude Panning (EFAP, VBAP) prototypes + * Amplitude Panning VBAP prototypes *----------------------------------------------------------------------------------*/ void panning_wrap_angles( @@ -4633,26 +4801,6 @@ void panning_wrap_angles( float *ele_wrapped /* o : wrapped elevation component */ ); -ivas_error efap_init_data( - EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ - const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ - const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ - const int16_t num_speaker_nodes, /* i : number of speaker nodes in the set */ - const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ -); - -void efap_free_data( - EFAP_HANDLE *hEFAPdata /* i/o: EFAP handle to be freed */ -); - -void efap_determine_gains( - EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ - float *gains, /* o : gain vector for speaker nodes for given direction */ - const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ - const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */ - const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ -); - ivas_error vbap_init_data( VBAP_HANDLE *hVBAPdata, /* i/o: handle for VBAP data structure that will be initialized */ const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ @@ -4672,9 +4820,9 @@ void vbap_determine_gains( ); void v_sort_ind( - float *x, /* i/o: Vector to be sorted */ - int16_t *idx, /* o : Original index positions */ - const int16_t len /* i : vector length */ + float *x, /* i/o: Vector to be sorted */ + int16_t *idx, /* o : Original index positions */ + const int16_t len /* i : vector length */ ); /*----------------------------------------------------------------------------------* @@ -4709,7 +4857,7 @@ void ivas_lssetupconversion_process_param_mc( Decoder_Struct *st_ivas, /* i/o: LS setup conversion renderer handle */ float Cldfb_RealBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */ float Cldfb_ImagBuffer_InOut[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i/o: LS signals */ - int16_t channel_active[MAX_CICP_CHANNELS] /* i : bitmap indicating which output channels are active */ + int16_t channel_active[MAX_CICP_CHANNELS] /* i : bitmap indicating which output channels are active */ ); @@ -4727,7 +4875,7 @@ ivas_error ivas_ls_custom_output_init( void ivas_ls_custom_setup( IVAS_OUTPUT_SETUP_HANDLE hOutSetup, /* o : IVAS output setup handle */ - const LSSETUP_CUSTOM_HANDLE hLsSetupCustom /* i : Custom loudspeaker setup handle */ + const LSSETUP_CUSTOM_STRUCT *hLsSetupCustom /* i : Custom loudspeaker setup handle */ ); @@ -4740,10 +4888,18 @@ ivas_error ivas_mcmasa_enc_open( ); void ivas_mcmasa_enc_close( - MCMASA_ENC_HANDLE hMcMasa, /* i/o: encoder McMASA handle */ + MCMASA_ENC_HANDLE *hMcMasa, /* i/o: encoder McMASA handle */ const int32_t input_Fs /* i : input sampling rate */ ); +ivas_error ivas_mcmasa_enc_reconfig( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +); + +ivas_error ivas_mcmasa_dec_reconfig( + Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ +); + void ivas_mcmasa_setNumTransportChannels( int16_t* nchan_transport, /* o : Pointer to number of transport channels to be set */ int16_t* element_mode, /* o : Pointer to element mode to be set */ @@ -4756,9 +4912,13 @@ void ivas_mcmasa_set_separate_channel_mode( const int32_t ivas_total_brate /* i : Total bitrate of IVAS */ ); -/*! r: McMASA SCE bitrate */ -int32_t ivas_mcmasa_mono_brate( - const int32_t ivas_total_brate /* i : IVAS total bitrate */ +void ivas_mcmasa_split_brate( + const uint8_t separateChannelEnabled, /* i : Transport running in "separate channel" mode */ + const int32_t ivas_total_brate, /* i : Total bitrate available to be split */ + const int16_t nSCE, /* i : Number of SCEs in use (0 or 1) */ + const int16_t nCPE, /* i : Number of CPEs in use (0 or 1) */ + int32_t *brate_sce, /* o : Pointer to SCE element bitrate */ + int32_t *brate_cpe /* o : Pointer to CPE element bitrate */ ); void ivas_mcmasa_enc( @@ -4775,28 +4935,35 @@ void ivas_mcmasa_param_est_enc( MCMASA_ENC_HANDLE hMcMasa, /* i/o: Encoder McMASA handle */ MASA_ENCODER_HANDLE hMasa, /* i/o: Encoder MASA handle */ float data_f[][L_FRAME48k], /* i : Input frame of audio */ - float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ - float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ - float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ - float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ - float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ + float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ + float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ + float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio*/ + float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ + float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ const int16_t input_frame, /* i : Input frame size */ const int16_t nchan_inp /* i : Number of input channels */ ); +void ivas_mcmasa_dmx_modify( + const int16_t n_samples, /* i : input frame length in samples */ + float dmx[][L_FRAME48k + NS2SA( 48000, IVAS_FB_ENC_DELAY_NS )], /* i/o: downmix signal to be transformed into another format */ + const int16_t n_chnls_dmx_old, /* i : number of downmix channels in the old format */ + const int16_t n_chnls_dmx_new /* i : number of downmix channels in the target format */ +); + void v_multc_acc( - const float x[], /* i : Input vector */ - const float c, /* i : Constant */ - float y[], /* o : Output vector that contains y + c*x */ - const int16_t N /* i : Vector length */ + const float x[], /* i : Input vector */ + const float c, /* i : Constant */ + float y[], /* o : Output vector that contains y + c*x */ + const int16_t N /* i : Vector length */ ); void lls_interp_n( - float x[], /* i/o: input/output vector */ - const int16_t N, /* i : length of the input vector */ - float *a, /* o : calculated slope */ - float *b, /* o : calculated offset */ - int16_t upd /* i : use 1 to update x[] with the interpolated output */ + float x[], /* i/o: input/output vector */ + const int16_t N, /* i : length of the input vector */ + float *a, /* o : calculated slope */ + float *b, /* o : calculated offset */ + const int16_t upd /* i : use 1 to update x[] with the interpolated output*/ ); void computeReferencePower_enc( @@ -4805,12 +4972,12 @@ void computeReferencePower_enc( float Cldfb_ImagBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], /* i : Imag part of input signal */ float *reference_power, /* o : Estimated power */ const int16_t enc_param_start_band, /* i : first band to process */ - const int16_t num_freq_bands /* i : Number of frequency bands */ + const int16_t num_freq_bands, /* i : Number of frequency bands */ + const SBA_MODE sba_mode /* i : SBA mode */ ); - ivas_error ivas_mono_dmx_renderer_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); void ivas_mono_downmix_render_passive( @@ -4833,6 +5000,7 @@ void ivas_lfe_synth_with_filters( const int16_t lfeChannelIndex /* i : LFE channel index */ ); + /*----------------------------------------------------------------------------------* * LFE Coding prototypes *----------------------------------------------------------------------------------*/ @@ -4843,7 +5011,7 @@ ivas_error ivas_create_lfe_enc( ); void ivas_lfe_enc_close( - LFE_ENC_HANDLE hLFE /* i/o: LFE encoder handle */ + LFE_ENC_HANDLE *hLFE /* i/o: LFE encoder handle */ ); void ivas_lfe_enc( @@ -4856,11 +5024,11 @@ void ivas_lfe_enc( ivas_error ivas_create_lfe_dec( LFE_DEC_HANDLE *hLFE_out, /* o : IVAS LFE decoder structure */ const int32_t output_Fs, /* i : output sampling rate */ - const float add_delay_s /* i : additional delay in seconds to lfe to sync with binaural filter*/ + const int32_t binauralization_delay_ns /* i : additional LFE delay to sync with binaural renderer */ ); void ivas_lfe_dec_close( - LFE_DEC_HANDLE hLFE /* i/o: LFE encoder handle */ + LFE_DEC_HANDLE *hLFE /* i/o: LFE encoder handle */ ); void ivas_lfe_dec( @@ -4879,9 +5047,9 @@ void LFE_tdplc( ); void lfe_window_init( - LFE_WINDOW_HANDLE hLFEWindow, - const int32_t sampling_rate, - const int16_t frame_len + LFE_WINDOW_HANDLE hLFEWindow, /* i/o: LFE window handle */ + const int32_t sampling_rate, /* i : sampling rate */ + const int16_t frame_len /* i : frame length in samples */ ); void ivas_lfe_lpf_select_filt_coeff( @@ -4891,15 +5059,15 @@ void ivas_lfe_lpf_select_filt_coeff( ); void ivas_filters_init( - ivas_filters_process_state_t *filter_state, - const float *filt_coeff, - const int16_t order + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + const float *filt_coeff, /* i : filter coefficients */ + const int16_t order /* i : filter order */ ); void ivas_filter_process( - ivas_filters_process_state_t *filter_state, - float *pIn_Out, - const int16_t length + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + float *pIn_Out, /* i : signal subject to filtering */ + const int16_t length /* i : filter order */ ); @@ -4907,236 +5075,16 @@ void ivas_filter_process( * TD Binaural Object renderer *----------------------------------------------------------------------------------*/ -ivas_error ivas_HRTF_binary_open( - TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ -); - -void ivas_HRTF_binary_close( - TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ -); - -/*! r: TD Renderer result code. */ -ivas_error DefaultBSplineModel( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* o : Loaded HR filter set */ - const int32_t output_Fs /* i : Output sampling rate */ -); - ivas_error ivas_td_binaural_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); -void ivas_td_binaural_close( - BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */ -); - -ivas_error ObjRenderIVASFrame( +ivas_error ivas_td_binaural_renderer( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ const int16_t output_frame /* i : output frame length */ ); -void BSplineModelEvalAlloc( - ModelParams_t *model, /* i : Model parameters */ - ModelEval_t *modelEval /* i/o: Model evaluation structure */ -); - -/* ----- Object renderer - hrfilt ----- */ - -void GetFilterFromAngle( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ - const float Elev, /* i : Elevation, degrees */ - float Azim, /* i : Azimuth, degrees */ - SFX_SpatBin_Params_t *SfxSpatBinParams_p /* i/o: Currently used HR filter */ -); - -void HRTF_model_precalc( - ModelParams_t *model /* i/o: HRTF Model parameters */ -); - -void BSplineModelEvalDealloc( - ModelParams_t *model, /* i : Model parameters */ - ModelEval_t *modelEval /* i : Model evaluation structure */ -); - -void BSplineModelEvalITDDealloc( - ModelParamsITD_t *model /* i : Model parameters */ -); - -#ifdef TDREND_HRTF_TABLE_METHODS -void TDREND_HRFILT_SetFiltSet( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR hilter set structure */ - FILE *f_hrtf /* i : File handle for HR filter parameters */ -); -#endif - -ivas_error TDREND_REND_RenderSourceHRFilt( - const TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ -#ifdef TDREND_HRTF_TABLE_METHODS - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ -#endif - float output_buf[][L_FRAME48k], /* o : Output buffer */ - const int16_t output_frame, /* i : Output frame length in use */ - const int32_t output_Fs /* i : Output sample rate */ -); - -/* ----- Object renderer - sources ----- */ - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_SRC_SetPos( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const int16_t SrcInd, /* i : Source index */ - const float *Vec_p /* i : Position vector */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_SRC_SetDir( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const int16_t SrcInd, /* i : Source index */ - const float *Vec_p /* i : Direction vector */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_SRC_SetDirAtten( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const int16_t SrcInd, /* i : Source index */ - const TDREND_DirAtten_t *DirAtten_p /* i : Directional attenuation specifier */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_SRC_SetPlayState( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const int16_t SrcInd, /* i : Source index */ - const TDREND_PlayStatus_t PlayStatus /* i : Play state */ -); - - -void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ - TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i : Spatial aspects of source */ - const int32_t output_Fs /* i : Output sample rate */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_SRC_Alloc( - TDREND_SRC_t **Src_pp /* i/o: Source */ -); - -void TDREND_SRC_Dealloc( - TDREND_SRC_t *Src_p /* i/o: Source to deallocate */ -); - -void TDREND_SRC_Init( - TDREND_SRC_t *Src_p, /* i/o: Source to initialize */ - const TDREND_PosType_t PosType, /* i : Position type specifier */ - const int32_t output_Fs /* i : Output sampling rate */ -); - -/* ----- Object renderer - vec ----- */ - -void TDREND_SPATIAL_VecInit( - float *Pos_p, /* o : Output vector */ - const float PosX, /* i : X value */ - const float PosY, /* i : Y value */ - const float PosZ /* i : Z value */ -); - -/*! r: Euclidian norm value */ -float TDREND_SPATIAL_VecNorm( - const float *Vec_p /* i : Vector for norm calculation */ -); - -void TDREND_SPATIAL_VecNormalize( - const float *Vec_p, /* i : Input vector */ - float *VecNorm_p /* o : Output vector */ -); - -void TDREND_SPATIAL_VecMapToNewCoordSystem( - const float *Vec_p, /* i : Input vector */ - const float *TranslVec_p, /* i : Translation vector */ - const float *DirVec_p, /* i : Direction vector */ - const float *UpVec_p, /* i : Up vector */ - const float *RightVec_p, /* i : Right vector */ - float *MappedVec_p /* o : Transformed vector */ -); - -/*! r: Flag if the orientation has been updated */ -int16_t TDREND_SPATIAL_EvalOrthonormOrient( - float *FrontVecON_p, /* o : Normalized front vector */ - float *UpVecON_p, /* o : Normalized up vector */ - float *RightVecON_p, /* o : Normalized right vector */ - const float *FrontVec_p, /* i : Input front vector */ - const float *UpVec_p /* i : Input up vector */ -); - -/* ----- Object renderer - mix ----- */ - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_AddSrc( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - int16_t *SrcInd, /* o : Source index */ - const TDREND_PosType_t PosType, /* i : Position type (absolute/relative) */ - const int32_t output_Fs /* i : Output sampling rate */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_SetDistAttenModel( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const TDREND_DistAttenModel_t DistAttenModel /* i : Distance attenuation model */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_LIST_SetPos( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const float *Pos_p /* i : Listener's position */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_LIST_SetOrient( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - const float *FrontVec_p, /* i : Listener's orientation front vector */ - const float *UpVec_p /* i : Listener's orientation up vector */ -); - -void TDREND_MIX_Dealloc( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_Init( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HRTF data (initialized in case of NULL) */ - const TDREND_MixSpatSpec_t *MixSpatSpec_p, /* i : Mixer spatial specification */ - const int32_t output_Fs /* i : Output sampling rate */ -); - - /* ----- Object renderer - sfx ----- */ - -/*! r: TD Renderer result code. */ -ivas_error TDREND_SFX_SpatBin_Initialize( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters handle */ - const int32_t output_Fs /* i : Output sampling rate */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_SFX_SpatBin_SetParams( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct to be updated */ - const SFX_SpatBin_Params_t *NewParam_p, /* i : New parameters struct */ - const int32_t output_Fs /* i : Output sample rate */ -); - -/*! r: TD Renderer result code. */ -ivas_error TDREND_SFX_SpatBin_Execute_Main( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters handle */ - const float *InBuffer_p, /* i : Input buffer */ - const int16_t output_frame, /* i : frame length */ - float *LeftOutBuffer_p, /* o : Rendered left channel */ - float *RightOutBuffer_p, /* o : Rendered right channel */ - int16_t *NoOfUsedInputSamples_p, /* o : Number of input samples actually used */ - int16_t *NoOfDeliveredOutputSamples_p, /* o : Number of output samples actually rendered */ - const int32_t output_Fs /* i : Output sample rate */ -); - /*----------------------------------------------------------------------------------* * Filter-bank (FB) Mixer @@ -5155,12 +5103,14 @@ ivas_error ivas_fb_set_cfg( ivas_error ivas_FB_mixer_open( IVAS_FB_MIXER_HANDLE *hFbMixer, /* i/o: FB mixer handle */ const int32_t sampling_rate, /* i : sampling rate */ - IVAS_FB_CFG *fb_cfg /* i : FB config. handle */ + IVAS_FB_CFG *fb_cfg, /* i : FB config. handle */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ); void ivas_FB_mixer_close( IVAS_FB_MIXER_HANDLE *hFbMixer, /* i/o: FB mixer handle */ - const int32_t sampling_rate /* i : sampling rate in Hz */ + const int32_t sampling_rate, /* i : sampling rate in Hz */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ); void ivas_fb_mixer_pcm_ingest( @@ -5171,9 +5121,9 @@ void ivas_fb_mixer_pcm_ingest( ); void ivas_dirac_enc_spar_delay_synchro( - Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ - const int16_t input_frame, /* i : input frame length */ - float data_f[][L_FRAME48k] /* i/o: input: ACN/SN3D, output: omni, stereo DMX or FOA*/ + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const int16_t input_frame, /* i : input frame length */ + float data_f[][L_FRAME48k] /* i/o: SBA channels (ACN / SN3D) */ ); void ivas_fb_mixer_update_prior_input( @@ -5213,285 +5163,6 @@ int16_t ivas_get_num_bands_from_bw_idx( ); -/*----------------------------------------------------------------------------------* - * Crend renderer - *----------------------------------------------------------------------------------*/ - -ivas_error ivas_crend_init_from_rom( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -); - -ivas_error ivas_crend_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -); - -ivas_error ivas_crend_close( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -); - -ivas_error ivas_crend_process( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output[][L_FRAME48k] /* i/o: input/output audio channels */ -); - - -/*----------------------------------------------------------------------------------* - * Renderer configuration - *----------------------------------------------------------------------------------*/ - -ivas_error ivas_render_config_open( - RENDER_CONFIG_HANDLE *hRenderConfig /* i/o: Renderer config handle */ -); - -void ivas_render_config_close( - RENDER_CONFIG_HANDLE *hRenderConfig /* i/o: Renderer config handle */ -); - -ivas_error ivas_render_config_init_from_rom( - RENDER_CONFIG_HANDLE *hRenderConfig, /* i/o: Renderer config handle */ - const int16_t room_flag_on /* i : room effect on/off flag */ -); - -/*----------------------------------------------------------------------------------* - * Reverberator - *----------------------------------------------------------------------------------*/ - -ivas_error ivas_reverb_open( - REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ - const HRTFS_HANDLE hHrtf, /* i : HRTF handle */ - RENDER_CONFIG_DATA *pConfig, /* i : Reverb configuration */ - const int32_t output_Fs /* i : output sampling rate */ -); - -void ivas_reverb_close( - REVERB_HANDLE *hReverb /* i/o: Reverberator handle */ -); - -ivas_error ivas_reverb_process( - REVERB_HANDLE hReverb, /* i/o: reverb state */ - const AUDIO_CONFIG transport_config, /* i : reverb. input audio configuration */ - const int16_t mix_signals, /* i : add reverb to output signal */ - float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ - float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ - const int16_t i_ts -); - -void ivas_rev_delay_line_init( - ivas_rev_delay_line_t *pDelay, /* o : the delay line to initialize */ - float *memory_buffer, /* i : the memory buffer to use for the delay line */ - const uint16_t delay, /* i : the delay */ - const uint16_t maxdelay /* i : maximum delay to be supported */ -); - -/* !r: sample gotten out of delay line, and amplified by set gain */ -float ivas_rev_delay_line_get_sample( - ivas_rev_delay_line_t *pDelay /* i/o: the delay line */ -); - -void ivas_rev_delay_line_feed_sample( - ivas_rev_delay_line_t *pDelay, /* i : the delay line */ - float input /* i : the sample to feed */ -); - -void ivas_rev_delay_line_get_sample_blk( - ivas_rev_delay_line_t *pDelay, /* i : the delay line */ - const uint16_t blk_size, /* i : number of samples in the data block */ - float *output /* i/o: amples gotten out of delay line, and amplified by set gainin */ -); - -void ivas_rev_delay_line_feed_sample_blk( - ivas_rev_delay_line_t *pDelay, /* i/o: the delay line */ - const uint16_t blk_size, /* i : number of samples in the input data block */ - float *input /* i : the samples to feed */ -); - -void ivas_reverb_iir_filt_init( - ivas_rev_iir_filter_t *iirFilter, /* o : IIR filter */ - const uint16_t maxTaps /* i : maximum number of filter taps */ -); - -void ivas_reverb_iir_filt_set( - ivas_rev_iir_filter_t *iirFilter, /* i/o: IIR filter */ - uint16_t nr_taps, /* i : number of IIR filter taps */ - const float *coefA, /* i : A filter coefficients to set */ - const float *coefB /* i : the B filter coefficients to set */ -); - -void ivas_reverb_iir_filt_2taps_feed_blk( - ivas_rev_iir_filter_t *iirFilter, /* i/o: IIR filter */ - const uint16_t blk_size, /* i : size */ - const float *input, /* i : input buffer */ - float *output /* i : output buffer */ -); - -uint16_t int_log2( - uint32_t powerOf2 -); - -int16_t ivas_reverb_t2f_f2t_init( - ivas_reverb_t2f_f2t_t *t2f_f2t, - const int16_t fft_size, - const int16_t block_size -); - -void ivas_reverb_t2f_f2t_ClearHistory( - ivas_reverb_t2f_f2t_t *t2f_f2t -); - -void ivas_reverb_t2f_f2t_in( - ivas_reverb_t2f_f2t_t *t2f_f2t, - float *input_L, - float *input_R, float *buffer_L, - float *buffer_R -); - -void ivas_reverb_t2f_f2t_out( - ivas_reverb_t2f_f2t_t *t2f_f2t, - float *buffer_L, - float *buffer_R, - float *output_L, - float *output_R -); - -int16_t ivas_reverb_fft_filter_init( - ivas_reverb_fft_filter_t *fft_filter, - const int16_t fft_size -); - -void ivas_reverb_fft_filter_ComplexMul( - ivas_reverb_fft_filter_t *fft_filter, - float *buffer -); - -void ivas_reverb_fft_filter_CrossMix( - float *buffer0, - float *buffer1, - const int16_t fft_size -); - -void ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( - rv_fftwf_type_complex *spectrum, - float *fft_real, - const int16_t fft_size -); - -void ivas_reverb_define_window_fft( - float *pWindow, - const int16_t transitionStart, - const int16_t transitionLength, - const int16_t spectrumLength -); - -int16_t ivas_reverb_calc_color_filters( - const float *pTargetL, - const float *pTargetR, - const float *pWindow, - const int16_t fft_size, - const float delay, - rv_fftwf_type_complex *pBeqL, - rv_fftwf_type_complex *pBeqR -); - -int16_t ivas_reverb_calc_correl_filters( - const float *pTargetICC, - const float *pWindow, - const int16_t fft_size, - const float delay, - rv_fftwf_type_complex *pU, - rv_fftwf_type_complex *pV -); - -void ivas_reverb_calc_color_levels( - const int32_t output_Fs, - const int16_t freq_count, - const int16_t loop_count, - const float *pFc, - const float *pAcoustic_dsr, - const float *pHrtf_avg_pwr_L, - const float *pHrtf_avg_pwr_R, - const int16_t *pLoop_delays, - const float *pT60_filter_coeff, - float *pTarget_color_L, - float *pTarget_color_R -); - -void ivas_reverb_prepare_cldfb_params( - ivas_roomAcoustics_t *pInput_params, - AUDIO_CONFIG renderer_config, - int16_t use_brir, - const int32_t output_Fs, - float *pOutput_t60, - float *pOutput_ene ); - -void ivas_reverb_interpolate_acoustic_data( - const int16_t input_table_size, - const float *pInput_fc, - const float *pInput_t60, - const float *pInput_dsrR, - const int16_t output_table_size, - const float *pOutput_fc, - float *pOutput_t60, - float *pOutput_dsr -); - -void ivas_reverb_get_hrtf_set_properties( - float **ppHrtf_set_L_re, - float **ppHrtf_set_L_im, - float **ppHrtf_set_R_re, - float **ppHrtf_set_R_im, - const int16_t hrtf_count, - const int16_t in_freq_count, - const int16_t out_freq_count, - float *pOut_avg_pwr_L, - float *pOut_avg_pwr_R, - float *pOut_i_a_coherence -); - -/* Orientation tracking */ -void ivas_orient_trk_Init( - ivas_orient_trk_state_t *pOTR -); - -ivas_error ivas_orient_trk_SetTrackingType( - ivas_orient_trk_state_t *pOTR, - OTR_TRACKING_T trackingType -); - -ivas_error ivas_orient_trk_SetAbsoluteOrientation( - ivas_orient_trk_state_t *pOTR, - float yaw, - float pitch, - float roll -); - -ivas_error ivas_orient_trk_Process( - ivas_orient_trk_state_t *pOTR -); - -ivas_error ivas_orient_trk_GetTrackedOrientation( - ivas_orient_trk_state_t *pOTR, - float *yaw, - float *pitch, - float *roll -); - -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT -void TonalMdctConceal_create_concealment_noise( - float concealment_noise[L_FRAME48k], - CPE_DEC_HANDLE hCPE, - const int16_t L_frameTCX, - const int16_t L_frame, - const int16_t idchan, - const int16_t subframe_idx, - const int16_t core, - const int16_t crossfade_gain, - const TONALMDCTCONC_NOISE_GEN_MODE noise_gen_mode -); -#endif - -float rand_triangular_signed( - int16_t *seed ); - /* clang-format on */ #endif /* IVAS_PROT_H */ diff --git a/lib_com/ivas_qmetadata_com.c b/lib_com/ivas_qmetadata_com.c index ee8cfd2f2f10de073c8647b8cfe7d740594752e6..0f2491bad3545e1dcfe9a785d208aa1f702f3eb1 100644 --- a/lib_com/ivas_qmetadata_com.c +++ b/lib_com/ivas_qmetadata_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "ivas_prot.h" #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * Local constants @@ -65,7 +65,7 @@ ivas_error ivas_qmetadata_open( ) { /* allocate MetaData handle */ - if ( ( *hQMetaData = (IVAS_QMETADATA_HANDLE) count_malloc( sizeof( IVAS_QMETADATA ) ) ) == NULL ) + if ( ( *hQMetaData = (IVAS_QMETADATA_HANDLE) malloc( sizeof( IVAS_QMETADATA ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); } @@ -98,9 +98,8 @@ ivas_error ivas_qmetadata_allocate_memory( const int16_t coherence_flag /* i : new coherence coding status */ ) { - int16_t dir; + int16_t j, dir; uint8_t do_realloc; - uint8_t reservationFailed = 0; #ifdef DEBUGGING assert( hQMetaData != NULL ); @@ -126,68 +125,63 @@ ivas_error ivas_qmetadata_allocate_memory( hQMetaData->no_directions = ndirs; hQMetaData->coherence_flag = coherence_flag; - hQMetaData->q_direction = (IVAS_QDIRECTION *) count_malloc( sizeof( IVAS_QDIRECTION ) * ndirs ); - reservationFailed = hQMetaData->q_direction == NULL; + if ( ( hQMetaData->q_direction = (IVAS_QDIRECTION *) malloc( sizeof( IVAS_QDIRECTION ) * ndirs ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); + } + - if ( !reservationFailed ) + for ( dir = 0; dir < hQMetaData->no_directions; dir++ ) { - for ( dir = 0; dir < hQMetaData->no_directions; dir++ ) + hQMetaData->q_direction[dir].cfg.nbands = nbands; + if ( nbands == 0 ) { - hQMetaData->q_direction[dir].cfg.nbands = nbands; - if ( nbands == 0 ) - { - hQMetaData->q_direction[dir].band_data = NULL; - } - else + hQMetaData->q_direction[dir].band_data = NULL; + } + else + { + if ( ( hQMetaData->q_direction[dir].band_data = (IVAS_QDIRECTION_BAND_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ) ) == NULL ) { - hQMetaData->q_direction[dir].band_data = (IVAS_QDIRECTION_BAND_DATA *) count_malloc( sizeof( IVAS_QDIRECTION_BAND_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ); - { - int16_t j; - for ( j = 0; j < nbands; j++ ) - { - set_zero( hQMetaData->q_direction[dir].band_data[j].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); - set_zero( hQMetaData->q_direction[dir].band_data[j].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); - } - } - - - reservationFailed |= hQMetaData->q_direction[dir].band_data == NULL; + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); } - if ( coherence_flag ) + for ( j = 0; j < nbands; j++ ) { - hQMetaData->q_direction[dir].coherence_band_data = (IVAS_QDIRECTION_BAND_COHERENCE_DATA *) count_malloc( sizeof( IVAS_QDIRECTION_BAND_COHERENCE_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ); - reservationFailed |= hQMetaData->q_direction[dir].coherence_band_data == NULL; + set_zero( hQMetaData->q_direction[dir].band_data[j].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); + set_zero( hQMetaData->q_direction[dir].band_data[j].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); } - else - { - hQMetaData->q_direction[dir].coherence_band_data = NULL; - } - - /* These default values are set here to get them conveniently in one place */ - hQMetaData->q_direction[dir].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES; - hQMetaData->q_direction[dir].cfg.search_effort = 3; - hQMetaData->q_direction[dir].cfg.start_band = 0; - hQMetaData->q_direction[dir].cfg.mc_ls_setup = MC_LS_SETUP_INVALID; } if ( coherence_flag ) { - hQMetaData->surcoh_band_data = (IVAS_SURROUND_COHERENCE_BAND_DATA *) count_malloc( sizeof( IVAS_SURROUND_COHERENCE_BAND_DATA ) * hQMetaData->q_direction[0].cfg.nbands ); - reservationFailed |= hQMetaData->surcoh_band_data == NULL; + hQMetaData->q_direction[dir].coherence_band_data = (IVAS_QDIRECTION_BAND_COHERENCE_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_COHERENCE_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ); } else { - hQMetaData->surcoh_band_data = NULL; + hQMetaData->q_direction[dir].coherence_band_data = NULL; } + + /* These default values are set here to get them conveniently in one place */ + hQMetaData->q_direction[dir].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES; + hQMetaData->q_direction[dir].cfg.search_effort = 3; + hQMetaData->q_direction[dir].cfg.start_band = 0; + hQMetaData->q_direction[dir].cfg.mc_ls_setup = MC_LS_SETUP_INVALID; } - } - if ( reservationFailed ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Q MetaData\n" ) ); + if ( coherence_flag ) + { + if ( ( hQMetaData->surcoh_band_data = (IVAS_SURROUND_COHERENCE_BAND_DATA *) malloc( sizeof( IVAS_SURROUND_COHERENCE_BAND_DATA ) * hQMetaData->q_direction[0].cfg.nbands ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); + } + } + else + { + hQMetaData->surcoh_band_data = NULL; + } } + return IVAS_ERR_OK; } @@ -215,23 +209,23 @@ static void ivas_qmetadata_free_memory( { if ( hQMetaData->q_direction[dir].band_data != NULL ) { - count_free( hQMetaData->q_direction[dir].band_data ); + free( hQMetaData->q_direction[dir].band_data ); hQMetaData->q_direction[dir].band_data = NULL; } if ( hQMetaData->q_direction[dir].coherence_band_data != NULL ) { - count_free( hQMetaData->q_direction[dir].coherence_band_data ); + free( hQMetaData->q_direction[dir].coherence_band_data ); hQMetaData->q_direction[dir].coherence_band_data = NULL; } } - count_free( hQMetaData->q_direction ); + free( hQMetaData->q_direction ); hQMetaData->q_direction = NULL; } if ( hQMetaData->surcoh_band_data != NULL ) { - count_free( hQMetaData->surcoh_band_data ); + free( hQMetaData->surcoh_band_data ); hQMetaData->surcoh_band_data = NULL; } @@ -256,7 +250,7 @@ void ivas_qmetadata_close( ivas_qmetadata_free_memory( *hQMetaData ); - count_free( *hQMetaData ); + free( *hQMetaData ); *hQMetaData = NULL; return; diff --git a/lib_com/ivas_qspherical_com.c b/lib_com/ivas_qspherical_com.c index cd12fd8dc81add0a03ade5496400ab46c4907cbb..039dea53eb97d18f2537058c841560ae1a90719a 100644 --- a/lib_com/ivas_qspherical_com.c +++ b/lib_com/ivas_qspherical_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "ivas_prot.h" #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -450,7 +450,7 @@ int16_t quantize_phi_chan_compand( float phi, /* i : azimuth value */ float *phi_hat, /* o : quantized azimuth */ const int16_t n, /* i : azimuth codebook size */ - const int16_t theta_flag, /* i : flag signalling high elevation */ + const int16_t theta_flag, /* i : flag signaling high elevation */ const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ ) { diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index f45c56dd5f2d742c841bb51e1ae82986bd4ab2c1..e8c4b3f127b641e0f94025a330a51bdfb140eb18 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "cnst.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /* clang-format off */ @@ -49,7 +49,7 @@ const int32_t ivas_brate_tbl[SIZE_IVAS_BRATE_TBL] = { - FRAME_NO_DATA, IVAS_SID_4k4, IVAS_SID_5k, + FRAME_NO_DATA, IVAS_SID_5k2, IVAS_13k2, IVAS_16k4, IVAS_24k4, IVAS_32k, IVAS_48k, IVAS_64k, IVAS_80k, IVAS_96k, IVAS_128k, IVAS_160k, IVAS_192k, IVAS_256k, IVAS_384k, IVAS_512k @@ -901,11 +901,11 @@ const int16_t DirAC_block_grouping_5ms_MDFT[MAX_PARAM_SPATIAL_SUBFRAMES + 1] = const ivas_spar_br_table_t ivas_spar_br_table_consts[IVAS_SPAR_BR_TABLE_LEN] = { -/* When AGC is ON additional (AGC_BITS_PER_CH+1) bits may be taken from each EVS channel - so minimum EVS bitrate per channel can be min EVS bitrates as per the table - AGC_BITS_PER_CH */ +/* When AGC is ON additional (AGC_BITS_PER_CH+1) bits may be taken from each core-coder channel + so minimum core-coder bitrate per channel can be min core-coder bitrates as per the table - AGC_BITS_PER_CH */ #ifdef LBR_SBA /* preferred tuning (3.2/4.9kbps) with/out TDD */ - { 13200, 0, 1, FB, 24000, 1, WYXZ, 1, 0, + { 13200, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, #ifdef LBR_SBA_PLANAR { { 11000, 9600, 13150 } }, #else @@ -913,7 +913,7 @@ const ivas_spar_br_table_t ivas_spar_br_table_consts[IVAS_SPAR_BR_TABLE_LEN] = #endif { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, - { 16400, 0, 1, FB, 24000, 1, WYXZ, 1, 0, + { 16400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, #ifdef LBR_SBA_PLANAR { { 14200, 12800, 16350 } }, #else @@ -921,4988 +921,563 @@ const ivas_spar_br_table_t ivas_spar_br_table_consts[IVAS_SPAR_BR_TABLE_LEN] = #endif { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, #endif - { 24400, 0, 1, FB, 24000, 1, WYXZ, 1, 0,{ { 16400, 15200, 24350 } }, + { 24400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0,{ { 16400, 14850, 24350 } }, { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, - { 32000, 0, 1, FB, 24000, 1, WYXZ, 1, 0,{{ 24000, 20450, 31950 }},{ { 21, 1, 5, 1 },{ 15, 1, 5, 1 },{ 15, 1, 3, 1 } }, 0, 0, 0 }, + { 32000, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0,{ { 24000, 20450, 31950 } }, + { { 21, 1, 5, 1 },{ 15, 1, 5, 1 },{ 15, 1, 3, 1 } }, 0, 0, 0 }, - { 48000, 0, 1, FB, 24000, 2, WYXZ, 0, 0,{ { 24000, 21000, 31950 },{ 16000, 15000, 20400 } }, + { 48000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0,{ { 24000, 21000, 31950 },{ 16000, 15000, 20400 } }, { { 15, 7, 5, 1 },{ 15, 7, 3, 1 },{ 7, 7, 3, 1 } }, 1, 0, 0 }, - { 64000, 0, 1, FB, 24000, 2, WYXZ, 0, 0,{ { 38000, 34050, 56000 },{ 16000, 15600, 20400 } },{ { 21, 7, 5, 1 },{ 15, 7, 5, 1 },{ 15, 7, 3, 1 } }, 1, 1, 0 }, + { 64000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0,{ { 38000, 34050, 56000 },{ 16000, 15600, 20400 } },{ { 21, 7, 5, 1 },{ 15, 7, 5, 1 },{ 15, 7, 3, 1 } }, 1, 1, 0 }, - { 80000, 0, 1, FB, 24000, 2, WYXZ, 0, 0,{ { 46000, 43000, 56000 },{ 24000, 23000, 31950 } }, + { 80000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0,{ { 46000, 43000, 56000 },{ 24000, 23000, 31950 } }, { { 21, 7, 5, 1 },{ 15, 7, 5, 1 },{ 15, 7, 3, 1 } }, 1, 0, 0 }, - { 96000, 0, 1, FB, 24000, 3, WYXZ, 0, 0,{ { 47000, 42600, 56000 },{ 23000, 22600, 31950 },{ 16000, 15600, 20400 } }, + { 96000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0,{ { 47000, 42600, 56000 },{ 23000, 22600, 31950 },{ 16000, 15600, 20400 } }, { { 21, 9, 9, 1 },{ 21, 7, 5, 1 },{ 21, 7, 5, 1 } }, 1, 0, 0 }, - { 128000, 0, 1, FB, 24000, 3, WYXZ, 0, 0,{ { 55000, 50000, 56000 },{ 36000, 36000, 56000 },{ 27000, 27000, 31950 } }, + { 128000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0,{ { 55000, 50000, 56000 },{ 36000, 36000, 56000 },{ 27000, 27000, 31950 } }, { { 21, 11, 9, 1 },{ 21, 9, 7, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, - { 160000, 0, 1, FB, 24000, 3, WYXZ, 0, 0,{ { 74000, 70900, 112000 },{ 41000, 40050, 56000 },{ 35000, 34050, 56000 } }, + { 160000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0,{ { 74000, 70900, 112000 },{ 41000, 40050, 56000 },{ 35000, 34050, 56000 } }, { { 21, 11, 11, 1 },{ 21, 9, 9, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, - { 192000, 0, 1, FB, 24000, 3, WYXZ, 0, 0,{ { 90000, 87900, 112000 },{ 50000, 48050, 56000 },{ 42000, 41050, 56000 } }, + { 192000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0,{ { 90000, 87900, 112000 },{ 50000, 48050, 56000 },{ 42000, 41050, 56000 } }, { { 21, 11, 11, 1 },{ 21, 9, 9, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, - { 256000, 0, 1, FB, 24000, 4, WYXZ, 0, 0,{ { 90000, 85000, 112000 },{ 70000, 69000, 112000 },{ 50000, 48950, 56000 },{ 36400, 35600, 56000 } }, + { 256000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 90000, 85000, 112000 },{ 70000, 69000, 112000 },{ 50000, 48950, 56000 },{ 36400, 35600, 56000 } }, { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - { 256000, 0, 2, FB, 24000, 4, WYXZ, 0, 0,{ { 84650, 83000, 112000 },{ 65850, 64550, 56000 },{ 47000, 46100, 48000 },{ 28200, 27650, 40000 } }, + { 256000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 84650, 83000, 112000 },{ 65850, 64550, 56000 },{ 47000, 46100, 48000 },{ 28200, 27650, 40000 } }, { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - { 256000, 0, 3, FB, 24000, 4, WYXZ, 0, 0,{ { 76300, 73550, 112000 },{ 59350, 57200, 56000 },{ 42400, 40850, 48000 },{ 25450, 24500, 40000 } }, + { 256000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 76300, 73550, 112000 },{ 59350, 57200, 56000 },{ 42400, 40850, 48000 },{ 25450, 24500, 40000 } }, { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 31, 1, 1, 1 } }, 1, 2, 0 }, - { 384000, 0, 1, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 100000, 100000, 128000 },{ 79850, 79850, 104000 },{ 66600, 66600, 104000 } }, // not yet optimized + { 384000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 100000, 100000, 128000 },{ 79850, 79850, 104000 },{ 66600, 66600, 104000 } }, // not yet optimized { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - { 384000, 0, 2, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 105350, 103300, 112000 },{ 75200, 73750, 96000 },{ 45100, 44250, 48000 } }, // just added as a place holder, not necessarily operational + { 384000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 105350, 103300, 112000 },{ 75200, 73750, 96000 },{ 45100, 44250, 48000 } }, // just added as a place holder, not necessarily operational { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - { 384000, 0, 3, FB, 24000, 4, WYXZ, 0, 0,{ { 124300, 121550, 128000 },{ 96700, 94550, 112000 },{ 69050, 67500, 96000 },{ 41450, 40500, 48000 } }, // just added as a place holder, not necessarily operational + { 384000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 124300, 121550, 128000 },{ 96700, 94550, 112000 },{ 69050, 67500, 96000 },{ 41450, 40500, 48000 } }, // just added as a place holder, not necessarily operational { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - { 512000, 0, 1, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 }, {118450, 118450, 128000 } }, // not yet optimized + { 512000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 }, {118450, 118450, 128000 } }, // not yet optimized { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - { 512000, 0, 2, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 97700, 93300, 128000 } }, // not yet optimized + { 512000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 97700, 93300, 128000 } }, // not yet optimized { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - { 512000, 0, 3, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 127200, 122550, 128000 },{ 76300, 73550, 128000 } }, // not yet optimized + { 512000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 127200, 122550, 128000 },{ 76300, 73550, 128000 } }, // not yet optimized { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - }; -const ivas_arith_consts_t ivas_arith_consts[IVAS_SPAR_BR_TABLE_LEN][MAX_QUANT_STRATS] = + +const ivas_freq_models_t ivas_arith_pred_r_consts[TOTAL_PRED_QUANT_STRATS_ARITH] = { -#ifdef LBR_SBA - /* tbl_idx 0 -- 13.2kbps FOA */ + /* entry for 1 quantization points */ { - /* Quant strat = 0 */ + /* pred_R real */ { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, }, - /* Quant strat = 1 */ + /* pred_R real differential */ { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,327,778,1851,10472,1851,778,327, }, - { 0,1057,1630,2514,5982,2514,1630,1057, }, - { 0,1668,2572,6122,2572,1668,1081,701, }, - { 0,701,1081,1668,2572,6122,2572,1668, }, - }, - /* pred_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* pred_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, }, + /* pred_R real : values for general and differential */ + { 0 },{ 0 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 0 -- 16.4kbps FOA */ + /* entry for 7 quantization points for br_table_idx >= 2 */ { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ + /* pred_R real */ { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,546,1092,2184,8740,2184,1092,546, }, + { 0,1779,2116,2516,3562,2516,2116,1779, }, + { 0,1848,2614,5229,2614,1848,1307,924, }, + { 0,924,1307,1848,2614,5229,2614,1848, }, }, - /* Quant strat = 2 */ + /* pred_R real differential */ { - { - /* pred_R real */ - { - { 0,327,778,1851,10472,1851,778,327, }, - { 0,1057,1630,2514,5982,2514,1630,1057, }, - { 0,1668,2572,6122,2572,1668,1081,701, }, - { 0,701,1081,1668,2572,6122,2572,1668, }, - }, - /* pred_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* pred_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, }, }, + /* pred_R real : values for general and differential */ + { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 }, -#endif - /* tbl_idx 0 -- 24.4kbps FOA */ + /* entry for 15 quantization points for br_table_idx >= 2 */ { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,327,778,1851,10472,1851,778,327, }, - { 0,1057,1630,2514,5982,2514,1630,1057, }, - { 0,1668,2572,6122,2572,1668,1081,701, }, - { 0,701,1081,1668,2572,6122,2572,1668, }, - }, - /* pred_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* pred_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 1 -- 32kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,1,1,4,9,23,56,133,318,756,1799,10184,1799,756,318,133,56,23,9,4,1,1, }, - { 0,41,64,98,152,234,362,558,861,1329,2049,4888,2049,1329,861,558,362,234,152,98,64,41, }, - { 0,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64,41,26, }, - { 0,26,41,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 2 -- 48kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, - { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, - { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, - { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, - { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, - { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, - { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,546,1092,2184,8740,2184,1092,546, }, - { 0,1779,2116,2516,3562,2516,2116,1779, }, - { 0,1848,2614,5229,2614,1848,1307,924, }, - { 0,924,1307,1848,2614,5229,2614,1848, }, - }, - /* pred_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* pred_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 3 -- 64kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, - { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, - { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, - { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, - { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, - { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, - { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 4 -- 80kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, - { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, - { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, - { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, - { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, - { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, - { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd_R real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2 },{ -1,0,1 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 5 -- 96kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,573,722,909,1146,1444,1819,2292,2888,4591, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* drct_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* drct_R real : values for general and differential */ - { -4,-3,-2,-1,0,1,2,3,4 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10941,2734,1367,683,341,170,85,42,21, }, - { 0,6305,3150,2227,1575,1113,787,556,393,278, }, - { 0,1101,1388,1749,2203,3502,2203,1749,1388,1101, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* decd_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd_R real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 6 -- 128kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10941,2734,1367,683,341,170,85,42,21, }, - { 0,6305,3150,2227,1575,1113,787,556,393,278, }, - { 0,1101,1388,1749,2203,3502,2203,1749,1388,1101, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* decd_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,573,722,909,1146,1444,1819,2292,2888,4591, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* drct_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* drct_R real : values for general and differential */ - { -4,-3,-2,-1,0,1,2,3,4 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10983,2744,1372,686,343,171,85, }, - { 0,6573,3285,2322,1642,1161,821,580, }, - { 0,1603,2020,2546,4046,2546,2020,1603, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* decd_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6 },{ -3,-2,-1,0,1,2,3 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10983,2744,1372,686,343,171,85, }, - { 0,6573,3285,2322,1642,1161,821,580, }, - { 0,1603,2020,2546,4046,2546,2020,1603, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* decd_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6 },{ -3,-2,-1,0,1,2,3 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 7 -- 160kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,573,722,909,1146,1444,1819,2292,2888,4591, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* drct_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* drct_R real : values for general and differential */ - { -4,-3,-2,-1,0,1,2,3,4 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10941,2734,1367,683,341,170,85,42,21, }, - { 0,6305,3150,2227,1575,1113,787,556,393,278, }, - { 0,1101,1388,1749,2203,3502,2203,1749,1388,1101, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* decd_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10983,2744,1372,686,343,171,85, }, - { 0,6573,3285,2322,1642,1161,821,580, }, - { 0,1603,2020,2546,4046,2546,2020,1603, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* decd_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6 },{ -3,-2,-1,0,1,2,3 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 8 -- 192kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,573,722,909,1146,1444,1819,2292,2888,4591, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* drct_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* drct_R real : values for general and differential */ - { -4,-3,-2,-1,0,1,2,3,4 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10941,2734,1367,683,341,170,85,42,21, }, - { 0,6305,3150,2227,1575,1113,787,556,393,278, }, - { 0,1101,1388,1749,2203,3502,2203,1749,1388,1101, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* decd_R real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10983,2744,1372,686,343,171,85, }, - { 0,6573,3285,2322,1642,1161,821,580, }, - { 0,1603,2020,2546,4046,2546,2020,1603, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* decd_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6 },{ -3,-2,-1,0,1,2,3 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 9 -- 256kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 10 -- 256kbps HOA2 */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 11 -- 256kbps HOA3 */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ + /* pred_R real */ { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - }, - /* tbl_idx 12 -- 384kbps FOA */ - { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, + { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, + { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, + { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, + { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, + }, + /* pred_R real differential */ + { + { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, + { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, + { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, + { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, + }, + /* pred_R real : values for general and differential */ + { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, + { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 13 -- 384kbps HOA2 */ + /* entry for 21 quantization points for br_table_idx >= 2 */ { - /* Quant strat = 0 */ + /* pred_R real */ { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, + { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, + { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, + { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, }, - /* Quant strat = 2 */ + /* pred_R real differential */ { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, + { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, + { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, + { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, }, + /* pred_R real : values for general and differential */ + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 14 -- 384kbps HOA3 */ + /* entry for 31 quantization points */ { - /* Quant strat = 0 */ + /* pred real */ { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, + { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, + { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, + { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, } }, - /* Quant strat = 1 */ + /* pred real differential */ { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, + { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, + { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, + { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, } }, + /* pred real : values for general and differential */ + { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, + { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, + /* pred real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 15 -- 512kbps FOA */ + /* entry for 7 quantization points for br_table_idx < 2 */ { - /* Quant strat = 0 */ - { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 1 */ + /* pred_R real */ { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,327,778,1851,10472,1851,778,327, }, + { 0,1057,1630,2514,5982,2514,1630,1057, }, + { 0,1668,2572,6122,2572,1668,1081,701, }, + { 0,701,1081,1668,2572,6122,2572,1668, }, }, - /* Quant strat = 2 */ + /* pred_R real differential */ { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, }, }, + /* pred_R real : values for general and differential */ + { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 16 -- 512kbps HOA2 */ + /* entry for 15 quantization points for br_table_idx < 2 */ { - /* Quant strat = 0 */ + /* pred real */ { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, + { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, + { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, + { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, } }, - /* Quant strat = 1 */ + /* pred real differential */ { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, + { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, + { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, + { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, } }, + /* pred real : values for general and differential */ + {-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7}, + { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, + /* pred real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 17 -- 512kbps HOA3 */ + /* entry for 21 quantization points for br_table_idx < 2 */ { - /* Quant strat = 0 */ + /* pred_R real */ { - { - /* pred_R real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, }, - }, - /* pred_R real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct_R real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd_R real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd_R real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,1,1,4,9,23,56,133,318,756,1799,10184,1799,756,318,133,56,23,9,4,1,1, }, + { 0,41,64,98,152,234,362,558,861,1329,2049,4888,2049,1329,861,558,362,234,152,98,64,41, }, + { 0,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64,41,26, }, + { 0,26,41,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64, }, }, - /* Quant strat = 1 */ + /* pred_R real differential */ { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, - }, - /* Quant strat = 2 */ - { - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* drct_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct_R real : values for general and differential */ - { 0 },{ 0 }, - /* drct_R real : num dyn models for general and differential */ - 4, 4 - }, - { - /* decd_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd_R real : values for general and differential */ - { 0 },{ 0 }, - /* decd_R real : num dyn models for general and differential */ - 4, 4 - }, + { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, + { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, + { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, + { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, }, - }, - + /* pred_R real : values for general and differential */ + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 + } }; -const ivas_huff_consts_t ivas_huff_const[IVAS_SPAR_BR_TABLE_LEN][MAX_QUANT_STRATS] = +const ivas_freq_models_t ivas_arith_drct_r_consts[TOTAL_DRCT_QUANT_STRATS] = { -#ifdef LBR_SBA - /* tbl_idx 0 -- 13.2kbps FOA */ + /* entry for 1 quantization points */ { - /* Quant strat 0 */ + /* drct real */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, }, - /* Quant strat 1 */ + /* drct real differential */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, - }, - /* Quant strat 2 */ - { - { - /* pred_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* pred_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, }, + /* drct real : values for general and differential */ + {0},{ 0 }, + /* drct real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 0 -- 16.4kbps FOA */ - { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, - }, - /* Quant strat 1 */ + /* entry for 7 quantization points */ + { /* drct real */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,988,1244,1568,1976,2489,3136,4983, }, + { 0,2111,2262,2425,2788,2425,2262,2111, }, }, - /* Quant strat 2 */ + /* drct real differential */ { - { - /* pred_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* pred_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, }, }, + /* drct real : values for general and differential */ + { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, + /* drct real : num dyn models for general and differential */ + 4, 4 }, -#endif - /* tbl_idx 0 -- 24.4kbps FOA */ + /* entry for 9 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, - }, - /* Quant strat 1 */ + /* drct real */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,39,125,397,1263,12736,1263,397,125,39, }, + { 0,397,708,1262,2250,7150,2250,1262,708,397, }, + { 0,573,722,909,1146,1444,1819,2292,2888,4591, }, + { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, }, - /* Quant strat 2 */ + /* drct real differential */ { - { - /* pred_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* pred_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,39,125,397,1263,12736,1263,397,125,39, }, + { 0,397,708,1262,2250,7150,2250,1262,708,397, }, + { 0,716,1276,2274,7225,2274,1276,716,402,225, }, + { 0,225,402,716,1276,2274,7225,2274,1276,716, } }, + /* drct real : values for general and differential */ + { -4,-3,-2,-1,0,1,2,3,4 },{ -4,-3,-2,-1,0,1,2,3,4 }, + /* drct real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 1 -- 32kbps FOA */ + /* entry for 11 quantization points */ { - /* Quant strat 0 */ + /* drct real */ { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, + { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, + { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, + { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, + { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, }, - /* Quant strat 1 */ + /* drct real differential */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, + { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, + { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, + { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, + { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, }, - /* Quant strat 2 */ - { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, - }, - }, - /* tbl_idx 2 -- 48kbps FOA */ + /* drct real : values for general and differential */ + { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, + /* drct real : num dyn models for general and differential */ + 4, 4 + } +}; + +const ivas_freq_models_t ivas_arith_decd_r_consts[TOTAL_DECD_QUANT_STRATS] = +{ + /* entry for 1 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, - }, - /* Quant strat 1 */ + /* decd real */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, }, - /* Quant strat 2 */ + /* decd real differential */ { - { - /* pred_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* pred_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, }, + /* decd real : values for general and differential */ + { 0 },{ 0 }, + /* decd real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 3 -- 64kbps FOA */ + /* entry for 3 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, - }, - /* Quant strat 1 */ + /* decd real */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, + { 0,11917,2978,1489, }, + { 0,8840,4419,3125, }, + { 0,4567,7250,4567, }, + { 0,5203,5978,5203, }, }, - /* Quant strat 2 */ + /* decd real differential */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,1356,13672,1356, }, + { 0,3166,10052,3166, }, + { 0,10984,3459,1941, }, + { 0,1941,3459,10984, }, }, + /* decd real : values for general and differential */ + { 0,1,2 },{-1,0,1}, + /* decd real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 4 -- 80kbps FOA */ + /* entry for 5 quantization points */ { - /* Quant strat 0 */ + /* decd real */ { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, + { 0,11157,2788,1394,697,348, }, + { 0,7186,3592,2540,1796,1270, }, + { 0,2512,3166,5028,3166,2512, }, + { 0,3048,3267,3754,3267,3048, }, }, - /* Quant strat 1 */ + /* decd real differential */ { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, - }, - /* Quant strat 2 */ - { - { - /* pred_R codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - /* pred_R differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5,4,4 },{ -4,4,5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 },{ 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,2,2 },{ 1,1,0 },{ 2,2,3 }, }, - /* decd_R differential codebook */ - { { -1,2,2 },{ 0,1,0 },{ 1,2,3 }, }, - }, + { 0,406,1289,12994,1289,406, }, + { 0,1460,2601,8262,2601,1460, }, + { 0,2707,8599,2707,1519,852, }, + { 0,852,1519,2707,8599,2707, }, }, + /* decd real : values for general and differential */ + { 0,1,2,3,4 },{ -2,-1,0,1,2 }, + /* decd real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 5 -- 96kbps FOA */ + /* entry for 7 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - /* drct_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,14 },{ 1,3,0 },{ 2,3,1 },{ 3,3,2 },{ 4,3,3 },{ 5,3,4 },{ 6,3,5 },{ 7,3,6 },{ 8,4,15 }, }, - /* decd_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, - }, - /* Quant strat 1 */ + /* decd real */ { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, + { 0,10983,2744,1372,686,343,171,85, }, + { 0,6573,3285,2322,1642,1161,821,580, }, + { 0,1603,2020,2546,4046,2546,2020,1603, }, + { 0,2111,2262,2425,2788,2425,2262,2111, }, }, - /* Quant strat 2 */ + /* decd real differential */ { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 }, }, - /* decd_R differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 }, }, - }, + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, } }, + /* decd real : values for general and differential */ + { 0,1,2,3,4,5,6 },{ -3,-2,-1,0,1,2,3 }, + /* decd real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 6 -- 128kbps FOA */ - { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,14 },{ 1,3,0 },{ 2,3,1 },{ 3,3,2 },{ 4,3,3 },{ 5,3,4 },{ 6,3,5 },{ 7,3,6 },{ 8,4,15 }, }, - /* decd_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - /* drct_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,2,0 },{ 4,3,5 },{ 5,3,6 },{ 6,3,7 }, }, - /* decd_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - }, - /* Quant strat 2 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,2,0 },{ 4,3,5 },{ 5,3,6 },{ 6,3,7 }, }, - /* decd_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - }, + /* entry for 9 quantization points */ + { /* decd real */ + { + { 0,10941,2734,1367,683,341,170,85,42,21, }, + { 0,6305,3150,2227,1575,1113,787,556,393,278, }, + { 0,1101,1388,1749,2203,3502,2203,1749,1388,1101, }, + { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, + }, + /* decd real differential */ + { + { 0,39,125,397,1263,12736,1263,397,125,39, }, + { 0,397,708,1262,2250,7150,2250,1262,708,397, }, + { 0,716,1276,2274,7225,2274,1276,716,402,225, }, + { 0,225,402,716,1276,2274,7225,2274,1276,716, } + }, + /* decd real : values for general and differential */ + { 0,1,2,3,4,5,6,7,8 },{ -4,-3,-2,-1,0,1,2,3,4 }, + /* decd real : num dyn models for general and differential */ + 4, 4 }, - /* tbl_idx 7 -- 160kbps FOA */ + /* entry for 11 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ + /* decd real */ { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - /* drct_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,14 },{ 1,3,0 },{ 2,3,1 },{ 3,3,2 },{ 4,3,3 },{ 5,3,4 },{ 6,3,5 },{ 7,3,6 },{ 8,4,15 }, }, - /* decd_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, + { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, + { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, + { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, + { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, }, - /* Quant strat 2 */ + /* decd real differential */ { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,2,0 },{ 4,3,5 },{ 5,3,6 },{ 6,3,7 }, }, - /* decd_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, + { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, + { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, + { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, + { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, }, + /* decd real : values for general and differential */ + { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, + /* decd real : num dyn models for general and differential */ + 4, 4 + } +}; + +const ivas_huff_models_t ivas_huff_pred_r_consts[TOTAL_PRED_QUANT_STRATS_HUFF] = +{ + /* entry for 1 quantization points for br_table_idx */ + {{{ 0 }}, {{ 0 }}}, + /* entry for 7 quantization points for br_table_idx */ + { + /* pred_R codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, + /* pred_R differential codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, }, - /* tbl_idx 8 -- 192kbps FOA */ + /* entry for 15 quantization points for br_table_idx */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - /* drct_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,14 },{ 1,3,0 },{ 2,3,1 },{ 3,3,2 },{ 4,3,3 },{ 5,3,4 },{ 6,3,5 },{ 7,3,6 },{ 8,4,15 }, }, - /* decd_R differential codebook */ - { { -4,4,14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 }, }, - }, - }, - /* Quant strat 2 */ - { - { - /* pred_R codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - /* pred_R differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5,4,0 },{ -4,4,1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 },{ 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* drct_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - { - /* decd_R codebook */ - { { 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,2,0 },{ 4,3,5 },{ 5,3,6 },{ 6,3,7 }, }, - /* decd_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - }, + /* pred_r codebook */ + { { -7,4,2 },{ -6,4,3 },{ -5, 4, 4 },{ -4, 4, 5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 }, + { 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 } }, + /* pred_r differential codebook */ + { { -7,4,2 },{ -6,4,3 },{ -5, 4, 4 },{ -4, 4, 5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 }, + { 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 } }, }, - /* tbl_idx 9 -- 256kbps FOA */ + /* entry for 21 quantization points for br_table_idx=0 */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ -{ - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* pred_r codebook */ + { {-10,5,22},{-9,5,23},{-8,5,24},{-7,5,25},{-6,5,26}, { -5, 4, 0 },{ -4, 4, 1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 }, + { 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{6,5,27},{7,5,28},{8,5,29},{9,5,30},{10,5,31} }, + /* pred_r differential codebook */ + { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5, 4, 0 },{ -4, 4, 1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 }, + { 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 } }, }, - /* tbl_idx 10 -- 256kbps HOA2 */ + + /* entry for 31 quantization points for br_table_idx>0 */ + { + /* pred_r codebook */ + { {-15,5,2},{-14,5,3},{-13,5,4},{-12,5,5},{-11,5,6}, { -10,5,7 },{ -9,5,8 },{ -8,5,9 }, + { -7,5,10 },{ -6,5,11 },{ -5, 5, 12 },{ -4, 5, 13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 }, + { 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 }, + { 8,5,24 },{ 9,5,25 },{ 10,5,26 },{11,5,27},{12,5,28},{13,5,29},{14,5,30},{15,5,31} }, + /* pred_r differential codebook */ + { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 }, + { -7,5,10 },{ -6,5,11 },{ -5, 5, 12 },{ -4, 5, 13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 }, + { 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 }, + { 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 } }, + }, + }; + + const ivas_huff_models_t ivas_huff_drct_r_consts[TOTAL_DRCT_QUANT_STRATS] = +{ + /* entry for 1 quantization points */ + {{{ 0 }}, {{ 0 }}}, + /* entry for 7 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* drct_r codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, + /* drct_r differential codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, }, - /* tbl_idx 11 -- 256kbps HOA3 */ + /* entry for 9 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* drct_r codebook */ + { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, + /* drct_r differential codebook */ + { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, }, - /* tbl_idx 12 -- 384kbps FOA */ + /* entry for 11 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* drct_r codebook */ + { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, + /* drct_r differential codebook */ + { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, }, - /* tbl_idx 13 -- 384kbps HOA2 */ +}; + +const ivas_huff_models_t ivas_huff_decd_r_consts[TOTAL_DECD_QUANT_STRATS] = +{ + /* entry for 1 quantization points */ + {{{ 0 }}, {{ 0 }}}, + /* entry for 3 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* decd_r codebook */ + { { 0, 2, 2 },{ 1, 1, 0 },{ 2,2,3 } }, + /* decd_r differential codebook */ + { { -1, 2, 2 },{ 0, 1, 0 },{ 1,2,3 } }, }, - /* tbl_idx 14 -- 384kbps HOA3 */ + /* entry for 5 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* decd_r codebook */ + { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 } }, + /* decd_r differential codebook */ + { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 } }, }, - /* tbl_idx 15 -- 512kbps FOA */ + /* entry for 7 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 1 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* decd_r */ + { { 0, 3, 2 },{ 1, 3, 3 },{ 2,3,4 },{ 3,3,0 },{ 4,3,5 },{ 5,3,6 },{ 6,3,7 } }, + /* decd_r codebook differential codebook */ + { { -3, 3, 2 },{ -2, 3, 3 },{ -1,3,4 },{ 0,3,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, }, - /* tbl_idx 16 -- 512kbps HOA2 */ + /* entry for 9 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* decd_r codebook */ + { { 0, 4, 14 },{ 1,3,0 },{ 2,3,1 },{ 3,3,2 },{ 4,3,3 },{ 5,3,4 },{ 6,3,5 },{ 7,3,6 },{ 8,4,15 } }, + /* decd_r differential codebook */ + { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, }, - /* tbl_idx 17 -- 512kbps HOA3 */ + /* entry for 11 quantization points */ { - /* Quant strat 0 */ - { - { - /* pred_R codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - /* pred_R differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 },{ -7,5,10 },{ -6,5,11 },{ -5,5,12 },{ -4,5,13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 },{ 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 },{ 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 }, }, - }, - { - /* drct_R codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - /* drct_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - { - /* decd_R codebook */ - { { 0,4,10 },{ 1,4,11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 }, }, - /* decd_R differential codebook */ - { { -5,4,10 },{ -4,4,11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 }, }, - }, - }, - /* Quant strat 1 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, - /* Quant strat 2 */ - { - /* pred_R */ - {{{ 0 }}, {{ 0 }}}, - /* drct_R */ - {{{ 0 }}, {{ 0 }}}, - /* decd_R */ - {{{ 0 }}, {{ 0 }}}, - }, + /* decd_r codebook */ + { { 0, 4, 10 },{ 1, 4, 11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 } }, + /* decd_r differential codebook */ + { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, }, }; @@ -7174,7 +2749,7 @@ const uint8_t masa_twodir_bands[IVAS_NUM_ACTIVE_BRATES] = const uint8_t masa_twodir_bands_joined[IVAS_NUM_ACTIVE_BRATES] = { - 0, 0, 0, 0, 0, 2, 2, 3, 4, 6, 8, 9, 12, 18 + 0, 0, 0, 0, 0, 2, 2, 3, 4, 6, 8, 9, 12, MASA_MAXIMUM_TWO_DIR_BANDS }; @@ -7805,252 +3380,7 @@ const float ivas_mdft_coeff_cos_twid_960[IVAS_960_PT_LEN + 1] = 0.00000000000000000f }; -const float ivas_mdft_coeff_sin_twid_960[IVAS_960_PT_LEN] = -{ - 0.00000000000000f, 0.00163624544362405f, 0.00327248650652663f, 0.00490871880799799f, - 0.00654493796735186f, 0.00818113960393713f, 0.00981731933714962f, 0.0114534727864438f, - 0.0130895955713444f, 0.0147256833114585f, 0.0163617316264868f, 0.0179977361362355f, - 0.0196336924606283f, 0.0212695962197177f, 0.0229054430336971f, 0.0245412285229123f, - 0.0261769483078732f, 0.0278125980092656f, 0.0294481732479632f, 0.0310836696450387f, - 0.0327190828217761f, 0.0343544083996823f, 0.0359896420004984f, 0.0376247792462120f, - 0.0392598157590686f, 0.0408947471615835f, 0.0425295690765531f, 0.0441642771270674f, - 0.0457988669365208f, 0.0474333341286245f, 0.0490676743274180f, 0.0507018831572807f, - 0.0523359562429438f, 0.0539698892095019f, 0.0556036776824246f, 0.0572373172875686f, - 0.0588708036511890f, 0.0605041323999513f, 0.0621372991609427f, 0.0637702995616845f, - 0.0654031292301431f, 0.0670357837947420f, 0.0686682588843738f, 0.0703005501284112f, - 0.0719326531567194f, 0.0735645635996674f, 0.0751962770881399f, 0.0768277892535488f, - 0.0784590957278449f, 0.0800901921435301f, 0.0817210741336682f, 0.0833517373318975f, - 0.0849821773724417f, 0.0866123898901222f, 0.0882423705203695f, 0.0898721148992350f, - 0.0915016186634024f, 0.0931308774501998f, 0.0947598868976111f, 0.0963886426442878f, - 0.0980171403295606f, 0.0996453755934511f, 0.101273344076683f, 0.102901041420696f, - 0.104528463267653f, 0.106155605260457f, 0.107782463042759f, 0.109409032258971f, - 0.111035308554278f, 0.112661287574648f, 0.114286964966846f, 0.115912336378446f, - 0.117537397457838f, 0.119162143854244f, 0.120786571217731f, 0.122410675199216f, - 0.124034451450485f, 0.125657895624201f, 0.127281003373913f, 0.128903770354075f, - 0.130526192220052f, 0.132148264628130f, 0.133769983235535f, 0.135391343700438f, - 0.137012341681968f, 0.138632972840227f, 0.140253232836296f, 0.141873117332253f, - 0.143492621991179f, 0.145111742477173f, 0.146730474455362f, 0.148348813591913f, - 0.149966755554045f, 0.151584296010041f, 0.153201430629258f, 0.154818155082141f, - 0.156434465040231f, 0.158050356176180f, 0.159665824163761f, 0.161280864677880f, - 0.162895473394589f, 0.164509645991092f, 0.166123378145765f, 0.167736665538162f, - 0.169349503849025f, 0.170961888760301f, 0.172573815955152f, 0.174185281117962f, - 0.175796279934355f, 0.177406808091201f, 0.179016861276633f, 0.180626435180053f, - 0.182235525492147f, 0.183844127904898f, 0.185452238111591f, 0.187059851806832f, - 0.188666964686555f, 0.190273572448036f, 0.191879670789901f, 0.193485255412143f, - 0.195090322016128f, 0.196694866304610f, 0.198298883981740f, 0.199902370753082f, - 0.201505322325617f, 0.203107734407763f, 0.204709602709380f, 0.206310922941784f, - 0.207911690817759f, 0.209511902051569f, 0.211111552358965f, 0.212710637457203f, - 0.214309153065051f, 0.215907094902801f, 0.217504458692281f, 0.219101240156870f, - 0.220697435021501f, 0.222293039012681f, 0.223888047858498f, 0.225482457288634f, - 0.227076263034373f, 0.228669460828619f, 0.230262046405902f, 0.231854015502391f, - 0.233445363855905f, 0.235036087205927f, 0.236626181293610f, 0.238215641861795f, - 0.239804464655017f, 0.241392645419519f, 0.242980179903264f, 0.244567063855944f, - 0.246153293028993f, 0.247738863175598f, 0.249323770050712f, 0.250908009411060f, - 0.252491577015158f, 0.254074468623319f, 0.255656679997664f, 0.257238206902140f, - 0.258819045102521f, 0.260399190366428f, 0.261978638463337f, 0.263557385164591f, - 0.265135426243408f, 0.266712757474898f, 0.268289374636071f, 0.269865273505849f, - 0.271440449865074f, 0.273014899496527f, 0.274588618184932f, 0.276161601716971f, - 0.277733845881292f, 0.279305346468526f, 0.280876099271292f, 0.282446100084212f, - 0.284015344703923f, 0.285583828929082f, 0.287151548560387f, 0.288718499400580f, - 0.290284677254462f, 0.291850077928904f, 0.293414697232857f, 0.294978530977364f, - 0.296541574975571f, 0.298103825042740f, 0.299665276996257f, 0.301225926655644f, - 0.302785769842575f, 0.304344802380877f, 0.305903020096553f, 0.307460418817785f, - 0.309016994374947f, 0.310572742600619f, 0.312127659329594f, 0.313681740398891f, - 0.315234981647770f, 0.316787378917734f, 0.318338928052550f, 0.319889624898253f, - 0.321439465303162f, 0.322988445117886f, 0.324536560195342f, 0.326083806390759f, - 0.327630179561694f, 0.329175675568039f, 0.330720290272037f, 0.332264019538291f, - 0.333806859233771f, 0.335348805227832f, 0.336889853392220f, 0.338429999601086f, - 0.339969239730994f, 0.341507569660936f, 0.343044985272340f, 0.344581482449080f, - 0.346117057077493f, 0.347651705046382f, 0.349185422247033f, 0.350718204573223f, - 0.352250047921234f, 0.353780948189858f, 0.355310901280416f, 0.356839903096763f, - 0.358367949545300f, 0.359895036534988f, 0.361421159977355f, 0.362946315786509f, - 0.364470499879150f, 0.365993708174577f, 0.367515936594704f, 0.369037181064066f, - 0.370557437509836f, 0.372076701861829f, 0.373594970052516f, 0.375112238017038f, - 0.376628501693211f, 0.378143757021540f, 0.379657999945233f, 0.381171226410203f, - 0.382683432365090f, 0.384194613761262f, 0.385704766552831f, 0.387213886696666f, - 0.388721970152396f, 0.390229012882428f, 0.391735010851956f, 0.393239960028970f, - 0.394743856384267f, 0.396246695891466f, 0.397748474527011f, 0.399249188270190f, - 0.400748833103141f, 0.402247405010863f, 0.403744899981227f, 0.405241314004990f, - 0.406736643075800f, 0.408230883190212f, 0.409724030347695f, 0.411216080550645f, - 0.412707029804395f, 0.414196874117224f, 0.415685609500371f, 0.417173231968043f, - 0.418659737537428f, 0.420145122228702f, 0.421629382065045f, 0.423112513072644f, - 0.424594511280713f, 0.426075372721496f, 0.427555093430282f, 0.429033669445413f, - 0.430511096808295f, 0.431987371563412f, 0.433462489758331f, 0.434936447443717f, - 0.436409240673342f, 0.437880865504095f, 0.439351317995994f, 0.440820594212194f, - 0.442288690219001f, 0.443755602085881f, 0.445221325885468f, 0.446685857693580f, - 0.448149193589223f, 0.449611329654607f, 0.451072261975153f, 0.452531986639508f, - 0.453990499739547f, 0.455447797370393f, 0.456903875630421f, 0.458358730621271f, - 0.459812358447860f, 0.461264755218387f, 0.462715917044350f, 0.464165840040552f, - 0.465614520325111f, 0.467061954019477f, 0.468508137248431f, 0.469953066140108f, - 0.471396736825998f, 0.472839145440959f, 0.474280288123229f, 0.475720161014437f, - 0.477158760259608f, 0.478596082007181f, 0.480032122409011f, 0.481466877620387f, - 0.482900343800037f, 0.484332517110141f, 0.485763393716340f, 0.487192969787746f, - 0.488621241496955f, 0.490048205020053f, 0.491473856536628f, 0.492898192229784f, - 0.494321208286145f, 0.495742900895868f, 0.497163266252654f, 0.498582300553759f, - 0.500000000000000f, 0.501416360795769f, 0.502831379149042f, 0.504245051271389f, - 0.505657373377985f, 0.507068341687617f, 0.508477952422700f, 0.509886201809281f, - 0.511293086077052f, 0.512698601459362f, 0.514102744193222f, 0.515505510519320f, - 0.516906896682028f, 0.518306898929413f, 0.519705513513249f, 0.521102736689023f, - 0.522498564715949f, 0.523892993856974f, 0.525286020378792f, 0.526677640551852f, - 0.528067850650368f, 0.529456646952329f, 0.530844025739509f, 0.532229983297479f, - 0.533614515915612f, 0.534997619887097f, 0.536379291508950f, 0.537759527082020f, - 0.539138322911000f, 0.540515675304440f, 0.541891580574752f, 0.543266035038224f, - 0.544639035015027f, 0.546010576829228f, 0.547380656808797f, 0.548749271285616f, - 0.550116416595493f, 0.551482089078169f, 0.552846285077328f, 0.554209000940606f, - 0.555570233019602f, 0.556929977669889f, 0.558288231251022f, 0.559644990126546f, - 0.561000250664010f, 0.562354009234973f, 0.563706262215017f, 0.565057005983753f, - 0.566406236924833f, 0.567753951425961f, 0.569100145878898f, 0.570444816679478f, - 0.571787960227612f, 0.573129572927301f, 0.574469651186643f, 0.575808191417845f, - 0.577145190037234f, 0.578480643465260f, 0.579814548126514f, 0.581146900449730f, - 0.582477696867802f, 0.583806933817786f, 0.585134607740916f, 0.586460715082607f, - 0.587785252292473f, 0.589108215824328f, 0.590429602136201f, 0.591749407690343f, - 0.593067628953237f, 0.594384262395609f, 0.595699304492433f, 0.597012751722948f, - 0.598324600570659f, 0.599634847523352f, 0.600943489073102f, 0.602250521716282f, - 0.603555941953571f, 0.604859746289968f, 0.606161931234795f, 0.607462493301711f, - 0.608761429008721f, 0.610058734878182f, 0.611354407436817f, 0.612648443215719f, - 0.613940838750366f, 0.615231590580627f, 0.616520695250769f, 0.617808149309472f, - 0.619093949309834f, 0.620378091809381f, 0.621660573370077f, 0.622941390558334f, - 0.624220539945018f, 0.625498018105461f, 0.626773821619470f, 0.628047947071334f, - 0.629320391049838f, 0.630591150148264f, 0.631860220964409f, 0.633127600100588f, - 0.634393284163646f, 0.635657269764965f, 0.636919553520476f, 0.638180132050665f, - 0.639439001980585f, 0.640696159939861f, 0.641951602562703f, 0.643205326487914f, - 0.644457328358897f, 0.645707604823667f, 0.646956152534857f, 0.648202968149730f, - 0.649448048330184f, 0.650691389742765f, 0.651932989058674f, 0.653172842953777f, - 0.654410948108610f, 0.655647301208395f, 0.656881898943041f, 0.658114738007160f, - 0.659345815100069f, 0.660575126925805f, 0.661802670193130f, 0.663028441615542f, - 0.664252437911282f, 0.665474655803342f, 0.666695092019479f, 0.667913743292216f, - 0.669130606358858f, 0.670345677961497f, 0.671558954847018f, 0.672770433767117f, - 0.673980111478298f, 0.675187984741891f, 0.676394050324054f, 0.677598304995789f, - 0.678800745532942f, 0.680001368716218f, 0.681200171331188f, 0.682397150168297f, - 0.683592302022871f, 0.684785623695130f, 0.685977111990193f, 0.687166763718086f, - 0.688354575693754f, 0.689540544737067f, 0.690724667672829f, 0.691906941330786f, - 0.693087362545636f, 0.694265928157036f, 0.695442635009612f, 0.696617479952964f, - 0.697790459841680f, 0.698961571535339f, 0.700130811898524f, 0.701298177800824f, - 0.702463666116852f, 0.703627273726243f, 0.704788997513670f, 0.705948834368849f, - 0.707106781186548f, 0.708262834866593f, 0.709416992313883f, 0.710569250438390f, - 0.711719606155171f, 0.712868056384380f, 0.714014598051268f, 0.715159228086199f, - 0.716301943424654f, 0.717442741007240f, 0.718581617779698f, 0.719718570692913f, - 0.720853596702919f, 0.721986692770910f, 0.723117855863248f, 0.724247082951467f, - 0.725374371012288f, 0.726499717027620f, 0.727623117984575f, 0.728744570875469f, - 0.729864072697836f, 0.730981620454432f, 0.732097211153246f, 0.733210841807505f, - 0.734322509435686f, 0.735432211061519f, 0.736539943713999f, 0.737645704427393f, - 0.738749490241246f, 0.739851298200392f, 0.740951125354959f, 0.742048968760379f, - 0.743144825477394f, 0.744238692572067f, 0.745330567115786f, 0.746420446185274f, - 0.747508326862597f, 0.748594206235171f, 0.749678081395770f, 0.750759949442534f, - 0.751839807478977f, 0.752917652613995f, 0.753993481961869f, 0.755067292642284f, - 0.756139081780323f, 0.757208846506485f, 0.758276583956687f, 0.759342291272275f, - 0.760405965600031f, 0.761467604092177f, 0.762527203906388f, 0.763584762205796f, - 0.764640276159000f, 0.765693742940071f, 0.766745159728561f, 0.767794523709512f, - 0.768841832073460f, 0.769887082016445f, 0.770930270740018f, 0.771971395451250f, - 0.773010453362737f, 0.774047441692607f, 0.775082357664531f, 0.776115198507728f, - 0.777145961456971f, 0.778174643752598f, 0.779201242640517f, 0.780225755372213f, - 0.781248179204759f, 0.782268511400816f, 0.783286749228650f, 0.784302889962131f, - 0.785316930880745f, 0.786328869269598f, 0.787338702419428f, 0.788346427626606f, - 0.789352042193150f, 0.790355543426726f, 0.791356928640660f, 0.792356195153942f, - 0.793353340291235f, 0.794348361382881f, 0.795341255764910f, 0.796332020779044f, - 0.797320653772707f, 0.798307152099032f, 0.799291513116864f, 0.800273734190774f, - 0.801253812691061f, 0.802231745993758f, 0.803207531480645f, 0.804181166539250f, - 0.805152648562858f, 0.806121974950521f, 0.807089143107059f, 0.808054150443073f, - 0.809016994374948f, 0.809977672324859f, 0.810936181720784f, 0.811892519996505f, - 0.812846684591615f, 0.813798672951530f, 0.814748482527489f, 0.815696110776568f, - 0.816641555161679f, 0.817584813151584f, 0.818525882220897f, 0.819464759850093f, - 0.820401443525514f, 0.821335930739376f, 0.822268218989775f, 0.823198305780696f, - 0.824126188622016f, 0.825051865029513f, 0.825975332524873f, 0.826896588635696f, - 0.827815630895502f, 0.828732456843738f, 0.829647064025785f, 0.830559449992965f, - 0.831469612302545f, 0.832377548517748f, 0.833283256207754f, 0.834186732947712f, - 0.835087976318743f, 0.835986983907947f, 0.836883753308409f, 0.837778282119209f, - 0.838670567945424f, 0.839560608398136f, 0.840448401094438f, 0.841333943657443f, - 0.842217233716287f, 0.843098268906135f, 0.843977046868193f, 0.844853565249707f, - 0.845727821703973f, 0.846599813890344f, 0.847469539474234f, 0.848336996127127f, - 0.849202181526579f, 0.850065093356229f, 0.850925729305802f, 0.851784087071117f, - 0.852640164354092f, 0.853493958862750f, 0.854345468311227f, 0.855194690419775f, - 0.856041622914771f, 0.856886263528723f, 0.857728610000272f, 0.858568660074204f, - 0.859406411501453f, 0.860241862039105f, 0.861075009450407f, 0.861905851504774f, - 0.862734385977792f, 0.863560610651224f, 0.864384523313017f, 0.865206121757311f, - 0.866025403784439f, 0.866842367200935f, 0.867657009819544f, 0.868469329459222f, - 0.869279323945144f, 0.870086991108711f, 0.870892328787557f, 0.871695334825548f, - 0.872496007072797f, 0.873294343385663f, 0.874090341626759f, 0.874883999664958f, - 0.875675315375400f, 0.876464286639493f, 0.877250911344924f, 0.878035187385663f, - 0.878817112661965f, 0.879596685080383f, 0.880373902553765f, 0.881148763001268f, - 0.881921264348355f, 0.882691404526809f, 0.883459181474733f, 0.884224593136556f, - 0.884987637463042f, 0.885748312411291f, 0.886506615944746f, 0.887262546033203f, - 0.888016100652807f, 0.888767277786068f, 0.889516075421856f, 0.890262491555416f, - 0.891006524188368f, 0.891748171328711f, 0.892487430990834f, 0.893224301195515f, - 0.893958779969932f, 0.894690865347664f, 0.895420555368697f, 0.896147848079432f, - 0.896872741532688f, 0.897595233787707f, 0.898315322910159f, 0.899033006972149f, - 0.899748284052221f, 0.900461152235364f, 0.901171609613013f, 0.901879654283062f, - 0.902585284349861f, 0.903288497924226f, 0.903989293123443f, 0.904687668071273f, - 0.905383620897955f, 0.906077149740215f, 0.906768252741266f, 0.907456928050819f, - 0.908143173825081f, 0.908826988226768f, 0.909508369425101f, 0.910187315595818f, - 0.910863824921176f, 0.911537895589956f, 0.912209525797468f, 0.912878713745555f, - 0.913545457642601f, 0.914209755703531f, 0.914871606149819f, 0.915531007209492f, - 0.916187957117136f, 0.916842454113898f, 0.917494496447491f, 0.918144082372204f, - 0.918791210148898f, 0.919435878045019f, 0.920078084334595f, 0.920717827298248f, - 0.921355105223192f, 0.921989916403245f, 0.922622259138823f, 0.923252131736957f, - 0.923879532511287f, 0.924504459782072f, 0.925126911876195f, 0.925746887127164f, - 0.926364383875118f, 0.926979400466833f, 0.927591935255724f, 0.928201986601852f, - 0.928809552871924f, 0.929414632439304f, 0.930017223684012f, 0.930617324992729f, - 0.931214934758804f, 0.931810051382254f, 0.932402673269775f, 0.932992798834739f, - 0.933580426497202f, 0.934165554683908f, 0.934748181828292f, 0.935328306370488f, - 0.935905926757326f, 0.936481041442343f, 0.937053648885784f, 0.937623747554606f, - 0.938191335922484f, 0.938756412469813f, 0.939318975683713f, 0.939879024058033f, - 0.940436556093355f, 0.940991570296997f, 0.941544065183021f, 0.942094039272230f, - 0.942641491092178f, 0.943186419177173f, 0.943728822068278f, 0.944268698313317f, - 0.944806046466878f, 0.945340865090320f, 0.945873152751771f, 0.946402908026138f, - 0.946930129495106f, 0.947454815747144f, 0.947976965377510f, 0.948496576988253f, - 0.949013649188214f, 0.949528180593037f, 0.950040169825165f, 0.950549615513851f, - 0.951056516295154f, 0.951560870811948f, 0.952062677713924f, 0.952561935657595f, - 0.953058643306297f, 0.953552799330193f, 0.954044402406280f, 0.954533451218389f, - 0.955019944457187f, 0.955503880820186f, 0.955985259011744f, 0.956464077743065f, - 0.956940335732209f, 0.957414031704088f, 0.957885164390477f, 0.958353732530011f, - 0.958819734868193f, 0.959283170157394f, 0.959744037156857f, 0.960202334632705f, - 0.960658061357935f, 0.961111216112432f, 0.961561797682962f, 0.962009804863184f, - 0.962455236453647f, 0.962898091261798f, 0.963338368101980f, 0.963776065795440f, - 0.964211183170329f, 0.964643719061708f, 0.965073672311547f, 0.965501041768733f, - 0.965925826289068f, 0.966348024735277f, 0.966767635977008f, 0.967184658890834f, - 0.967599092360260f, 0.968010935275723f, 0.968420186534595f, 0.968826845041188f, - 0.969230909706754f, 0.969632379449491f, 0.970031253194544f, 0.970427529874007f, - 0.970821208426928f, 0.971212287799312f, 0.971600766944121f, 0.971986644821279f, - 0.972369920397677f, 0.972750592647168f, 0.973128660550580f, 0.973504123095711f, - 0.973876979277334f, 0.974247228097201f, 0.974614868564045f, 0.974979899693582f, - 0.975342320508513f, 0.975702130038529f, 0.976059327320311f, 0.976413911397535f, - 0.976765881320872f, 0.977115236147994f, 0.977461974943572f, 0.977806096779282f, - 0.978147600733806f, 0.978486485892835f, 0.978822751349072f, 0.979156396202234f, - 0.979487419559051f, 0.979815820533276f, 0.980141598245680f, 0.980464751824058f, - 0.980785280403230f, 0.981103183125046f, 0.981418459138384f, 0.981731107599154f, - 0.982041127670304f, 0.982348518521816f, 0.982653279330712f, 0.982955409281056f, - 0.983254907563955f, 0.983551773377562f, 0.983846005927077f, 0.984137604424753f, - 0.984426568089892f, 0.984712896148850f, 0.984996587835043f, 0.985277642388941f, - 0.985556059058078f, 0.985831837097047f, 0.986104975767509f, 0.986375474338188f, - 0.986643332084879f, 0.986908548290446f, 0.987171122244825f, 0.987431053245027f, - 0.987688340595138f, 0.987942983606322f, 0.988194981596825f, 0.988444333891970f, - 0.988691039824167f, 0.988935098732911f, 0.989176509964781f, 0.989415272873448f, - 0.989651386819670f, 0.989884851171301f, 0.990115665303286f, 0.990343828597665f, - 0.990569340443577f, 0.990792200237260f, 0.991012407382049f, 0.991229961288385f, - 0.991444861373810f, 0.991657107062973f, 0.991866697787626f, 0.992073632986633f, - 0.992277912105967f, 0.992479534598710f, 0.992678499925058f, 0.992874807552322f, - 0.993068456954926f, 0.993259447614414f, 0.993447779019444f, 0.993633450665799f, - 0.993816462056378f, 0.993996812701206f, 0.994174502117428f, 0.994349529829318f, - 0.994521895368273f, 0.994691598272820f, 0.994858638088611f, 0.995023014368432f, - 0.995184726672197f, 0.995343774566954f, 0.995500157626885f, 0.995653875433303f, - 0.995804927574662f, 0.995953313646548f, 0.996099033251687f, 0.996242085999945f, - 0.996382471508325f, 0.996520189400975f, 0.996655239309180f, 0.996787620871373f, - 0.996917333733128f, 0.997044377547164f, 0.997168751973348f, 0.997290456678690f, - 0.997409491337352f, 0.997525855630641f, 0.997639549247016f, 0.997750571882084f, - 0.997858923238604f, 0.997964603026487f, 0.998067610962796f, 0.998167946771749f, - 0.998265610184716f, 0.998360600940223f, 0.998452918783950f, 0.998542563468736f, - 0.998629534754574f, 0.998713832408616f, 0.998795456205172f, 0.998874405925711f, - 0.998950681358860f, 0.999024282300407f, 0.999095208553300f, 0.999163459927649f, - 0.999229036240723f, 0.999291937316955f, 0.999352162987941f, 0.999409713092437f, - 0.999464587476366f, 0.999516785992811f, 0.999566308502021f, 0.999613154871411f, - 0.999657324975557f, 0.999698818696204f, 0.999737635922260f, 0.999773776549800f, - 0.999807240482065f, 0.999838027629461f, 0.999866137909562f, 0.999891571247108f, - 0.999914327574007f, 0.999934406829333f, 0.999951808959328f, 0.999966533917401f, - 0.999978581664129f, 0.999987952167257f, 0.999994645401697f, 0.999998661349528f -}; - - -const float ivas_mdft_coeff_cos_twid_640[IVAS_640_PT_LEN +1] = +const float ivas_mdft_coeff_cos_twid_640[IVAS_640_PT_LEN + 1] = { 1.00000000000000f, 0.999996988037278f, 0.999987952167257f, 0.999972892444367f, 0.999951808959328f, 0.999924701839145f, 0.999891571247108f, 0.999852417382795f, @@ -8211,172 +3541,8 @@ const float ivas_mdft_coeff_cos_twid_640[IVAS_640_PT_LEN +1] = 0.0392598157590687f, 0.0368072229413588f, 0.0343544083996823f, 0.0319013869096110f, 0.0294481732479634f, 0.0269947821927155f, 0.0245412285229123f, 0.0220875270185784f, 0.0196336924606283f, 0.0171797396307788f, 0.0147256833114584f, 0.0122715382857199f, - 0.00981731933714973f, 0.00736304124977978f, 0.00490871880799808f, 0.00245436679646048f - ,0.00000000000000000f -}; - -const float ivas_mdft_coeff_sin_twid_640[IVAS_640_PT_LEN] = -{ - 0.00000000000000f, 0.00245436679646029f, 0.00490871880799799f, 0.00736304124977957f, - 0.00981731933714962f, 0.0122715382857199f, 0.0147256833114585f, 0.0171797396307787f, - 0.0196336924606283f, 0.0220875270185783f, 0.0245412285229123f, 0.0269947821927154f, - 0.0294481732479632f, 0.0319013869096109f, 0.0343544083996823f, 0.0368072229413588f, - 0.0392598157590686f, 0.0417121720785753f, 0.0441642771270674f, 0.0466161161332467f, - 0.0490676743274180f, 0.0515189369415775f, 0.0539698892095019f, 0.0564205163668375f, - 0.0588708036511890f, 0.0613207363022086f, 0.0637702995616845f, 0.0662194786736303f, - 0.0686682588843738f, 0.0711166254426453f, 0.0735645635996674f, 0.0760120586092431f, - 0.0784590957278449f, 0.0809056602147038f, 0.0833517373318975f, 0.0857973123444399f, - 0.0882423705203695f, 0.0906868971308382f, 0.0931308774501998f, 0.0955742967560992f, - 0.0980171403295606f, 0.100459393455076f, 0.102901041420696f, 0.105342069518114f, - 0.107782463042759f, 0.110222207293883f, 0.112661287574648f, 0.115099689192216f, - 0.117537397457838f, 0.119974397686940f, 0.122410675199216f, 0.124846215318711f, - 0.127281003373913f, 0.129715024697841f, 0.132148264628130f, 0.134580708507126f, - 0.137012341681968f, 0.139443149504679f, 0.141873117332253f, 0.144302230526747f, - 0.146730474455362f, 0.149157834490539f, 0.151584296010041f, 0.154009844397046f, - 0.156434465040231f, 0.158858143333861f, 0.161280864677880f, 0.163702614477995f, - 0.166123378145765f, 0.168543141098691f, 0.170961888760301f, 0.173379606560240f, - 0.175796279934355f, 0.178211894324786f, 0.180626435180053f, 0.183039887955141f, - 0.185452238111591f, 0.187863471117585f, 0.190273572448036f, 0.192682527584672f, - 0.195090322016128f, 0.197496941238030f, 0.199902370753082f, 0.202306596071156f, - 0.204709602709380f, 0.207111376192219f, 0.209511902051569f, 0.211911165826842f, - 0.214309153065051f, 0.216705849320900f, 0.219101240156870f, 0.221495311143304f, - 0.223888047858498f, 0.226279435888785f, 0.228669460828619f, 0.231058108280671f, - 0.233445363855905f, 0.235831213173673f, 0.238215641861795f, 0.240598635556650f, - 0.242980179903264f, 0.245360260555389f, 0.247738863175598f, 0.250115973435366f, - 0.252491577015158f, 0.254865659604515f, 0.257238206902140f, 0.259609204615985f, - 0.261978638463337f, 0.264346494170904f, 0.266712757474898f, 0.269077414121127f, - 0.271440449865074f, 0.273801850471989f, 0.276161601716971f, 0.278519689385053f, - 0.280876099271292f, 0.283230817180850f, 0.285583828929082f, 0.287935120341621f, - 0.290284677254462f, 0.292632485514050f, 0.294978530977364f, 0.297322799511998f, - 0.299665276996257f, 0.302005949319228f, 0.304344802380877f, 0.306681822092128f, - 0.309016994374947f, 0.311350305162432f, 0.313681740398891f, 0.316011286039934f, - 0.318338928052550f, 0.320664652415197f, 0.322988445117886f, 0.325310292162263f, - 0.327630179561694f, 0.329948093341349f, 0.332264019538291f, 0.334577944201551f, - 0.336889853392220f, 0.339199733183530f, 0.341507569660936f, 0.343813348922205f, - 0.346117057077493f, 0.348418680249435f, 0.350718204573223f, 0.353015616196696f, - 0.355310901280416f, 0.357604045997758f, 0.359895036534988f, 0.362183859091351f, - 0.364470499879150f, 0.366754945123831f, 0.369037181064066f, 0.371317193951838f, - 0.373594970052516f, 0.375870495644949f, 0.378143757021541f, 0.380414740488332f, - 0.382683432365090f, 0.384949818985382f, 0.387213886696666f, 0.389475621860365f, - 0.391735010851956f, 0.393992040061048f, 0.396246695891466f, 0.398498964761330f, - 0.400748833103141f, 0.402996287363860f, 0.405241314004990f, 0.407483899502658f, - 0.409724030347695f, 0.411961693045722f, 0.414196874117224f, 0.416429560097637f, - 0.418659737537428f, 0.420887393002174f, 0.423112513072644f, 0.425335084344881f, - 0.427555093430282f, 0.429772526955677f, 0.431987371563412f, 0.434199613911428f, - 0.436409240673342f, 0.438616238538528f, 0.440820594212194f, 0.443022294415467f, - 0.445221325885468f, 0.447417675375397f, 0.449611329654607f, 0.451802275508688f, - 0.453990499739547f, 0.456175989165483f, 0.458358730621271f, 0.460538710958240f, - 0.462715917044350f, 0.464890335764274f, 0.467061954019477f, 0.469230758728290f, - 0.471396736825998f, 0.473559875264908f, 0.475720161014437f, 0.477877581061184f, - 0.480032122409011f, 0.482183772079123f, 0.484332517110141f, 0.486478344558187f, - 0.488621241496955f, 0.490761195017794f, 0.492898192229784f, 0.495032220259813f, - 0.497163266252654f, 0.499291317371047f, 0.501416360795769f, 0.503538383725718f, - 0.505657373377985f, 0.507773316987935f, 0.509886201809281f, 0.511996015114162f, - 0.514102744193222f, 0.516206376355680f, 0.518306898929413f, 0.520404299261031f, - 0.522498564715949f, 0.524589682678469f, 0.526677640551852f, 0.528762425758396f, - 0.530844025739509f, 0.532922427955790f, 0.534997619887097f, 0.537069589032630f, - 0.539138322911000f, 0.541203809060310f, 0.543266035038224f, 0.545324988422047f, - 0.547380656808796f, 0.549433027815281f, 0.551482089078169f, 0.553527828254070f, - 0.555570233019602f, 0.557609291071472f, 0.559644990126546f, 0.561677317921925f, - 0.563706262215017f, 0.565731810783613f, 0.567753951425961f, 0.569772671960834f, - 0.571787960227612f, 0.573799804086349f, 0.575808191417845f, 0.577813110123727f, - 0.579814548126514f, 0.581812493369691f, 0.583806933817786f, 0.585797857456439f, - 0.587785252292473f, 0.589769106353971f, 0.591749407690343f, 0.593726144372402f, - 0.595699304492433f, 0.597668876164268f, 0.599634847523352f, 0.601597206726822f, - 0.603555941953571f, 0.605511041404326f, 0.607462493301711f, 0.609410285890327f, - 0.611354407436817f, 0.613294846229936f, 0.615231590580627f, 0.617164628822086f, - 0.619093949309834f, 0.621019540421789f, 0.622941390558334f, 0.624859488142386f, - 0.626773821619470f, 0.628684379457781f, 0.630591150148264f, 0.632494122204672f, - 0.634393284163646f, 0.636288624584773f, 0.638180132050665f, 0.640067795167023f, - 0.641951602562703f, 0.643831542889792f, 0.645707604823667f, 0.647579777063073f, - 0.649448048330184f, 0.651312407370671f, 0.653172842953777f, 0.655029343872374f, - 0.656881898943041f, 0.658730497006124f, 0.660575126925805f, 0.662415777590172f, - 0.664252437911282f, 0.666085096825230f, 0.667913743292216f, 0.669738366296610f, - 0.671558954847018f, 0.673375497976352f, 0.675187984741890f, 0.676996404225348f, - 0.678800745532942f, 0.680600997795453f, 0.682397150168297f, 0.684189191831585f, - 0.685977111990193f, 0.687760899873822f, 0.689540544737067f, 0.691316035859480f, - 0.693087362545636f, 0.694854514125194f, 0.696617479952964f, 0.698376249408973f, - 0.700130811898524f, 0.701881156852263f, 0.703627273726243f, 0.705369152001986f, - 0.707106781186548f, 0.708840150812579f, 0.710569250438390f, 0.712294069648014f, - 0.714014598051268f, 0.715730825283819f, 0.717442741007240f, 0.719150334909079f, - 0.720853596702919f, 0.722552516128436f, 0.724247082951467f, 0.725937286964068f, - 0.727623117984575f, 0.729304565857668f, 0.730981620454432f, 0.732654271672413f, - 0.734322509435686f, 0.735986323694910f, 0.737645704427393f, 0.739300641637149f, - 0.740951125354959f, 0.742597145638433f, 0.744238692572067f, 0.745875756267305f, - 0.747508326862597f, 0.749136394523459f, 0.750759949442534f, 0.752378981839648f, - 0.753993481961869f, 0.755603440083571f, 0.757208846506485f, 0.758809691559762f, - 0.760405965600031f, 0.761997659011457f, 0.763584762205797f, 0.765167265622459f, - 0.766745159728562f, 0.768318435018988f, 0.769887082016445f, 0.771451091271519f, - 0.773010453362737f, 0.774565158896617f, 0.776115198507728f, 0.777660562858748f, - 0.779201242640517f, 0.780737228572095f, 0.782268511400816f, 0.783795081902349f, - 0.785316930880745f, 0.786834049168500f, 0.788346427626606f, 0.789854057144609f, - 0.791356928640660f, 0.792855033061574f, 0.794348361382882f, 0.795836904608884f, - 0.797320653772707f, 0.798799599936358f, 0.800273734190774f, 0.801743047655881f, - 0.803207531480645f, 0.804667176843123f, 0.806121974950521f, 0.807571917039243f, - 0.809016994374948f, 0.810457198252595f, 0.811892519996505f, 0.813322950960406f, - 0.814748482527489f, 0.816169106110459f, 0.817584813151584f, 0.818995595122750f, - 0.820401443525514f, 0.821802349891147f, 0.823198305780696f, 0.824589302785025f, - 0.825975332524873f, 0.827356386650900f, 0.828732456843738f, 0.830103534814044f, - 0.831469612302545f, 0.832830681080094f, 0.834186732947712f, 0.835537759736646f, - 0.836883753308409f, 0.838224705554838f, 0.839560608398136f, 0.840891453790923f, - 0.842217233716286f, 0.843537940187827f, 0.844853565249707f, 0.846164100976699f, - 0.847469539474234f, 0.848769872878448f, 0.850065093356229f, 0.851355193105265f, - 0.852640164354092f, 0.853919999362139f, 0.855194690419775f, 0.856464229848356f, - 0.857728610000272f, 0.858987823258990f, 0.860241862039105f, 0.861490718786378f, - 0.862734385977792f, 0.863972856121587f, 0.865206121757311f, 0.866434175455865f, - 0.867657009819544f, 0.868874617482086f, 0.870086991108711f, 0.871294123396174f, - 0.872496007072797f, 0.873692634898524f, 0.874883999664958f, 0.876070094195407f, - 0.877250911344924f, 0.878426444000357f, 0.879596685080383f, 0.880761627535558f, - 0.881921264348355f, 0.883075588533209f, 0.884224593136556f, 0.885368271236879f, - 0.886506615944746f, 0.887639620402854f, 0.888767277786068f, 0.889889581301463f, - 0.891006524188368f, 0.892118099718401f, 0.893224301195515f, 0.894325121956035f, - 0.895420555368697f, 0.896510594834693f, 0.897595233787707f, 0.898674465693954f, - 0.899748284052221f, 0.900816682393908f, 0.901879654283062f, 0.902937193316419f, - 0.903989293123443f, 0.905035947366364f, 0.906077149740215f, 0.907112893972869f, - 0.908143173825081f, 0.909167983090522f, 0.910187315595818f, 0.911201165200584f, - 0.912209525797468f, 0.913212391312179f, 0.914209755703531f, 0.915201612963474f, - 0.916187957117136f, 0.917168782222852f, 0.918144082372204f, 0.919113851690058f, - 0.920078084334595f, 0.921036774497350f, 0.921989916403245f, 0.922937504310623f, - 0.923879532511287f, 0.924815995330528f, 0.925746887127164f, 0.926672202293573f, - 0.927591935255724f, 0.928506080473216f, 0.929414632439304f, 0.930317585680942f, - 0.931214934758804f, 0.932106674267327f, 0.932992798834739f, 0.933873303123092f, - 0.934748181828292f, 0.935617429680138f, 0.936481041442343f, 0.937339011912575f, - 0.938191335922484f, 0.939038008337734f, 0.939879024058033f, 0.940714378017165f, - 0.941544065183021f, 0.942368080557626f, 0.943186419177173f, 0.943999076112052f, - 0.944806046466878f, 0.945607325380521f, 0.946402908026138f, 0.947192789611197f, - 0.947976965377510f, 0.948755430601262f, 0.949528180593037f, 0.950295210697844f, - 0.951056516295154f, 0.951812092798916f, 0.952561935657595f, 0.953306040354194f, - 0.954044402406280f, 0.954777017366017f, 0.955503880820186f, 0.956224988390216f, - 0.956940335732209f, 0.957649918536965f, 0.958353732530011f, 0.959051773471624f, - 0.959744037156857f, 0.960430519415566f, 0.961111216112432f, 0.961786123146989f, - 0.962455236453647f, 0.963118552001719f, 0.963776065795440f, 0.964427773873996f, - 0.965073672311547f, 0.965713757217249f, 0.966348024735277f, 0.966976471044852f, - 0.967599092360260f, 0.968215884930876f, 0.968826845041188f, 0.969431969010818f, - 0.970031253194544f, 0.970624693982323f, 0.971212287799312f, 0.971794031105889f, - 0.972369920397677f, 0.972939952205560f, 0.973504123095711f, 0.974062429669605f, - 0.974614868564045f, 0.975161436451181f, 0.975702130038529f, 0.976236946068990f, - 0.976765881320873f, 0.977288932607910f, 0.977806096779282f, 0.978317370719628f, - 0.978822751349072f, 0.979322235623241f, 0.979815820533276f, 0.980303503105861f, - 0.980785280403230f, 0.981261149523195f, 0.981731107599154f, 0.982195151800116f, - 0.982653279330712f, 0.983105487431216f, 0.983551773377562f, 0.983992134481354f, - 0.984426568089892f, 0.984855071586178f, 0.985277642388941f, 0.985694277952645f, - 0.986104975767509f, 0.986509733359519f, 0.986908548290446f, 0.987301418157858f, - 0.987688340595138f, 0.988069313271492f, 0.988444333891970f, 0.988813400197476f, - 0.989176509964781f, 0.989533661006540f, 0.989884851171301f, 0.990230078343521f, - 0.990569340443577f, 0.990902635427780f, 0.991229961288385f, 0.991551316053606f, - 0.991866697787626f, 0.992176104590609f, 0.992479534598710f, 0.992776985984091f, - 0.993068456954926f, 0.993353945755417f, 0.993633450665799f, 0.993906970002356f, - 0.994174502117428f, 0.994436045399422f, 0.994691598272820f, 0.994941159198190f, - 0.995184726672197f, 0.995422299227608f, 0.995653875433303f, 0.995879453894286f, - 0.996099033251687f, 0.996312612182778f, 0.996520189400975f, 0.996721763655847f, - 0.996917333733128f, 0.997106898454717f, 0.997290456678690f, 0.997468007299307f, - 0.997639549247016f, 0.997805081488460f, 0.997964603026487f, 0.998118112900149f, - 0.998265610184716f, 0.998407093991674f, 0.998542563468736f, 0.998672017799843f, - 0.998795456205172f, 0.998912877941140f, 0.999024282300407f, 0.999129668611881f, - 0.999229036240723f, 0.999322384588350f, 0.999409713092437f, 0.999491021226926f, - 0.999566308502021f, 0.999635574464198f, 0.999698818696204f, 0.999756040817060f, - 0.999807240482065f, 0.999852417382795f, 0.999891571247108f, 0.999924701839145f, - 0.999951808959328f, 0.999972892444367f, 0.999987952167257f, 0.999996988037278f + 0.00981731933714973f, 0.00736304124977978f, 0.00490871880799808f, 0.00245436679646048f, + 0.00000000000000000f }; const float ivas_mdft_coeff_cos_twid_320[IVAS_320_PT_LEN + 1] = @@ -8460,92 +3626,8 @@ const float ivas_mdft_coeff_cos_twid_320[IVAS_320_PT_LEN + 1] = 0.0784590957278450f, 0.0735645635996675f, 0.0686682588843738f, 0.0637702995616845f, 0.0588708036511890f, 0.0539698892095020f, 0.0490676743274181f, 0.0441642771270675f, 0.0392598157590687f, 0.0343544083996823f, 0.0294481732479634f, 0.0245412285229123f, - 0.0196336924606283f, 0.0147256833114584f, 0.00981731933714973f, 0.00490871880799808f - ,0.0000000000000000f -}; - -const float ivas_mdft_coeff_sin_twid_320[IVAS_320_PT_LEN] = -{ - 0.00000000000000f, 0.00490871880799799f, 0.00981731933714962f, 0.0147256833114585f, - 0.0196336924606283f, 0.0245412285229123f, 0.0294481732479632f, 0.0343544083996823f, - 0.0392598157590686f, 0.0441642771270674f, 0.0490676743274180f, 0.0539698892095019f, - 0.0588708036511890f, 0.0637702995616845f, 0.0686682588843738f, 0.0735645635996674f, - 0.0784590957278449f, 0.0833517373318975f, 0.0882423705203695f, 0.0931308774501998f, - 0.0980171403295606f, 0.102901041420696f, 0.107782463042759f, 0.112661287574648f, - 0.117537397457838f, 0.122410675199216f, 0.127281003373913f, 0.132148264628130f, - 0.137012341681968f, 0.141873117332253f, 0.146730474455362f, 0.151584296010041f, - 0.156434465040231f, 0.161280864677880f, 0.166123378145765f, 0.170961888760301f, - 0.175796279934355f, 0.180626435180053f, 0.185452238111591f, 0.190273572448036f, - 0.195090322016128f, 0.199902370753082f, 0.204709602709380f, 0.209511902051569f, - 0.214309153065051f, 0.219101240156870f, 0.223888047858498f, 0.228669460828619f, - 0.233445363855905f, 0.238215641861795f, 0.242980179903264f, 0.247738863175598f, - 0.252491577015158f, 0.257238206902140f, 0.261978638463337f, 0.266712757474898f, - 0.271440449865074f, 0.276161601716971f, 0.280876099271292f, 0.285583828929082f, - 0.290284677254462f, 0.294978530977364f, 0.299665276996257f, 0.304344802380877f, - 0.309016994374947f, 0.313681740398891f, 0.318338928052550f, 0.322988445117886f, - 0.327630179561694f, 0.332264019538291f, 0.336889853392220f, 0.341507569660936f, - 0.346117057077493f, 0.350718204573223f, 0.355310901280416f, 0.359895036534988f, - 0.364470499879150f, 0.369037181064066f, 0.373594970052516f, 0.378143757021541f, - 0.382683432365090f, 0.387213886696666f, 0.391735010851956f, 0.396246695891466f, - 0.400748833103141f, 0.405241314004990f, 0.409724030347695f, 0.414196874117224f, - 0.418659737537428f, 0.423112513072644f, 0.427555093430282f, 0.431987371563412f, - 0.436409240673342f, 0.440820594212194f, 0.445221325885468f, 0.449611329654607f, - 0.453990499739547f, 0.458358730621271f, 0.462715917044350f, 0.467061954019477f, - 0.471396736825998f, 0.475720161014437f, 0.480032122409011f, 0.484332517110141f, - 0.488621241496955f, 0.492898192229784f, 0.497163266252654f, 0.501416360795769f, - 0.505657373377985f, 0.509886201809281f, 0.514102744193222f, 0.518306898929413f, - 0.522498564715949f, 0.526677640551852f, 0.530844025739509f, 0.534997619887097f, - 0.539138322911000f, 0.543266035038224f, 0.547380656808796f, 0.551482089078169f, - 0.555570233019602f, 0.559644990126546f, 0.563706262215017f, 0.567753951425961f, - 0.571787960227612f, 0.575808191417845f, 0.579814548126514f, 0.583806933817786f, - 0.587785252292473f, 0.591749407690343f, 0.595699304492433f, 0.599634847523352f, - 0.603555941953571f, 0.607462493301711f, 0.611354407436817f, 0.615231590580627f, - 0.619093949309834f, 0.622941390558334f, 0.626773821619470f, 0.630591150148264f, - 0.634393284163646f, 0.638180132050665f, 0.641951602562703f, 0.645707604823667f, - 0.649448048330184f, 0.653172842953777f, 0.656881898943041f, 0.660575126925805f, - 0.664252437911282f, 0.667913743292216f, 0.671558954847018f, 0.675187984741890f, - 0.678800745532942f, 0.682397150168297f, 0.685977111990193f, 0.689540544737067f, - 0.693087362545636f, 0.696617479952964f, 0.700130811898524f, 0.703627273726243f, - 0.707106781186548f, 0.710569250438390f, 0.714014598051268f, 0.717442741007240f, - 0.720853596702919f, 0.724247082951467f, 0.727623117984575f, 0.730981620454432f, - 0.734322509435686f, 0.737645704427393f, 0.740951125354959f, 0.744238692572067f, - 0.747508326862597f, 0.750759949442534f, 0.753993481961869f, 0.757208846506485f, - 0.760405965600031f, 0.763584762205797f, 0.766745159728562f, 0.769887082016445f, - 0.773010453362737f, 0.776115198507728f, 0.779201242640517f, 0.782268511400816f, - 0.785316930880745f, 0.788346427626606f, 0.791356928640660f, 0.794348361382882f, - 0.797320653772707f, 0.800273734190774f, 0.803207531480645f, 0.806121974950521f, - 0.809016994374948f, 0.811892519996505f, 0.814748482527489f, 0.817584813151584f, - 0.820401443525514f, 0.823198305780696f, 0.825975332524873f, 0.828732456843738f, - 0.831469612302545f, 0.834186732947712f, 0.836883753308409f, 0.839560608398136f, - 0.842217233716286f, 0.844853565249707f, 0.847469539474234f, 0.850065093356229f, - 0.852640164354092f, 0.855194690419775f, 0.857728610000272f, 0.860241862039105f, - 0.862734385977792f, 0.865206121757311f, 0.867657009819544f, 0.870086991108711f, - 0.872496007072797f, 0.874883999664958f, 0.877250911344924f, 0.879596685080383f, - 0.881921264348355f, 0.884224593136556f, 0.886506615944746f, 0.888767277786068f, - 0.891006524188368f, 0.893224301195515f, 0.895420555368697f, 0.897595233787707f, - 0.899748284052221f, 0.901879654283062f, 0.903989293123443f, 0.906077149740215f, - 0.908143173825081f, 0.910187315595818f, 0.912209525797468f, 0.914209755703531f, - 0.916187957117136f, 0.918144082372204f, 0.920078084334595f, 0.921989916403245f, - 0.923879532511287f, 0.925746887127164f, 0.927591935255724f, 0.929414632439304f, - 0.931214934758804f, 0.932992798834739f, 0.934748181828292f, 0.936481041442343f, - 0.938191335922484f, 0.939879024058033f, 0.941544065183021f, 0.943186419177173f, - 0.944806046466878f, 0.946402908026138f, 0.947976965377510f, 0.949528180593037f, - 0.951056516295154f, 0.952561935657595f, 0.954044402406280f, 0.955503880820186f, - 0.956940335732209f, 0.958353732530011f, 0.959744037156857f, 0.961111216112432f, - 0.962455236453647f, 0.963776065795440f, 0.965073672311547f, 0.966348024735277f, - 0.967599092360260f, 0.968826845041188f, 0.970031253194544f, 0.971212287799312f, - 0.972369920397677f, 0.973504123095711f, 0.974614868564045f, 0.975702130038529f, - 0.976765881320873f, 0.977806096779282f, 0.978822751349072f, 0.979815820533276f, - 0.980785280403230f, 0.981731107599154f, 0.982653279330712f, 0.983551773377562f, - 0.984426568089892f, 0.985277642388941f, 0.986104975767509f, 0.986908548290446f, - 0.987688340595138f, 0.988444333891970f, 0.989176509964781f, 0.989884851171301f, - 0.990569340443577f, 0.991229961288385f, 0.991866697787626f, 0.992479534598710f, - 0.993068456954926f, 0.993633450665799f, 0.994174502117428f, 0.994691598272820f, - 0.995184726672197f, 0.995653875433303f, 0.996099033251687f, 0.996520189400975f, - 0.996917333733128f, 0.997290456678690f, 0.997639549247016f, 0.997964603026487f, - 0.998265610184716f, 0.998542563468736f, 0.998795456205172f, 0.999024282300407f, - 0.999229036240723f, 0.999409713092437f, 0.999566308502021f, 0.999698818696204f, - 0.999807240482065f, 0.999891571247108f, 0.999951808959328f, 0.999987952167257f + 0.0196336924606283f, 0.0147256833114584f, 0.00981731933714973f, 0.00490871880799808f, + 0.0000000000000000f }; const float ivas_mdft_coeff_cos_twid_240[IVAS_240_PT_LEN + 1] = @@ -8592,51 +3674,6 @@ const float ivas_mdft_coeff_cos_twid_240[IVAS_240_PT_LEN + 1] = 0.0392598158f, 0.0327190828f, 0.0261769483f, 0.0196336925f, 0.0130895956f, 0.0065449380f, 0.000000000f }; - -const float ivas_mdft_coeff_sin_twid_240[IVAS_240_PT_LEN] = -{ - 0.0000000000f, 0.0065449380f, 0.0130895956f, 0.0196336925f, 0.0261769483f, 0.0327190828f, - 0.0392598158f, 0.0457988669f, 0.0523359562f, 0.0588708037f, 0.0654031292f, 0.0719326532f, - 0.0784590957f, 0.0849821774f, 0.0915016187f, 0.0980171403f, 0.1045284633f, 0.1110353086f, - 0.1175373975f, 0.1240344515f, 0.1305261922f, 0.1370123417f, 0.1434926220f, 0.1499667556f, - 0.1564344650f, 0.1628954734f, 0.1693495038f, 0.1757962799f, 0.1822355255f, 0.1886669647f, - 0.1950903220f, 0.2015053223f, 0.2079116908f, 0.2143091531f, 0.2206974350f, 0.2270762630f, - 0.2334453639f, 0.2398044647f, 0.2461532930f, 0.2524915770f, 0.2588190451f, 0.2651354262f, - 0.2714404499f, 0.2777338459f, 0.2840153447f, 0.2902846773f, 0.2965415750f, 0.3027857698f, - 0.3090169944f, 0.3152349816f, 0.3214394653f, 0.3276301796f, 0.3338068592f, 0.3399692397f, - 0.3461170571f, 0.3522500479f, 0.3583679495f, 0.3644704999f, 0.3705574375f, 0.3766285017f, - 0.3826834324f, 0.3887219702f, 0.3947438564f, 0.4007488331f, 0.4067366431f, 0.4127070298f, - 0.4186597375f, 0.4245945113f, 0.4305110968f, 0.4364092407f, 0.4422886902f, 0.4481491936f, - 0.4539904997f, 0.4598123584f, 0.4656145203f, 0.4713967368f, 0.4771587603f, 0.4829003438f, - 0.4886212415f, 0.4943212083f, 0.5000000000f, 0.5056573734f, 0.5112930861f, 0.5169068967f, - 0.5224985647f, 0.5280678507f, 0.5336145159f, 0.5391383229f, 0.5446390350f, 0.5501164166f, - 0.5555702330f, 0.5610002507f, 0.5664062369f, 0.5717879602f, 0.5771451900f, 0.5824776969f, - 0.5877852523f, 0.5930676290f, 0.5983246006f, 0.6035559420f, 0.6087614290f, 0.6139408388f, - 0.6190939493f, 0.6242205399f, 0.6293203910f, 0.6343932842f, 0.6394390020f, 0.6444573284f, - 0.6494480483f, 0.6544109481f, 0.6593458151f, 0.6642524379f, 0.6691306064f, 0.6739801115f, - 0.6788007455f, 0.6835923020f, 0.6883545757f, 0.6930873625f, 0.6977904598f, 0.7024636661f, - 0.7071067812f, 0.7117196062f, 0.7163019434f, 0.7208535967f, 0.7253743710f, 0.7298640727f, - 0.7343225094f, 0.7387494902f, 0.7431448255f, 0.7475083269f, 0.7518398075f, 0.7561390818f, - 0.7604059656f, 0.7646402762f, 0.7688418321f, 0.7730104534f, 0.7771459615f, 0.7812481792f, - 0.7853169309f, 0.7893520422f, 0.7933533403f, 0.7973206538f, 0.8012538127f, 0.8051526486f, - 0.8090169944f, 0.8128466846f, 0.8166415552f, 0.8204014435f, 0.8241261886f, 0.8278156309f, - 0.8314696123f, 0.8350879763f, 0.8386705679f, 0.8422172337f, 0.8457278217f, 0.8492021815f, - 0.8526401644f, 0.8560416229f, 0.8594064115f, 0.8627343860f, 0.8660254038f, 0.8692793239f, - 0.8724960071f, 0.8756753154f, 0.8788171127f, 0.8819212643f, 0.8849876375f, 0.8880161007f, - 0.8910065242f, 0.8939587800f, 0.8968727415f, 0.8997482841f, 0.9025852843f, 0.9053836209f, - 0.9081431738f, 0.9108638249f, 0.9135454576f, 0.9161879571f, 0.9187912101f, 0.9213551052f, - 0.9238795325f, 0.9263643839f, 0.9288095529f, 0.9312149348f, 0.9335804265f, 0.9359059268f, - 0.9381913359f, 0.9404365561f, 0.9426414911f, 0.9448060465f, 0.9469301295f, 0.9490136492f, - 0.9510565163f, 0.9530586433f, 0.9550199445f, 0.9569403357f, 0.9588197349f, 0.9606580614f, - 0.9624552365f, 0.9642111832f, 0.9659258263f, 0.9675990924f, 0.9692309097f, 0.9708212084f, - 0.9723699204f, 0.9738769793f, 0.9753423205f, 0.9767658813f, 0.9781476007f, 0.9794874196f, - 0.9807852804f, 0.9820411277f, 0.9832549076f, 0.9844265681f, 0.9855560591f, 0.9866433321f, - 0.9876883406f, 0.9886910398f, 0.9896513868f, 0.9905693404f, 0.9914448614f, 0.9922779121f, - 0.9930684570f, 0.9938164621f, 0.9945218954f, 0.9951847267f, 0.9958049276f, 0.9963824715f, - 0.9969173337f, 0.9974094913f, 0.9978589232f, 0.9982656102f, 0.9986295348f, 0.9989506814f, - 0.9992290362f, 0.9994645875f, 0.9996573250f, 0.9998072405f, 0.9999143276f, 0.9999785817f -}; - const float ivas_mdft_coeff_cos_twid_160[IVAS_160_PT_LEN + 1] = { 1.0000000000f, 0.9999518090f, 0.9998072405f, 0.9995663085f, 0.9992290362f, 0.9987954562f, @@ -8668,37 +3705,6 @@ const float ivas_mdft_coeff_cos_twid_160[IVAS_160_PT_LEN + 1] = 0.0392598158f, 0.0294481732f, 0.0196336925f, 0.0098173193f, 0.000000000f }; -const float ivas_mdft_coeff_sin_twid_160[IVAS_160_PT_LEN] = -{ - 0.0000000000f, 0.0098173193f, 0.0196336925f, 0.0294481732f, 0.0392598158f, 0.0490676743f, - 0.0588708037f, 0.0686682589f, 0.0784590957f, 0.0882423705f, 0.0980171403f, 0.1077824630f, - 0.1175373975f, 0.1272810034f, 0.1370123417f, 0.1467304745f, 0.1564344650f, 0.1661233781f, - 0.1757962799f, 0.1854522381f, 0.1950903220f, 0.2047096027f, 0.2143091531f, 0.2238880479f, - 0.2334453639f, 0.2429801799f, 0.2524915770f, 0.2619786385f, 0.2714404499f, 0.2808760993f, - 0.2902846773f, 0.2996652770f, 0.3090169944f, 0.3183389281f, 0.3276301796f, 0.3368898534f, - 0.3461170571f, 0.3553109013f, 0.3644704999f, 0.3735949701f, 0.3826834324f, 0.3917350109f, - 0.4007488331f, 0.4097240303f, 0.4186597375f, 0.4275550934f, 0.4364092407f, 0.4452213259f, - 0.4539904997f, 0.4627159170f, 0.4713967368f, 0.4800321224f, 0.4886212415f, 0.4971632663f, - 0.5056573734f, 0.5141027442f, 0.5224985647f, 0.5308440257f, 0.5391383229f, 0.5473806568f, - 0.5555702330f, 0.5637062622f, 0.5717879602f, 0.5798145481f, 0.5877852523f, 0.5956993045f, - 0.6035559420f, 0.6113544074f, 0.6190939493f, 0.6267738216f, 0.6343932842f, 0.6419516026f, - 0.6494480483f, 0.6568818989f, 0.6642524379f, 0.6715589548f, 0.6788007455f, 0.6859771120f, - 0.6930873625f, 0.7001308119f, 0.7071067812f, 0.7140145981f, 0.7208535967f, 0.7276231180f, - 0.7343225094f, 0.7409511254f, 0.7475083269f, 0.7539934820f, 0.7604059656f, 0.7667451597f, - 0.7730104534f, 0.7792012426f, 0.7853169309f, 0.7913569286f, 0.7973206538f, 0.8032075315f, - 0.8090169944f, 0.8147484825f, 0.8204014435f, 0.8259753325f, 0.8314696123f, 0.8368837533f, - 0.8422172337f, 0.8474695395f, 0.8526401644f, 0.8577286100f, 0.8627343860f, 0.8676570098f, - 0.8724960071f, 0.8772509113f, 0.8819212643f, 0.8865066159f, 0.8910065242f, 0.8954205554f, - 0.8997482841f, 0.9039892931f, 0.9081431738f, 0.9122095258f, 0.9161879571f, 0.9200780843f, - 0.9238795325f, 0.9275919353f, 0.9312149348f, 0.9347481818f, 0.9381913359f, 0.9415440652f, - 0.9448060465f, 0.9479769654f, 0.9510565163f, 0.9540444024f, 0.9569403357f, 0.9597440372f, - 0.9624552365f, 0.9650736723f, 0.9675990924f, 0.9700312532f, 0.9723699204f, 0.9746148686f, - 0.9767658813f, 0.9788227513f, 0.9807852804f, 0.9826532793f, 0.9844265681f, 0.9861049758f, - 0.9876883406f, 0.9891765100f, 0.9905693404f, 0.9918666978f, 0.9930684570f, 0.9941745021f, - 0.9951847267f, 0.9960990333f, 0.9969173337f, 0.9976395492f, 0.9982656102f, 0.9987954562f, - 0.9992290362f, 0.9995663085f, 0.9998072405f, 0.9999518090f -}; - const float ivas_mdft_coeff_cos_twid_80[IVAS_80_PT_LEN + 1] = { 1.0000000000f, 0.9998072405f, 0.9992290362f, 0.9982656102f, 0.9969173337f, 0.9951847267f, @@ -8717,24 +3723,6 @@ const float ivas_mdft_coeff_cos_twid_80[IVAS_80_PT_LEN + 1] = 0.0392598158f, 0.0196336925f, 0.000000000f }; -const float ivas_mdft_coeff_sin_twid_80[IVAS_80_PT_LEN] = -{ - 0.0000000000f, 0.0196336925f, 0.0392598158f, 0.0588708037f, 0.0784590957f, 0.0980171403f, - 0.1175373975f, 0.1370123417f, 0.1564344650f, 0.1757962799f, 0.1950903220f, 0.2143091531f, - 0.2334453639f, 0.2524915770f, 0.2714404499f, 0.2902846773f, 0.3090169944f, 0.3276301796f, - 0.3461170571f, 0.3644704999f, 0.3826834324f, 0.4007488331f, 0.4186597375f, 0.4364092407f, - 0.4539904997f, 0.4713967368f, 0.4886212415f, 0.5056573734f, 0.5224985647f, 0.5391383229f, - 0.5555702330f, 0.5717879602f, 0.5877852523f, 0.6035559420f, 0.6190939493f, 0.6343932842f, - 0.6494480483f, 0.6642524379f, 0.6788007455f, 0.6930873625f, 0.7071067812f, 0.7208535967f, - 0.7343225094f, 0.7475083269f, 0.7604059656f, 0.7730104534f, 0.7853169309f, 0.7973206538f, - 0.8090169944f, 0.8204014435f, 0.8314696123f, 0.8422172337f, 0.8526401644f, 0.8627343860f, - 0.8724960071f, 0.8819212643f, 0.8910065242f, 0.8997482841f, 0.9081431738f, 0.9161879571f, - 0.9238795325f, 0.9312149348f, 0.9381913359f, 0.9448060465f, 0.9510565163f, 0.9569403357f, - 0.9624552365f, 0.9675990924f, 0.9723699204f, 0.9767658813f, 0.9807852804f, 0.9844265681f, - 0.9876883406f, 0.9905693404f, 0.9930684570f, 0.9951847267f, 0.9969173337f, 0.9982656102f, - 0.9992290362f, 0.9998072405f -}; - const float ivas_mdft_coeff_cos_twid_40[IVAS_40_PT_LEN + 1] = { 1.0000000000f, 0.9992290362f, 0.9969173337f, 0.9930684570f, 0.9876883406f, 0.9807852804f, @@ -8746,17 +3734,6 @@ const float ivas_mdft_coeff_cos_twid_40[IVAS_40_PT_LEN + 1] = 0.1564344650f, 0.1175373975f, 0.0784590957f, 0.0392598158f, 0.000000000f }; -const float ivas_mdft_coeff_sin_twid_40[IVAS_40_PT_LEN] = -{ - 0.0000000000f, 0.0392598158f, 0.0784590957f, 0.1175373975f, 0.1564344650f, 0.1950903220f, - 0.2334453639f, 0.2714404499f, 0.3090169944f, 0.3461170571f, 0.3826834324f, 0.4186597375f, - 0.4539904997f, 0.4886212415f, 0.5224985647f, 0.5555702330f, 0.5877852523f, 0.6190939493f, - 0.6494480483f, 0.6788007455f, 0.7071067812f, 0.7343225094f, 0.7604059656f, 0.7853169309f, - 0.8090169944f, 0.8314696123f, 0.8526401644f, 0.8724960071f, 0.8910065242f, 0.9081431738f, - 0.9238795325f, 0.9381913359f, 0.9510565163f, 0.9624552365f, 0.9723699204f, 0.9807852804f, - 0.9876883406f, 0.9930684570f, 0.9969173337f, 0.9992290362f -}; - const float ivas_sin_twiddle_480[IVAS_480_PT_LEN >> 1] = { -0.000818122995607253f, -0.00736304124977957f, -0.0139076440957708f, -0.0204516511845773f, diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 1415ae9f3e4233f3c7905d54837e47958e913a49..a095c9e4b48846d125154bbd3d6cba22e7a49549 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,6 @@ #include "options.h" #include "cnst.h" #include "ivas_cnst.h" -#include "typedef.h" #include "stat_com.h" #include "ivas_stat_com.h" #ifdef DEBUGGING @@ -170,9 +169,13 @@ extern const int16_t DirAC_block_grouping_5ms_MDFT[MAX_PARAM_SPATIAL_SUBFRAMES + * SPAR ROM tables *------------------------------------------------------------------------------------------*/ +extern const ivas_freq_models_t ivas_arith_pred_r_consts[TOTAL_PRED_QUANT_STRATS_ARITH]; +extern const ivas_freq_models_t ivas_arith_drct_r_consts[TOTAL_DRCT_QUANT_STRATS]; +extern const ivas_freq_models_t ivas_arith_decd_r_consts[TOTAL_DECD_QUANT_STRATS]; +extern const ivas_huff_models_t ivas_huff_pred_r_consts[TOTAL_PRED_QUANT_STRATS_HUFF]; +extern const ivas_huff_models_t ivas_huff_drct_r_consts[TOTAL_DRCT_QUANT_STRATS]; +extern const ivas_huff_models_t ivas_huff_decd_r_consts[TOTAL_DECD_QUANT_STRATS]; extern const ivas_spar_br_table_t ivas_spar_br_table_consts[IVAS_SPAR_BR_TABLE_LEN]; -extern const ivas_arith_consts_t ivas_arith_consts[IVAS_SPAR_BR_TABLE_LEN][MAX_QUANT_STRATS]; -extern const ivas_huff_consts_t ivas_huff_const[IVAS_SPAR_BR_TABLE_LEN][MAX_QUANT_STRATS]; extern const int16_t remix_order_set[1][IVAS_SPAR_MAX_CH]; extern const int16_t keep_planar[IVAS_SPAR_MAX_CH - FOA_CHANNELS]; extern const int16_t HOA_keep_ind[IVAS_SPAR_MAX_CH]; @@ -315,6 +318,7 @@ extern const float McMASA_LFEGain_vectors[64]; extern const float ism_azimuth_borders[4]; extern const float ism_elevation_borders[4]; + /*----------------------------------------------------------------------------------* * Param ISM ROM tables *----------------------------------------------------------------------------------*/ @@ -359,21 +363,12 @@ extern const float ivas_cos_twiddle_80[IVAS_80_PT_LEN >> 1]; *------------------------------------------------------------------------------------------*/ extern const float ivas_mdft_coeff_cos_twid_240[IVAS_240_PT_LEN + 1]; -extern const float ivas_mdft_coeff_sin_twid_240[IVAS_240_PT_LEN]; extern const float ivas_mdft_coeff_cos_twid_160[IVAS_160_PT_LEN + 1]; -extern const float ivas_mdft_coeff_sin_twid_160[IVAS_160_PT_LEN]; extern const float ivas_mdft_coeff_cos_twid_80[IVAS_80_PT_LEN + 1]; -extern const float ivas_mdft_coeff_sin_twid_80[IVAS_80_PT_LEN]; extern const float ivas_mdft_coeff_cos_twid_40[IVAS_40_PT_LEN + 1]; -extern const float ivas_mdft_coeff_sin_twid_40[IVAS_40_PT_LEN]; - extern const float ivas_mdft_coeff_cos_twid_960[IVAS_960_PT_LEN + 1]; -extern const float ivas_mdft_coeff_sin_twid_960[IVAS_960_PT_LEN]; extern const float ivas_mdft_coeff_cos_twid_640[IVAS_640_PT_LEN + 1]; -extern const float ivas_mdft_coeff_sin_twid_640[IVAS_640_PT_LEN]; extern const float ivas_mdft_coeff_cos_twid_320[IVAS_320_PT_LEN + 1]; -extern const float ivas_mdft_coeff_sin_twid_320[IVAS_320_PT_LEN]; - extern const int16_t dirac_gains_P_idx[16]; extern const float dirac_gains_norm_term[9]; extern const float dirac_gains_Pnm[91][9]; diff --git a/lib_com/ivas_sba_config.c b/lib_com/ivas_sba_config.c index 3755e68bc1fc5da23e2f970078007b2528300da5..1dc3c4faede2b8aae704c8f3c40a759fcd753ec3 100644 --- a/lib_com/ivas_sba_config.c +++ b/lib_com/ivas_sba_config.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -54,12 +54,15 @@ *-------------------------------------------------------------------*/ /*! r: SBA format mode */ -int16_t ivas_sba_mode_select( +SBA_MODE ivas_sba_mode_select( +#ifndef LBR_SBA const int32_t ivas_total_brate /* i : IVAS total bitrate */ +#endif ) { - SBA_MODE sba_mode; #ifndef LBR_SBA + SBA_MODE sba_mode; + if ( ivas_total_brate == IVAS_13k2 || ivas_total_brate == IVAS_16k4 ) { sba_mode = SBA_MODE_DIRAC; @@ -68,17 +71,12 @@ int16_t ivas_sba_mode_select( { sba_mode = SBA_MODE_SPAR; } -#else - int16_t filler; - filler = ivas_total_brate == 0; - sba_mode = SBA_MODE_SPAR; - -#endif return sba_mode; +#else + return SBA_MODE_SPAR; +#endif } - - /*-------------------------------------------------------------------* * ivas_sba_config() * @@ -93,8 +91,7 @@ void ivas_sba_config( const int16_t sba_planar, /* i : SBA Planar flag */ int16_t *nSCE, /* o : number of SCEs */ int16_t *nCPE, /* o : number of CPEs */ - int16_t *element_mode, /* o : element mode of the core coder */ - const SBA_MODE sba_mode /* i : SBA mode */ + int16_t *element_mode /* o : element mode of the core coder */ ) { if ( ( sba_order < 0 ) && ( nb_channels < 0 ) ) @@ -123,14 +120,7 @@ void ivas_sba_config( if ( nchan_transport != NULL ) { - if ( sba_mode == SBA_MODE_SPAR ) - { - *nchan_transport = ivas_get_spar_num_TCs( sba_total_brate, sba_order ); - } - else - { - *nchan_transport = ivas_dirac_getNumTransportChannels( sba_total_brate, sba_order, sba_planar ); - } + *nchan_transport = ivas_get_sba_num_TCs( sba_total_brate, sba_order ); } /* Configure core coder number of elements*/ @@ -164,6 +154,7 @@ void ivas_sba_config( * Get Ambisonic order from number of ambisonic channels *-------------------------------------------------------------------*/ +/*! r: Ambisonic (SBA) order */ int16_t ivas_sba_get_order( const int16_t nb_channels, /* i : Number of ambisonic channels */ const int16_t sba_planar /* i : SBA Planar flag */ @@ -189,29 +180,28 @@ int16_t ivas_sba_get_order( /*-------------------------------------------------------------------* - * ivas_sba_get_order_transport() + * ivas_sba_get_analysis_order() * - * Get effective Ambisonic order from number of transport channels + * Get Ambisonic order used for analysis and coding *-------------------------------------------------------------------*/ -int16_t ivas_sba_get_order_transport( - const int16_t nchan_transport /* i : Number of transport channels */ +/*! r: Ambisonic (SBA) order used for analysis and coding */ +int16_t ivas_sba_get_analysis_order( + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { - int16_t sba_order; + int16_t sba_analysis_order; - sba_order = 1; + sba_analysis_order = sba_order; - if ( nchan_transport > 6 ) + if ( ivas_total_brate < SBA_MIN_BRATE_HOA ) { - sba_order = 3; - } - else if ( nchan_transport > 4 ) - { - sba_order = 2; + /* Hard coding the sba_analysis_order as 1 as higher not supported below SBA_MIN_BRATE_HOA bitrate */ + sba_analysis_order = SBA_FOA_ORDER; } - return ( sba_order ); + return sba_analysis_order; } @@ -221,6 +211,7 @@ int16_t ivas_sba_get_order_transport( * Get number of Ambisonic channels *-------------------------------------------------------------------*/ +/*! r: number of Ambisonic channels */ int16_t ivas_sba_get_nchan( const int16_t sba_order, /* i : Ambisonic (SBA) order */ const int16_t sba_planar /* i : SBA planar flag */ @@ -254,7 +245,7 @@ int16_t ivas_sba_get_nchan_metadata( { int16_t nb_channels; - if ( sba_order == 1 ) + if ( sba_order == SBA_FOA_ORDER ) { nb_channels = FOA_CHANNELS; } @@ -267,6 +258,31 @@ int16_t ivas_sba_get_nchan_metadata( return ( nb_channels ); } +/*-------------------------------------------------------------------* + * ivas_sba_get_spar_hoa_md_flag() + * + * Get the flag to code SPAR HOA MD for all band + *-------------------------------------------------------------------*/ + +/*! r: flag indicating to code SPAR HOA MD for all bands */ +int16_t ivas_sba_get_spar_hoa_md_flag( + const int16_t sba_order, /* i : Ambisonic (SBA) order */ + const int32_t ivas_total_brate /* i : IVAS total bitrate */ +) +{ + int16_t spar_hoa_md_flag = 0; + + if ( sba_order > 1 && ivas_total_brate >= IVAS_256k ) + { + spar_hoa_md_flag = 1; + } + else + { + spar_hoa_md_flag = 0; + } + + return spar_hoa_md_flag; +} /*-------------------------------------------------------------------* * ivas_sba_zero_vert_comp() diff --git a/lib_com/ivas_sns_com.c b/lib_com/ivas_sns_com.c index 51f5fcee64c94f68dc271eb94d7c20d1abe85c51..e4515a98547ce096ec8f1ebcbb46b2a1ce0a0f7d 100644 --- a/lib_com/ivas_sns_com.c +++ b/lib_com/ivas_sns_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,15 +37,12 @@ #include "ivas_prot.h" #include "rom_com.h" #include -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT #include -#endif #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT /*------------------------------------------------------------------- * sns_compute_scf() @@ -56,7 +53,7 @@ void sns_compute_scf( float spectrum[], const PsychoacousticParameters *pPsychParams, - const int16_t L_frame, /* TODO: this parameter is obsolete, since pPsychParams->nBins is used anyway */ + const int16_t L_frame, float *scf ) { int16_t i, n, k; @@ -212,7 +209,6 @@ void sns_compute_scf( return; } -#endif /*------------------------------------------------------------------- * sns_interpolate_scalefactors() diff --git a/lib_com/ivas_spar_com.c b/lib_com/ivas_spar_com.c index 7d064d0104d6205fb600dd88d3c668106748ab5d..6b36c23291f513d0b593b403988174df4c57e3a6 100644 --- a/lib_com/ivas_spar_com.c +++ b/lib_com/ivas_spar_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "ivas_rom_com.h" #include "cnst.h" #include -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -53,7 +53,6 @@ #define IVAS_MDCT_SCALING_GAIN_48k 1.9699011974118126e-06f #define IVAS_MDCT_SCALING_GAIN_32k 2.9548517961177197e-06f #define IVAS_MDCT_SCALING_GAIN_16k 5.909703592235439e-06f -#define IVAS_MDCT_SCALING_GAIN_8k 0.000011819f #define IVAS_FLT_EPS ( 1e-10F ) #define IVAS_DBL_EPS ( (double) 1e-20 ) @@ -79,11 +78,12 @@ * Static functions declaration *------------------------------------------------------------------------------------------*/ -static void ivas_get_pred_coeffs( float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float ppPred_coeffs_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], float ppDM_Fv_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], const int16_t in_chans, const int16_t start_band, const int16_t end_band, const int16_t active_w, + +static void ivas_get_pred_coeffs( float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float ppPred_coeffs_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], float ppDM_Fv_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], const int16_t in_chans, const int16_t start_band, const int16_t end_band, const int16_t active_w, #ifdef LBR_SBA const int16_t active_w_vlbr, #endif - const int16_t dtx_vad, const int16_t from_dirac ); +const int16_t dtx_vad, const int16_t from_dirac ); static void ivas_reorder_array( float in_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS], const int16_t in_chans, const int16_t order[IVAS_SPAR_MAX_CH], float ***mixer_mat, const int16_t start_band, const int16_t end_band ); @@ -91,7 +91,7 @@ static void ivas_get_Wscaling_factor( float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVA #ifdef LBR_SBA const int16_t active_w_vlbr, #endif - float *pWscale ); +float *pWscale ); static void ivas_calc_post_pred_per_band( float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float ***mixer_mat, const int16_t num_ch, const int16_t num_dmx, const int16_t band_idx, float postpred_cov_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH] ); @@ -149,28 +149,23 @@ void ivas_get_twid_factors( float ivas_get_mdct_scaling_gain( const int16_t dct_len_by_2 ) { - float result = 0.0f; + float gain = 0.0f; switch ( dct_len_by_2 ) { case L_FRAME48k >> 2: { - result = IVAS_MDCT_SCALING_GAIN_48k; + gain = IVAS_MDCT_SCALING_GAIN_48k; break; } case L_FRAME32k >> 2: { - result = IVAS_MDCT_SCALING_GAIN_32k; + gain = IVAS_MDCT_SCALING_GAIN_32k; break; } case L_FRAME16k >> 2: { - result = IVAS_MDCT_SCALING_GAIN_16k; - break; - } - case L_FRAME8k >> 2: - { - result = IVAS_MDCT_SCALING_GAIN_8k; + gain = IVAS_MDCT_SCALING_GAIN_16k; break; } default: @@ -180,7 +175,7 @@ float ivas_get_mdct_scaling_gain( } } - return result; + return gain; } @@ -277,9 +272,10 @@ int16_t ivas_get_bw_idx_from_sample_rate( *-----------------------------------------------------------------------------------------*/ void lfe_window_init( - LFE_WINDOW_HANDLE hLFEWindow, - const int32_t sampling_rate, - const int16_t frame_len ) + LFE_WINDOW_HANDLE hLFEWindow, /* i/o: LFE window handle */ + const int32_t sampling_rate, /* i : sampling rate */ + const int16_t frame_len /* i : frame length in samples */ +) { /* Set window coefficients */ if ( sampling_rate == 48000 ) @@ -303,7 +299,7 @@ void lfe_window_init( hLFEWindow->dct_len = frame_len >> 1; /* 8ms of latency */ - hLFEWindow->fade_len = (int16_t) ( sampling_rate * IVAS_LFE_FADE_LEN_SEC_FLOAT ); + hLFEWindow->fade_len = NS2SA( sampling_rate, IVAS_LFE_FADE_NS ); hLFEWindow->zero_pad_len = (int16_t) ( IVAS_ZERO_PAD_LEN_MULT_FAC * ( hLFEWindow->dct_len - hLFEWindow->fade_len ) ); hLFEWindow->full_len = hLFEWindow->zero_pad_len + hLFEWindow->fade_len + hLFEWindow->dct_len; @@ -327,7 +323,7 @@ void ivas_spar_config( const int16_t sid_format /* i : IVAS format indicator from SID frame */ ) { - if ( ivas_total_brate == IVAS_SID_5k ) + if ( ivas_total_brate == IVAS_SID_5k2 ) { if ( sid_format == SID_SBA_1TC ) { @@ -340,7 +336,7 @@ void ivas_spar_config( } else { - *nchan_transport = ivas_get_spar_num_TCs( ivas_total_brate, sba_order ); + *nchan_transport = ivas_get_sba_num_TCs( ivas_total_brate, sba_order ); } *nCPE = ( *nchan_transport > 1 ) ? ( *nchan_transport + 1 ) >> 1 : 0; @@ -349,7 +345,7 @@ void ivas_spar_config( if ( *nchan_transport == 1 ) { /* map SPAR SID bitrate to SPAR active bitrate */ - if ( ivas_total_brate == IVAS_SID_5k ) + if ( ivas_total_brate == IVAS_SID_5k2 ) { ivas_total_brate = IVAS_32k; } @@ -438,20 +434,28 @@ int16_t ivas_get_spar_table_idx( /*-------------------------------------------------------------------* - * ivas_get_spar_num_TCs() + * ivas_get_sba_num_TCs() * - * Return number of TCs in SPAR + * Return number of TCs in SBA format *-------------------------------------------------------------------*/ /*! r: number of transport channels */ -int16_t ivas_get_spar_num_TCs( +int16_t ivas_get_sba_num_TCs( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { int16_t table_idx, nchan_transport; - if ( ivas_total_brate == IVAS_SID_5k ) + if ( ivas_total_brate == IVAS_SID_5k2 ) + { + nchan_transport = 1; + } +#ifndef LBR_SBA + else if ( ivas_sba_mode_select( ivas_total_brate ) == SBA_MODE_DIRAC ) +#else + else if ( ivas_sba_mode_select( ) == SBA_MODE_DIRAC ) +#endif { nchan_transport = 1; } @@ -473,7 +477,7 @@ int16_t ivas_get_spar_num_TCs( *-----------------------------------------------------------------------------------------*/ static void ivas_get_pred_coeffs( - float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float ppPred_coeffs_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], float ppDM_Fv_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], const int16_t in_chans, @@ -501,7 +505,7 @@ static void ivas_get_pred_coeffs( set_zero( pPred_temp, IVAS_MAX_NUM_BANDS ); for ( k = start_band; k < end_band; k++ ) { - div_factor[k] = max( 1e-20f, pppCov_mat_re[0][0][k] ); + div_factor[k] = max( 1e-20f, cov_real[0][0][k] ); div_factor[k] = 1 / div_factor[k]; } @@ -509,7 +513,7 @@ static void ivas_get_pred_coeffs( { for ( k = start_band; k < end_band; k++ ) { - ppPred_coeffs_re[i][k] = pppCov_mat_re[i + 1][0][k] * div_factor[k]; + ppPred_coeffs_re[i][k] = cov_real[i + 1][0][k] * div_factor[k]; IVAS_CALCULATE_SQ_ABS_N( ppPred_coeffs_re[i][k], abs_value ); @@ -547,7 +551,7 @@ static void ivas_get_pred_coeffs( { for ( k = start_band; k < end_band; k++ ) { - IVAS_CALCULATE_SQ_ABS_N( pppCov_mat_re[i][0][k], abs_value ); + IVAS_CALCULATE_SQ_ABS_N( cov_real[i][0][k], abs_value ); dm_alpha[k] += abs_value; } } @@ -563,7 +567,7 @@ static void ivas_get_pred_coeffs( { for ( k = start_band; k < end_band; k++ ) { - dm_v_re[i][k] = pppCov_mat_re[i + 1][0][k] * div_factor[k]; + dm_v_re[i][k] = cov_real[i + 1][0][k] * div_factor[k]; } } @@ -590,7 +594,7 @@ static void ivas_get_pred_coeffs( { float re; - IVAS_RMULT_FLOAT( pppCov_mat_re[j + 1][k][b], dm_v_re[k - 1][b], re ); + IVAS_RMULT_FLOAT( cov_real[j + 1][k][b], dm_v_re[k - 1][b], re ); real[j] += re; } } @@ -602,7 +606,7 @@ static void ivas_get_pred_coeffs( dm_beta_re += re; } - dm_w = pppCov_mat_re[0][0][b]; + dm_w = cov_real[0][0][b]; den_f = max( dm_w, 1e-20f ); passive_g = dm_alpha[b] / den_f; @@ -613,7 +617,7 @@ static void ivas_get_pred_coeffs( for ( k = 1; k < in_chans; k++ ) { - dm_y += pppCov_mat_re[k][k][b]; + dm_y += cov_real[k][k][b]; } den_f = max( dm_y, 1e-20f ); den_f = max( den_f, w_norm_fac * dm_w ); @@ -666,7 +670,7 @@ static void ivas_get_pred_coeffs( *-----------------------------------------------------------------------------------------*/ static void ivas_get_Wscaling_factor( - float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float pred_coeffs_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], float ***mixer_mat, const int16_t start_band, @@ -706,9 +710,9 @@ static void ivas_get_Wscaling_factor( { float Gw_sq, g_sq = 0; - ivas_calc_post_pred_per_band( pppCov_mat_re, mixer_mat, num_ch, pNum_dmx[b * bands_bw], b, postpred_cov_re ); + ivas_calc_post_pred_per_band( cov_real, mixer_mat, num_ch, pNum_dmx[b * bands_bw], b, postpred_cov_re ); - Gw_sq = pppCov_mat_re[0][0][b] / max( postpred_cov_re[0][0], IVAS_FLT_EPS ); + Gw_sq = cov_real[0][0][b] / max( postpred_cov_re[0][0], IVAS_FLT_EPS ); for ( ch = 0; ch < num_ch - 1; ch++ ) { @@ -741,7 +745,7 @@ void ivas_create_fullr_dmx_mat( const int16_t start_band, const int16_t end_band, const int16_t active_w, - ivas_spar_foa_md_com_cfg *hMdCfg ) + ivas_spar_md_com_cfg *hMdCfg ) { int16_t i, j, k, b; const int16_t *order; @@ -900,7 +904,7 @@ static void ivas_reorder_array( *-----------------------------------------------------------------------------------------*/ static void ivas_calc_post_pred_per_band( - float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float ***mixer_mat, const int16_t num_ch, const int16_t num_dmx, @@ -937,7 +941,7 @@ static void ivas_calc_post_pred_per_band( temp_mat[i][j] = 0; for ( k = 0; k < num_ch; k++ ) { - IVAS_RMULT_FLOAT( pppCov_mat_re[i][k][band_idx], dmx_mat_conj[k][j], tmp_re ); + IVAS_RMULT_FLOAT( cov_real[i][k][band_idx], dmx_mat_conj[k][j], tmp_re ); temp_mat[i][j] += tmp_re; } } @@ -950,7 +954,6 @@ static void ivas_calc_post_pred_per_band( { for ( k = 0; k < num_ch; k++ ) { - IVAS_RMULT_FLOAT( mixer_mat[i][k][band_idx], temp_mat[k][j], tmp_re ); postpred_cov_re[i][j] += tmp_re; } @@ -1251,6 +1254,7 @@ static void ivas_calc_c_coeffs_per_band( else { ivas_calc_mat_inv( cov_dd_re, num_dmx - 1, cov_dd_re_inv ); + for ( i = 0; i < num_ch - num_dmx; i++ ) { for ( j = 0; j < num_dmx - 1; j++ ) @@ -1278,7 +1282,7 @@ static void ivas_calc_c_coeffs_per_band( void ivas_calc_c_p_coeffs( ivas_spar_md_t *pSparMd, - float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], const int16_t i_ts, float ***mixer_mat, const int16_t num_ch, @@ -1293,7 +1297,8 @@ void ivas_calc_c_p_coeffs( if ( num_dmx != num_ch ) { - ivas_calc_post_pred_per_band( pppCov_mat_re, mixer_mat, num_ch, num_dmx, band_idx, postpred_cov_re ); + ivas_calc_post_pred_per_band( cov_real, mixer_mat, num_ch, num_dmx, band_idx, postpred_cov_re ); + if ( num_dmx != 1 ) { ivas_calc_c_coeffs_per_band( pSparMd, i_ts, postpred_cov_re, num_ch, num_dmx, band_idx, dtx_vad ); @@ -1427,6 +1432,7 @@ static void ivas_get_mat_cofactor( * * Calculate Invert of a matrix *-----------------------------------------------------------------------------------------*/ + static void ivas_calc_mat_inv( float in_re[MAX_MAT_DIM][MAX_MAT_DIM], const int16_t dim, @@ -1457,6 +1463,7 @@ static void ivas_calc_mat_inv( { double det_re; double re; + ivas_calc_mat_det( dbl_in_re, dim, &det_re ); det = ( det_re * det_re ); /* assert to catch cases when input is singular matrix*/ @@ -1483,6 +1490,7 @@ static void ivas_calc_mat_inv( ivas_calc_mat_det( dbl_in_re, dim, &det_re ); det = det_re > 0 ? 1 / max( IVAS_DBL_EPS, det_re ) : min( det_re, -IVAS_DBL_EPS ); + for ( i = 0; i < dim; i++ ) { for ( j = 0; j < dim; j++ ) @@ -1524,6 +1532,7 @@ static void ivas_calc_mat_inv( * * Check if matrix is invertible or not by checking if determinant is 0 or very close to 0 *-----------------------------------------------------------------------------------------*/ + static int16_t ivas_is_mat_inv( float in_re[MAX_MAT_DIM][MAX_MAT_DIM], const int16_t dim ) @@ -1561,7 +1570,7 @@ static int16_t ivas_is_mat_inv( *-----------------------------------------------------------------------------------------*/ void ivas_compute_spar_params( - float *pppCov_mat_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float dm_fv_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS], const int16_t i_ts, float ***mixer_mat, @@ -1574,19 +1583,20 @@ void ivas_compute_spar_params( #ifdef LBR_SBA const int16_t active_w_vlbr, #endif - ivas_spar_foa_md_com_cfg *hSparCfg, + ivas_spar_md_com_cfg *hSparCfg, ivas_spar_md_t *hSparMd, float *pWscale, const int16_t from_dirac ) { float pred_coeffs_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS]; int16_t b, i, ndm; - ivas_get_pred_coeffs( pppCov_mat_re, pred_coeffs_re, dm_fv_re, num_ch, - start_band, end_band, active_w, + + ivas_get_pred_coeffs( cov_real, pred_coeffs_re, dm_fv_re, num_ch, start_band, end_band, active_w, #ifdef LBR_SBA active_w_vlbr, #endif - dtx_vad, from_dirac ); + dtx_vad, from_dirac ); + #ifdef SPAR_HOA_DBG /*fprintf(stderr, "\n\n Prediction Coefficients:\n"); @@ -1616,12 +1626,12 @@ void ivas_compute_spar_params( fprintf(stderr, "\n\n");*/ #endif - ivas_get_Wscaling_factor( pppCov_mat_re, pred_coeffs_re, mixer_mat, start_band, end_band, dtx_vad, num_ch, + ivas_get_Wscaling_factor( cov_real, pred_coeffs_re, mixer_mat, start_band, end_band, dtx_vad, num_ch, hSparCfg->num_dmx_chans_per_band, bands_bw, active_w, #ifdef LBR_SBA active_w_vlbr, #endif - pWscale ); + pWscale ); for ( b = start_band; b < end_band; b++ ) { @@ -1643,22 +1653,24 @@ void ivas_compute_spar_params( if ( ndm != num_ch ) { - ivas_calc_c_p_coeffs( hSparMd, pppCov_mat_re, i_ts, mixer_mat, num_ch, ndm, b, dtx_vad, 1, 0 ); + ivas_calc_c_p_coeffs( hSparMd, cov_real, i_ts, mixer_mat, num_ch, ndm, b, dtx_vad, 1, 0 ); #ifdef SPAR_HOA_DBG /* if (b == 0) */ { fprintf( stdout, "\n\nUnquantised C, P coeffs -- band %d:\n", b ); - for ( ii = 0; ii < num_ch; ii++ ) + for ( int16_t ii = 0; ii < num_ch; ii++ ) { fprintf( stdout, "%f |", hSparMd->band_coeffs[b].pred_re[ii] ); if ( ii < num_ch - ndm ) { - for ( jj = 0; jj < ndm - 1; jj++ ) + for ( int16_t jj = 0; jj < ndm - 1; jj++ ) + { fprintf( stdout, "%f,\t", hSparMd->band_coeffs[b].C_re[ii][jj] ); - fprintf( stdout, "| %f", hSparMd->band_coeffs[b].P_re[ii][ii] ); + } + fprintf( stdout, "| %f", hSparMd->band_coeffs[b].P_re[ii] ); } fprintf( stdout, "\n" ); } @@ -1667,7 +1679,6 @@ void ivas_compute_spar_params( } } - return; } @@ -1685,7 +1696,7 @@ void ivas_get_spar_md_from_dirac( const int16_t n_ts, float ***mixer_mat, ivas_spar_md_t *hSpar_md, - ivas_spar_foa_md_com_cfg *hSpar_md_cfg, + ivas_spar_md_com_cfg *hSpar_md_cfg, const int16_t start_band, const int16_t end_band, const int16_t order, @@ -1696,7 +1707,7 @@ void ivas_get_spar_md_from_dirac( const uint8_t useLowerRes, const int16_t active_w_vlbr #endif -) + ) { int16_t num_ch, band, i, j; int16_t block, ch; @@ -1716,8 +1727,8 @@ void ivas_get_spar_md_from_dirac( remix_order = remix_order_set[hSpar_md_cfg->remix_unmix_order]; - num_ch = 2 * order + 2; - hoa2_ch = 6; + num_ch = ivas_sba_get_nchan_metadata( order ); + hoa2_ch = ivas_sba_get_nchan_metadata( SBA_HOA2_ORDER ); foa_ch = FOA_CHANNELS; diff_norm_order1 = 3.0f; diff_norm_order2 = 5.0f; @@ -1731,6 +1742,7 @@ void ivas_get_spar_md_from_dirac( } ppMixer_mat[i] = pMixer_mat[i]; } + #ifdef LBR_SBA if ( ( start_band >= 6 && hSpar_md_cfg->nchan_transport <= 2 && ( dtx_vad == 1 ) ) || ( useLowerRes && start_band >= 3 && hSpar_md_cfg->nchan_transport <= 2 && ( dtx_vad == 1 ) ) ) #else @@ -1739,6 +1751,7 @@ void ivas_get_spar_md_from_dirac( { float P_norm[3]; int16_t idx; + ndm = hSpar_md_cfg->num_dmx_chans_per_band[start_band - 1]; P_norm[0] = 0.0f; for ( i = 0; i < max( 0, foa_ch - ndm ); i++ ) @@ -1789,10 +1802,6 @@ void ivas_get_spar_md_from_dirac( /*SPAR from DirAC*/ set_f( response_avg, 0.0f, MAX_OUTPUT_CHANNELS ); - set_f( hSpar_md->band_coeffs[band + i_ts * IVAS_MAX_NUM_BANDS].pred_re, 0.0f, IVAS_SPAR_MAX_CH - 1 ); - set_f( &hSpar_md->band_coeffs[band + i_ts * IVAS_MAX_NUM_BANDS].C_re[0][0], 0.0f, ( IVAS_SPAR_MAX_CH - IVAS_SPAR_MAX_DMX_CHS ) * ( IVAS_SPAR_MAX_DMX_CHS - 1 ) ); - set_f( &hSpar_md->band_coeffs[band + i_ts * IVAS_MAX_NUM_BANDS].P_re[0], 0.0f, ( IVAS_SPAR_MAX_CH - 1 ) ); - if ( n_ts > 1 ) { ivas_dirac_dec_get_response( (int16_t) azi_dirac[band][i_ts], (int16_t) ele_dirac[band][i_ts], response_avg, order ); @@ -1813,8 +1822,10 @@ void ivas_get_spar_md_from_dirac( /* average responses in all subframes*/ { float norm; - int16_t num_ch_order = ( order + 1 ) * ( order + 1 ); - int16_t hoa2_ch_order = 9; + int16_t num_ch_order, hoa2_ch_order; + + num_ch_order = ivas_sba_get_nchan( order, 0 ); + hoa2_ch_order = ivas_sba_get_nchan( SBA_HOA2_ORDER, 0 ); for ( ch = 0; ch < num_ch_order; ch++ ) { @@ -1967,7 +1978,7 @@ void ivas_get_spar_md_from_dirac( #ifdef LBR_SBA active_w_vlbr, #endif - hSpar_md_cfg, hSpar_md, Wscale, 1 ); + hSpar_md_cfg, hSpar_md, Wscale, 1 ); if ( mixer_mat != NULL ) { @@ -2144,3 +2155,159 @@ int16_t ivas_get_bits_to_encode( return bits_req; } + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_spar_set_bitrate_config() + * + * Set SPAR bitrate config + *-----------------------------------------------------------------------------------------*/ + +void ivas_spar_set_bitrate_config( + ivas_spar_md_com_cfg *pSpar_md_cfg, /* i/o: SPAR MD config. handle */ + const int16_t table_idx, /* i : config. table index */ + const int16_t num_bands /* i : number of bands */ +) +{ + int32_t ivas_total_brate; + int16_t i, total_bits, max_bits, code, length; + int16_t sba_order; + int16_t md_coding_bits_header; + pSpar_md_cfg->nchan_transport = ivas_spar_br_table_consts[table_idx].nchan_transport; + + for ( i = 0; i < pSpar_md_cfg->nchan_transport; i++ ) + { + pSpar_md_cfg->max_freq_per_chan[i] = ivas_spar_br_table_consts[table_idx].fpcs; + } + + pSpar_md_cfg->active_w = ivas_spar_br_table_consts[table_idx].active_w; + pSpar_md_cfg->agc_bits_ch_idx = ivas_spar_br_table_consts[table_idx].agc_bits_ch_idx; + ivas_spar_get_uniform_quant_strat( pSpar_md_cfg, table_idx ); + + pSpar_md_cfg->quant_strat_bits = ivas_get_bits_to_encode( MAX_QUANT_STRATS ); + + /* BLOCK: getEntropyCoderModels */ + + pSpar_md_cfg->remix_unmix_order = ivas_spar_br_table_consts[table_idx].dmx_str; + + /* bits per block*/ + total_bits = 0; + max_bits = 0; + + ivas_total_brate = ivas_spar_br_table_consts[table_idx].ivas_total_brate; + sba_order = ivas_spar_br_table_consts[table_idx].sba_order; + ivas_get_spar_table_idx( ivas_total_brate, sba_order, ivas_spar_br_table_consts[table_idx].bwidth, &length, &code ); + + for ( i = 0; i < pSpar_md_cfg->nchan_transport; i++ ) + { + total_bits += (int16_t) ( ivas_spar_br_table_consts[table_idx].core_brs[i][0] / FRAMES_PER_SEC ); + max_bits += (int16_t) ( ivas_spar_br_table_consts[table_idx].core_brs[i][1] / FRAMES_PER_SEC ); + } + + pSpar_md_cfg->tgt_bits_per_blk = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ) - IVAS_FORMAT_SIGNALING_NBITS_SBA - SBA_PLANAR_BITS - SBA_ORDER_BITS - length - total_bits; + pSpar_md_cfg->max_bits_per_blk = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ) - IVAS_FORMAT_SIGNALING_NBITS_SBA - SBA_PLANAR_BITS - SBA_ORDER_BITS - length - max_bits; + + md_coding_bits_header = SPAR_NUM_CODING_STRAT_BITS + pSpar_md_cfg->quant_strat_bits; + + pSpar_md_cfg->tgt_bits_per_blk -= md_coding_bits_header; + pSpar_md_cfg->max_bits_per_blk -= md_coding_bits_header; + + pSpar_md_cfg->tgt_bits_per_blk = (int16_t) ceilf( ( 1.0f * pSpar_md_cfg->tgt_bits_per_blk * num_bands ) / IVAS_MAX_NUM_BANDS ); + pSpar_md_cfg->max_bits_per_blk = (int16_t) ceilf( ( 1.0f * pSpar_md_cfg->max_bits_per_blk * num_bands ) / IVAS_MAX_NUM_BANDS ); + + pSpar_md_cfg->tgt_bits_per_blk += md_coding_bits_header; + pSpar_md_cfg->max_bits_per_blk += md_coding_bits_header; + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_spar_bitrate_dist() + * + * Set SPAR bitrate distribution + *-----------------------------------------------------------------------------------------*/ + +void ivas_spar_bitrate_dist( + int32_t core_brates_act[], /* o : bitrates per core-coder */ + const int16_t nAvailBits, /* i : number of available bits */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t sba_order, /* i : Ambisonic (SBA) order */ + const int16_t bwidth /* i : audio bandwidth */ +) +{ + int16_t i, nchan_transport, table_idx, bitlen; + int16_t core_bits_act[FOA_CHANNELS], core_range_bits[FOA_CHANNELS]; + int16_t sum_core_act_bits, residual_bits, overflow_bits; + + table_idx = ivas_get_spar_table_idx( ivas_total_brate, sba_order, bwidth, &bitlen, NULL ); + + nchan_transport = ivas_spar_br_table_consts[table_idx].nchan_transport; + + sum_core_act_bits = 0; + for ( i = 0; i < nchan_transport; i++ ) + { + core_bits_act[i] = (int16_t) ( ivas_spar_br_table_consts[table_idx].core_brs[i][0] / FRAMES_PER_SEC ); + + sum_core_act_bits += core_bits_act[i]; + } + + residual_bits = nAvailBits - sum_core_act_bits; + + /* First compute core-coder bits as per bitrate distribution table and MD bitrate*/ + if ( residual_bits > 0 ) + { + for ( i = 0; i < nchan_transport; i++ ) + { + core_range_bits[i] = (int16_t) ( ( ivas_spar_br_table_consts[table_idx].core_brs[i][2] - ivas_spar_br_table_consts[table_idx].core_brs[i][0] ) / FRAMES_PER_SEC ); + core_bits_act[i] += min( residual_bits, core_range_bits[i] ); + residual_bits -= core_range_bits[i]; + + if ( residual_bits <= 0 ) + { + break; + } + } + } + else + { + for ( i = 0; i < nchan_transport; i++ ) + { + core_range_bits[i] = (int16_t) ( ( ivas_spar_br_table_consts[table_idx].core_brs[i][0] - ivas_spar_br_table_consts[table_idx].core_brs[i][1] ) / FRAMES_PER_SEC ); + } + + overflow_bits = -residual_bits; + + for ( i = 0; i < nchan_transport; i++ ) + { + core_bits_act[nchan_transport - 1 - i] -= min( overflow_bits, core_range_bits[nchan_transport - 1 - i] ); + overflow_bits -= core_range_bits[nchan_transport - 1 - i]; + + if ( overflow_bits <= 0 ) + { + break; + } + } + + if ( overflow_bits > 0 ) + { + int16_t overflow_bits_ch; + overflow_bits_ch = overflow_bits / nchan_transport; + + for ( i = 0; i < nchan_transport; i++ ) + { + core_bits_act[i] -= overflow_bits_ch; + overflow_bits -= overflow_bits_ch; + } + + core_bits_act[nchan_transport - 1] -= max( 0, overflow_bits ); + } + } + + for ( i = 0; i < nchan_transport; i++ ) + { + core_brates_act[i] = core_bits_act[i] * FRAMES_PER_SEC; + } + + return; +} diff --git a/lib_com/ivas_spar_com_quant_util.c b/lib_com/ivas_spar_com_quant_util.c index 472548833860ae747242d3465ec390ec3ed1116e..355e02ca76d05b1d187e3b950aa9ddd30e2b3ec1 100644 --- a/lib_com/ivas_spar_com_quant_util.c +++ b/lib_com/ivas_spar_com_quant_util.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,104 +40,62 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include -#include "wmops.h" - -/*-----------------------------------------------------------------------------------------* - * Function ivas_limit_values() - * - * Limit values within given range - *-----------------------------------------------------------------------------------------*/ - -static void ivas_limit_values( - float **ppValues, - const float min_value, - const float max_value, - const int16_t dim1, - const int16_t dim2 ) -{ - int16_t i, j; - - for ( i = 0; i < dim1; i++ ) - { - for ( j = 0; j < dim2; j++ ) - { - ppValues[i][j] = max( min_value, min( ppValues[i][j], max_value ) ); - } - } - - return; -} - +#include "wmc_auto.h" /*-----------------------------------------------------------------------------------------* * Function ivas_quantise_real_values() * * Quantize real values *-----------------------------------------------------------------------------------------*/ - void ivas_quantise_real_values( - float **values, + const float *values, const int16_t q_levels, const float min_value, const float max_value, - int16_t **index, - float **quant, - const int16_t dim1, - const int16_t dim2 ) + int16_t *index, + float *quant, + const int16_t dim ) { - int16_t i, j; + int16_t i; float q_step, one_by_q_step; - if ( q_levels == 1 ) { - for ( i = 0; i < dim1; i++ ) + for ( i = 0; i < dim; i++ ) { - for ( j = 0; j < dim2; j++ ) - { - quant[i][j] = 0; - index[i][j] = 0; - } + quant[i] = 0; + index[i] = 0; } } else if ( q_levels && max_value != min_value ) { - ivas_limit_values( values, min_value, max_value, dim1, dim2 ); - q_step = ( max_value - min_value ) / ( q_levels - 1 ); one_by_q_step = ( q_levels - 1 ) / ( max_value - min_value ); - - for ( i = 0; i < dim1; i++ ) + float val; + for ( i = 0; i < dim; i++ ) { - for ( j = 0; j < dim2; j++ ) - { - index[i][j] = (int16_t) round( one_by_q_step * values[i][j] ); - quant[i][j] = index[i][j] * q_step; - } + val = max( min_value, min( values[i], max_value ) ); + index[i] = (int16_t) round( one_by_q_step * val ); + quant[i] = index[i] * q_step; } } else { - for ( i = 0; i < dim1; i++ ) + for ( i = 0; i < dim; i++ ) { - for ( j = 0; j < dim2; j++ ) - { - quant[i][j] = values[i][j]; - } + quant[i] = values[i]; } } - return; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_get_uniform_quant_strat() + * Function ivas_spar_get_uniform_quant_strat() * * Sets the quant strat values *-----------------------------------------------------------------------------------------*/ - -void ivas_spar_foa_get_uniform_quant_strat( - ivas_spar_foa_md_com_cfg *pSpar_md_com_cfg, +void ivas_spar_get_uniform_quant_strat( + ivas_spar_md_com_cfg *pSpar_md_com_cfg, const int16_t table_idx ) { int16_t i; @@ -211,7 +169,7 @@ void ivas_spar_foa_get_uniform_quant_strat( void ivas_map_prior_coeffs_quant( ivas_spar_md_prev_t *pSpar_md_prior, - ivas_spar_foa_md_com_cfg *pSpar_md_cfg, + ivas_spar_md_com_cfg *pSpar_md_cfg, const int16_t qsi, const int16_t nB ) { @@ -260,7 +218,7 @@ void ivas_map_prior_coeffs_quant( /*-----------------------------------------------------------------------------------------* * Function ivas_spar_quant_dtx_init() * - * Init spar md with minmax vals + * Init SPAR MD with minmax vals *-----------------------------------------------------------------------------------------*/ void ivas_spar_quant_dtx_init( @@ -348,7 +306,7 @@ void ivas_copy_band_coeffs_idx_to_arr( /*-----------------------------------------------------------------------------------------* * Function ivas_clear_band_coeffs() * - * clear band coeffs array in spar MD + * clear band coeffs array in SPAR MD *-----------------------------------------------------------------------------------------*/ void ivas_clear_band_coeffs( @@ -375,7 +333,7 @@ void ivas_clear_band_coeffs( /*-----------------------------------------------------------------------------------------* * Function ivas_clear_band_coeff_idx() * - * clear band coeffs index array in spar MD + * clear band coeffs index array in SPAR MD *-----------------------------------------------------------------------------------------*/ void ivas_clear_band_coeff_idx( @@ -387,7 +345,6 @@ void ivas_clear_band_coeff_idx( for ( i = 0; i < num_bands; i++ ) { set_s( pband_coeff_idx[i].pred_index_re, 0, ( IVAS_SPAR_MAX_CH - 1 ) ); - set_s( pband_coeff_idx[i].drct_index_re, 0, IVAS_SPAR_MAX_C_COEFF ); set_s( pband_coeff_idx[i].decd_index_re, 0, ( IVAS_SPAR_MAX_CH - 1 ) ); } diff --git a/lib_com/ivas_spar_foa_br_dist.c b/lib_com/ivas_spar_foa_br_dist.c deleted file mode 100644 index 607ebc56abf33638a9d8970dd66f05d9b8b97dd0..0000000000000000000000000000000000000000 --- a/lib_com/ivas_spar_foa_br_dist.c +++ /dev/null @@ -1,224 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "math.h" -#include "options.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "prot.h" -#include "ivas_prot.h" -#include "ivas_rom_com.h" -#include "ivas_stat_com.h" -#include -#include "wmops.h" - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_spar_set_bitrate_config() - * - * Set SPAR bitrate config - *-----------------------------------------------------------------------------------------*/ - -void ivas_spar_set_bitrate_config( - ivas_spar_foa_md_com_cfg *pSpar_md_cfg, /* i/o: SPAR MD config. handle */ - const int16_t table_idx, /* i : config. table index */ - const int16_t num_bands /* i : number of bands */ -) -{ - int32_t ivas_total_brate; - int16_t i, total_bits, max_bits, code, length; - int16_t sba_order; - int16_t md_coding_bits_header; - pSpar_md_cfg->nchan_transport = ivas_spar_br_table_consts[table_idx].nchan_transport; - - for ( i = 0; i < pSpar_md_cfg->nchan_transport; i++ ) - { - pSpar_md_cfg->max_freq_per_chan[i] = ivas_spar_br_table_consts[table_idx].fpcs; - } - - pSpar_md_cfg->active_w = ivas_spar_br_table_consts[table_idx].active_w; - pSpar_md_cfg->agc_bits_ch_idx = ivas_spar_br_table_consts[table_idx].agc_bits_ch_idx; - ivas_spar_foa_get_uniform_quant_strat( pSpar_md_cfg, table_idx ); - - if ( pSpar_md_cfg->quant_strat->C.q_levels[0] == 0 || pSpar_md_cfg->quant_strat->C.q_levels[1] == 0 || pSpar_md_cfg->quant_strat->PR.q_levels[0] == 0 || pSpar_md_cfg->quant_strat->PR.q_levels[1] == 0 || pSpar_md_cfg->quant_strat->P_c.q_levels[0] == 0 || pSpar_md_cfg->quant_strat->P_c.q_levels[1] == 0 || pSpar_md_cfg->quant_strat->P_r.q_levels[0] == 0 || pSpar_md_cfg->quant_strat->P_r.q_levels[1] == 0 ) - { - pSpar_md_cfg->gen_bs = 0; - } - else - { - if ( 0 != pSpar_md_cfg->gen_bs ) - { - pSpar_md_cfg->quant_strat_bits = ivas_get_bits_to_encode( MAX_QUANT_STRATS ); - } - } - - /* BLOCK: getEntropyCoderModels */ - - pSpar_md_cfg->remix_unmix_order = ivas_spar_br_table_consts[table_idx].dmx_str; - - /* bits per block*/ - total_bits = 0; - max_bits = 0; - - ivas_total_brate = ivas_spar_br_table_consts[table_idx].ivas_total_brate; - sba_order = ivas_spar_br_table_consts[table_idx].sba_order; - ivas_get_spar_table_idx( ivas_total_brate, sba_order, ivas_spar_br_table_consts[table_idx].bwidth, &code, &length ); - - for ( i = 0; i < pSpar_md_cfg->nchan_transport; i++ ) - { - total_bits += (int16_t) ( ivas_spar_br_table_consts[table_idx].evs_brs[i][0] / FRAMES_PER_SEC ); - max_bits += (int16_t) ( ivas_spar_br_table_consts[table_idx].evs_brs[i][1] / FRAMES_PER_SEC ); - } - if ( ivas_total_brate >= IVAS_256k ) - { - pSpar_md_cfg->tgt_bits_per_blk = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ) - IVAS_FORMAT_SIGNALING_NBITS_SBA - SBA_PLANAR_BITS - SBA_ORDER_BITS - length - total_bits; - - pSpar_md_cfg->max_bits_per_blk = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ) - IVAS_FORMAT_SIGNALING_NBITS_SBA - SBA_PLANAR_BITS - SBA_ORDER_BITS - length - max_bits; - - // TODO : do this for lower bitrates as well once order/planar bits are added - md_coding_bits_header = SPAR_NUM_CODING_STRAT_BITS + pSpar_md_cfg->quant_strat_bits; - pSpar_md_cfg->tgt_bits_per_blk -= md_coding_bits_header; - pSpar_md_cfg->max_bits_per_blk -= md_coding_bits_header; - - pSpar_md_cfg->tgt_bits_per_blk = (int16_t) ceilf( ( 1.0f * pSpar_md_cfg->tgt_bits_per_blk * num_bands ) / IVAS_MAX_NUM_BANDS ); - pSpar_md_cfg->max_bits_per_blk = (int16_t) ceilf( ( 1.0f * pSpar_md_cfg->max_bits_per_blk * num_bands ) / IVAS_MAX_NUM_BANDS ); - - pSpar_md_cfg->tgt_bits_per_blk += md_coding_bits_header; - pSpar_md_cfg->max_bits_per_blk += md_coding_bits_header; - } - else - { - pSpar_md_cfg->tgt_bits_per_blk = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ) - IVAS_FORMAT_SIGNALING_NBITS_SBA - length - total_bits; - - pSpar_md_cfg->max_bits_per_blk = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC ) - IVAS_FORMAT_SIGNALING_NBITS_SBA - length - max_bits; - - pSpar_md_cfg->tgt_bits_per_blk = (int16_t) ceilf( ( 1.0f * pSpar_md_cfg->tgt_bits_per_blk * num_bands ) / IVAS_MAX_NUM_BANDS ); - pSpar_md_cfg->max_bits_per_blk = (int16_t) ceilf( ( 1.0f * pSpar_md_cfg->max_bits_per_blk * num_bands ) / IVAS_MAX_NUM_BANDS ); - } - - return; -} - -#ifdef FIX_I1_113 -/*-----------------------------------------------------------------------------------------* - * Function ivas_spar_bitrate_dist() - * - * Set SPAR bitrate distribution - *-----------------------------------------------------------------------------------------*/ - -// this function is not currently used but it is kept for future use -void ivas_spar_bitrate_dist( - int32_t core_brates_act[], /* o : bitrates per core-coder */ - const int16_t nAvailBits, /* i : number of available bits */ - const int32_t ivas_total_brate, /* i : IVAS total bitrate */ - const int16_t sba_order, /* i : Ambisonic (SBA) order */ - const int16_t bwidth /* i : audio bandwidth */ -) -{ - int16_t i, nchan_transport, table_idx, bitlen; - int16_t core_bits_act[FOA_CHANNELS], core_range_bits[FOA_CHANNELS]; - int16_t sum_core_act_bits, residual_bits, overflow_bits; - - table_idx = ivas_get_spar_table_idx( ivas_total_brate, sba_order, bwidth, &bitlen, NULL ); - - nchan_transport = ivas_spar_br_table_consts[table_idx].nchan_transport; - - sum_core_act_bits = 0; - for ( i = 0; i < nchan_transport; i++ ) - { - core_bits_act[i] = (int16_t) ( ivas_spar_br_table_consts[table_idx].evs_brs[i][0] / FRAMES_PER_SEC ); - - sum_core_act_bits += core_bits_act[i]; - } - - residual_bits = nAvailBits - sum_core_act_bits; - - /* First compute core-coder bits as per bitrate distribution table and MD bitrate*/ - if ( residual_bits > 0 ) - { - for ( i = 0; i < nchan_transport; i++ ) - { - core_range_bits[i] = (int16_t) ( ( ivas_spar_br_table_consts[table_idx].evs_brs[i][2] - ivas_spar_br_table_consts[table_idx].evs_brs[i][0] ) / FRAMES_PER_SEC ); - core_bits_act[i] += min( residual_bits, core_range_bits[i] ); - residual_bits -= core_range_bits[i]; - - if ( residual_bits <= 0 ) - { - break; - } - } - } - else - { - for ( i = 0; i < nchan_transport; i++ ) - { - core_range_bits[i] = (int16_t) ( ( ivas_spar_br_table_consts[table_idx].evs_brs[i][0] - ivas_spar_br_table_consts[table_idx].evs_brs[i][1] ) / FRAMES_PER_SEC ); - } - - overflow_bits = -residual_bits; - - for ( i = 0; i < nchan_transport; i++ ) - { - core_bits_act[nchan_transport - 1 - i] -= min( overflow_bits, core_range_bits[nchan_transport - 1 - i] ); - overflow_bits -= core_range_bits[nchan_transport - 1 - i]; - - if ( overflow_bits <= 0 ) - { - break; - } - } - - if ( overflow_bits > 0 ) - { - int16_t overflow_bits_ch; - overflow_bits_ch = overflow_bits / nchan_transport; - - for ( i = 0; i < nchan_transport; i++ ) - { - core_bits_act[i] -= overflow_bits_ch; - overflow_bits -= overflow_bits_ch; - } - - core_bits_act[nchan_transport - 1] -= max( 0, overflow_bits ); - } - } - - for ( i = 0; i < nchan_transport; i++ ) - { - core_brates_act[i] = core_bits_act[i] * FRAMES_PER_SEC; - } - - return; -} -#endif diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index cd5fff8afc78fc347a28c048e77d6a16eaf41eae..041a589ee3895ad58bd43132559a1ff3e966d14d 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,9 +41,26 @@ /*----------------------------------------------------------------------------------* - * Declaration of ISm common (encoder & decoder) structure + * Declaration of ISM common (encoder & decoder) structure *----------------------------------------------------------------------------------*/ +#ifdef FIX_379_ANGLE +typedef struct +{ + int16_t last_angle1_idx; /* last frame index of coded azimuth/yaw */ + int16_t angle1_diff_cnt; /* FEC counter of consecutive differentially azimuth/yaw coded frames */ + int16_t last_angle2_idx; /* last frame index of coded elevation/pitch */ + int16_t angle2_diff_cnt; /* FEC counter of consecutive differentially elevation/pitch coded frames */ +} ISM_METADATA_ANGLE, *ISM_METADATA_ANGLE_HANDLE; +#else +typedef struct +{ + int16_t last_azimuth_idx; /* last frame index of coded azimuth */ + int16_t azimuth_diff_cnt; /* FEC counter of consecutive differentially azimuth coded frames */ + int16_t last_elevation_idx; /* last frame index of coded elevation */ + int16_t elevation_diff_cnt; /* FEC counter of consecutive differentially elevation coded frames */ +} ISM_METADATA_ANGLE, *ISM_METADATA_ANGLE_HANDLE; +#endif /* ISM metadata handle (storage for one frame of read ISM metadata) */ typedef struct { @@ -52,11 +69,24 @@ typedef struct float azimuth; /* azimuth value read from the input metadata file */ float elevation; /* azimuth value read from the input metadata file */ - - int16_t last_azimuth_idx; /* last frame index of coded azimuth */ - int16_t azimuth_diff_cnt; /* FEC counter of consecutive differentially azimuth coded frames */ - int16_t last_elevation_idx; /* last frame index of coded elevation */ - int16_t elevation_diff_cnt; /* FEC counter of consecutive differentially elevation coded frames */ + float radius; + float yaw; /* azimuth orientation value read from the input metadata file */ + float pitch; /* elevation orientation value read from the input metadata file */ +#ifdef FIX_379_ANGLE + ISM_METADATA_ANGLE position_angle; /* Angle structs for azimuth and elevation */ + ISM_METADATA_ANGLE orientation_angle; /* Angle structs for yaw and pitch */ +#else + ISM_METADATA_ANGLE angle[2]; /* Angle structs for [0] azimuth/elevation and [1] yaw/pitch */ +#endif + int16_t last_radius_idx; /* last frame index of coded radius */ + int16_t radius_diff_cnt; /* FEC counter of consecutive differentially radius coded frames */ + +#ifdef DISCRETE_ISM_DTX_CNG + float last_azimuth; /* MD smoothing in DTX- last Q azimuth value */ + float last_elevation; /* MD smoothing in DTX - last Q elevation value */ + float last_true_azimuth; /* MD smoothing in DTX- last true Q azimuth value */ + float last_true_elevation; /* MD smoothing in DTX- last true Q elevation value */ +#endif } ISM_METADATA_FRAME, *ISM_METADATA_HANDLE; @@ -124,12 +154,15 @@ typedef struct /*----------------------------------------------------------------------------------* * PARAMETRIC ISM encoder/decoder (common) structure *----------------------------------------------------------------------------------*/ + typedef struct ivas_param_ism_data_structure { int16_t nbands; int16_t nblocks[MAX_PARAM_ISM_NBANDS]; int16_t band_grouping[MAX_PARAM_ISM_NBANDS + 1]; +#ifndef NCHAN_ISM_PARAMETER int16_t num_obj; +#endif int16_t azi_index[MAX_NUM_OBJECTS]; int16_t ele_index[MAX_NUM_OBJECTS]; @@ -187,7 +220,7 @@ typedef struct ivas_band_coeffs_ind_t typedef struct ivas_spar_md_t { - ivas_band_coeffs_t band_coeffs[IVAS_MAX_NUM_BANDS * MAX_PARAM_SPATIAL_SUBFRAMES]; + ivas_band_coeffs_t *band_coeffs; ivas_band_coeffs_ind_t band_coeffs_idx[IVAS_MAX_NUM_BANDS]; int16_t num_bands; float min_max[2]; @@ -220,7 +253,7 @@ typedef struct ivas_quant_strat_t } ivas_quant_strat_t; -typedef struct ivas_spar_foa_md_com_cfg +typedef struct ivas_spar_md_com_cfg { int16_t max_freq_per_chan[IVAS_SPAR_MAX_CH]; int16_t num_dmx_chans_per_band[IVAS_MAX_NUM_BANDS]; @@ -228,7 +261,6 @@ typedef struct ivas_spar_foa_md_com_cfg int16_t active_w; int16_t remix_unmix_order; ivas_quant_strat_t quant_strat[MAX_QUANT_STRATS]; - int16_t gen_bs; int16_t quant_strat_bits; int16_t nchan_transport; int16_t num_quant_strats; @@ -240,7 +272,7 @@ typedef struct ivas_spar_foa_md_com_cfg int16_t planarCP; int16_t num_umx_chs; -} ivas_spar_foa_md_com_cfg; +} ivas_spar_md_com_cfg; /* arithmetic coder structures */ @@ -269,19 +301,6 @@ typedef struct ivas_huff_models_t } ivas_huff_models_t; -typedef struct ivas_arith_consts_t -{ - ivas_freq_models_t pred_r; - ivas_freq_models_t drct_r; - ivas_freq_models_t decd_r; -} ivas_arith_consts_t; - -typedef struct ivas_huff_const_t -{ - ivas_huff_models_t pred_r; - ivas_huff_models_t drct_r; - ivas_huff_models_t decd_r; -} ivas_huff_consts_t; /* Entropy coder structures */ typedef struct ivas_huffman_cfg_t @@ -328,7 +347,6 @@ typedef struct ivas_huff_coeffs_t /* AGC structures */ typedef struct ivas_agc_chan_data_t { - int16_t gainException; int16_t absGainExp; int16_t absGainExpCurr; @@ -364,13 +382,6 @@ typedef struct ivas_cov_smooth_cfg_t } ivas_cov_smooth_cfg_t; -typedef struct ivas_cov_smooth_in_buf_t -{ - float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - int16_t num_ch; - int16_t reset_cov; - -} ivas_cov_smooth_in_buf_t; /* SPAR bitrate constant table structure */ typedef struct ivas_spar_br_table_t @@ -381,14 +392,15 @@ typedef struct ivas_spar_br_table_t int16_t bwidth; int16_t fpcs; int16_t nchan_transport; - ivas_spar_foa_pmx_strings_t dmx_str; + ivas_spar_pmx_strings_t dmx_str; int16_t active_w; int16_t tmode; - int32_t evs_brs[FOA_CHANNELS][3]; + int32_t core_brs[FOA_CHANNELS][3]; int16_t q_lvls[MAX_QUANT_STRATS][NUM_MD_Q_COEFS_SET]; int16_t td_ducking; int16_t agc_bits_ch_idx; /* 0-3, Indicates core-coder channel index from which AGC bits have been taken from*/ int16_t usePlanarCoeff; + } ivas_spar_br_table_t; @@ -490,6 +502,7 @@ typedef struct ivas_qdirection_band_data_struct uint16_t elevation_index[MAX_PARAM_SPATIAL_SUBFRAMES]; float q_azimuth[MAX_PARAM_SPATIAL_SUBFRAMES]; float q_elevation[MAX_PARAM_SPATIAL_SUBFRAMES]; + } IVAS_QDIRECTION_BAND_DATA; typedef struct ivas_qdirection_band_coherence_data_struct @@ -541,7 +554,8 @@ typedef struct ivas_masa_qmetadata_frame_struct /* Status values on metadata quality */ int16_t ec_flag; float dir_comp_ratio; - uint8_t is_masa_type_format; // VE: use 'ivas_format' instead + uint8_t is_masa_ivas_format; + } IVAS_QMETADATA, *IVAS_QMETADATA_HANDLE; @@ -673,6 +687,32 @@ typedef struct ivas_trans_det_state_t } ivas_trans_det_state_t; +/*----------------------------------------------------------------------------------* + * Time domain decorrelator + *----------------------------------------------------------------------------------*/ + +typedef struct ivas_td_decorr_APD_filt_state_t +{ + int16_t order[IVAS_MAX_DECORR_APD_SECTIONS]; + int16_t idx[IVAS_MAX_DECORR_APD_SECTIONS]; + float coeffs[IVAS_MAX_DECORR_APD_SECTIONS]; + float *state[IVAS_MAX_DECORR_APD_SECTIONS]; + +} ivas_td_decorr_APD_filt_state_t; + +typedef struct ivas_td_decorr_state_t +{ + ivas_trans_det_state_t *pTrans_det; + float *look_ahead_buf; + ivas_td_decorr_APD_filt_state_t APD_filt_state[IVAS_MAX_DECORR_CHS]; + + int16_t num_apd_outputs; + int16_t num_apd_sections; + int16_t ducking_flag; + +} ivas_td_decorr_state_t; + + /*----------------------------------------------------------------------------------* * Filter Bank (FB) structures *----------------------------------------------------------------------------------*/ @@ -705,8 +745,8 @@ typedef struct ivas_fb_bin_to_band_data_t float *pFb_bin_to_band[IVAS_MAX_NUM_FB_BANDS]; const int16_t *pFb_start_bin_per_band; const int16_t *pFb_active_bins_per_band; - float pp_cldfb_weights_per_spar_band[CLDFB_NO_CHANNELS_MAX][IVAS_MAX_NUM_FB_BANDS]; /* weights for linear combination of parameters from different spar bands*/ - int16_t p_spar_start_bands[CLDFB_NO_CHANNELS_MAX]; /* the first spar band per CLFB band when the weight is > 0 */ + float pp_cldfb_weights_per_spar_band[CLDFB_NO_CHANNELS_MAX][IVAS_MAX_NUM_FB_BANDS]; /* weights for linear combination of parameters from different SPAR bands*/ + int16_t p_spar_start_bands[CLDFB_NO_CHANNELS_MAX]; /* the first SPAR band per CLFB band when the weight is > 0 */ int16_t p_cldfb_map_to_spar_band[CLDFB_NO_CHANNELS_MAX]; /* a direct mapping from CLDFB band to SPAR band */ int16_t p_short_stride_start_bin_per_band[IVAS_MAX_NUM_FB_BANDS]; int16_t p_short_stride_num_bins_per_band[IVAS_MAX_NUM_FB_BANDS]; @@ -749,7 +789,6 @@ typedef struct ivas_fb_mixer_state_structure float cldfb_cross_fade[CLDFB_NO_COL_MAX]; int16_t cldfb_cross_fade_start; int16_t cldfb_cross_fade_end; - int16_t cldfb_latency; int16_t first_frame[IVAS_SPAR_MAX_CH]; diff --git a/lib_com/ivas_stereo_dft_com.c b/lib_com/ivas_stereo_dft_com.c index 918fd27b356378a66a9e3a414d6affe2520f2ec7..1b7f0101efec5b88bfef9aeda897fb03c2423187 100644 --- a/lib_com/ivas_stereo_dft_com.c +++ b/lib_com/ivas_stereo_dft_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "ivas_prot.h" #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- * stereo_dft_config() @@ -82,7 +82,7 @@ void stereo_dft_config( hConfig->res_cod_mode = STEREO_DFT_RES_COD_OFF; } } - else if ( brate == IVAS_SID_4k4 ) + else if ( brate == IVAS_SID_5k2 ) { *bits_frame_nominal = SID_2k40 / FRAMES_PER_SEC; if ( hConfig != NULL ) diff --git a/lib_com/ivas_stereo_eclvq_com.c b/lib_com/ivas_stereo_eclvq_com.c index 76fcff139573a788984419435de761abd45fb3df..ff78a66eba27d9972f2a72ddb29ed072418d6d3f 100644 --- a/lib_com/ivas_stereo_eclvq_com.c +++ b/lib_com/ivas_stereo_eclvq_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include "ivas_cnst.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- * ECSQ_init_instance() diff --git a/lib_com/ivas_stereo_ica_com.c b/lib_com/ivas_stereo_ica_com.c index b35c438d2edee59b51bc853ecc3d5427fd0f73d2..f2fd09eca313f023215b7eb1cbff33a5c0d9c2c4 100644 --- a/lib_com/ivas_stereo_ica_com.c +++ b/lib_com/ivas_stereo_ica_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "rom_com.h" #include "ivas_rom_com.h" diff --git a/lib_com/ivas_stereo_mdct_bands_com.c b/lib_com/ivas_stereo_mdct_bands_com.c index 16149941e4e4f17f8b729b4ebad123ba30a70fa2..19a1295f2de1c68ac3819f9a031e474b97218f6f 100644 --- a/lib_com/ivas_stereo_mdct_bands_com.c +++ b/lib_com/ivas_stereo_mdct_bands_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "ivas_prot.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local union @@ -225,6 +225,9 @@ void stereo_mdct_init_igf_start_band( { int16_t i, bitRateIndex, igfStartLine; const int16_t *swb_offset; +#ifdef DEBUGGING + stbParams->sfbIgfStart = 0; +#endif bitRateIndex = IGF_MapBitRateToIndex( element_brate, bwidth, IVAS_CPE_MDCT, 0 ); swb_offset = &swb_offset_LB_new[bitRateIndex][1]; diff --git a/lib_com/ivas_stereo_mdct_stereo_com.c b/lib_com/ivas_stereo_mdct_stereo_com.c index 7852d678beef1613cd5fdef0f5983d6b0d97ee61..c9151b72df87f1e9d08b63734f7177c668f85579 100644 --- a/lib_com/ivas_stereo_mdct_stereo_com.c +++ b/lib_com/ivas_stereo_mdct_stereo_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,7 +34,7 @@ #include "options.h" #include "ivas_cnst.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include /*-------------------------------------------------------------------* @@ -44,16 +44,22 @@ *-------------------------------------------------------------------*/ void splitAvailableBits( - const int16_t total_bits, /* i : total available bits for TCX coding */ - const int16_t split_ratio, /* i : split ratio */ - int16_t *bits_ch0, /* o : bits for channel 0 */ - int16_t *bits_ch1 /* o : bits for channel 1 */ + const int16_t total_bits, /* i : total available bits for TCX coding */ + const int16_t split_ratio, /* i : split ratio */ + const int16_t isSBAStereoMode, /* i : signal core coding for SBA */ + int16_t *bits_ch0, /* o : bits for channel 0 */ + int16_t *bits_ch1 /* o : bits for channel 1 */ ) { assert( split_ratio >= 1 && split_ratio < SMDCT_BITRATE_RATIO_RANGE ); *bits_ch0 = split_ratio * total_bits / SMDCT_BITRATE_RATIO_RANGE; - *bits_ch1 = total_bits + 0 - *bits_ch0; + /* for SBA mode bias the distribution towards the W channel */ + if ( split_ratio < 7 && isSBAStereoMode ) + { + *bits_ch0 += (int16_t) ( 0.2 * *bits_ch0 ); + } + *bits_ch1 = total_bits - *bits_ch0; return; } diff --git a/lib_com/ivas_stereo_psychlpc_com.c b/lib_com/ivas_stereo_psychlpc_com.c index 7093a9109349c1bc02fc7a9a2e63a7af3ad3be3d..aa24ef6b80bea06369a7a6028d11f14a2f83138f 100644 --- a/lib_com/ivas_stereo_psychlpc_com.c +++ b/lib_com/ivas_stereo_psychlpc_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,7 @@ #include "ivas_prot.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include /*-------------------------------------------------------------------* @@ -68,17 +68,14 @@ static void SpectrumWeighting_Init( * initialize a PsychoacousticParameters structure *-------------------------------------------------------------------*/ -#ifndef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT -static -#endif - ivas_error - PsychoacousticParameters_Init( - const int32_t sr_core, /* i : sampling rate of core-coder */ - const int16_t nBins, /* i : Number of bins (spectral lines) */ - const int8_t nBands, /* i : Number of spectrum subbands */ - const int16_t isTCX20, /* i : Flag indicating if the subband division is for TCX20 or TCX10 */ - const int16_t isWarped, /* i : Flag indicating if the scale is linear or warped */ - PsychoacousticParameters *pPsychParams ) +ivas_error +PsychoacousticParameters_Init( + const int32_t sr_core, /* i : sampling rate of core-coder */ + const int16_t nBins, /* i : Number of bins (spectral lines) */ + const int8_t nBands, /* i : Number of spectrum subbands */ + const int16_t isTCX20, /* i : Flag indicating if the subband division is for TCX20 or TCX10 */ + const int16_t isWarped, /* i : Flag indicating if the scale is linear or warped */ + PsychoacousticParameters *pPsychParams ) { if ( pPsychParams == NULL ) diff --git a/lib_com/ivas_stereo_td_bit_alloc.c b/lib_com/ivas_stereo_td_bit_alloc.c index 7d5b0afb5574e170a248273848f8925ce0ab090f..8b93558b219ea63fce4c737e2436d6221ff40ad0 100644 --- a/lib_com/ivas_stereo_td_bit_alloc.c +++ b/lib_com/ivas_stereo_td_bit_alloc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "ivas_rom_com.h" #include "ivas_cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_dec/ivas_td_decorr.c b/lib_com/ivas_td_decorr.c similarity index 87% rename from lib_dec/ivas_td_decorr.c rename to lib_com/ivas_td_decorr.c index 29b748e4c704dc0f352e0a813e3835db7306f3ce..23620b3b2db5dc6db7e83828c615efef98faba5e 100644 --- a/lib_dec/ivas_td_decorr.c +++ b/lib_com/ivas_td_decorr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #endif #include "math.h" #include -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -67,7 +67,7 @@ static const float ivas_hadamard_decorr_APD_coeff[IVAS_APD_16_SECT][IVAS_APD_16_ /* For R = 3.^([0:obj.parm_APD_nSections-1]/4); */ -const float ivas_three_pow_frac[IVAS_MAX_DECORR_APD_SECTIONS] = { +static const float ivas_three_pow_frac[IVAS_MAX_DECORR_APD_SECTIONS] = { 1.000000000000000f, 1.316074013710022f, 1.732050776481628f, @@ -96,83 +96,83 @@ static ivas_error ivas_td_decorr_init( ivas_td_decorr_state_t *hTdDecorr, const /*------------------------------------------------------------------------- - * ivas_spar_td_decorr_dec_open() + * ivas_td_decorr_dec_open() * - * Allocate and initialize SPAR time domain decorrelator handle + * Allocate and initialize time domain decorrelator handle *------------------------------------------------------------------------*/ -ivas_error ivas_spar_td_decorr_dec_open( - ivas_td_decorr_state_t **hTdDecorr, /* i/o: SPAR Covar. decoder handle */ - const int32_t output_Fs, /* i : output sampling rate */ - const int16_t nchan_internal, /* i : number of internal channels */ - const int16_t ducking_flag /* i : ducking flag */ +ivas_error ivas_td_decorr_dec_open( + ivas_td_decorr_state_t **hTdDecorr, /* i/o: TD decorrelator handle */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t nchan_internal, /* i : number of internal channels */ + const int16_t ducking_flag /* i : ducking flag */ ) { int16_t i, j, len; int16_t num_out_chans; - ivas_td_decorr_state_t *hCovState; + ivas_td_decorr_state_t *hTdDecorr_loc; ivas_error error; num_out_chans = nchan_internal - 1; error = IVAS_ERR_OK; - if ( ( hCovState = (ivas_td_decorr_state_t *) count_malloc( sizeof( ivas_td_decorr_state_t ) ) ) == NULL ) + if ( ( hTdDecorr_loc = (ivas_td_decorr_state_t *) malloc( sizeof( ivas_td_decorr_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV decoder" ); } - if ( ( hCovState->look_ahead_buf = (float *) count_malloc( sizeof( float ) * (int16_t) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ) ) ) == NULL ) + if ( ( hTdDecorr_loc->look_ahead_buf = (float *) malloc( sizeof( float ) * (int16_t) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV decoder" ); } - set_f( hCovState->look_ahead_buf, 0, (int16_t) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ) ); + set_f( hTdDecorr_loc->look_ahead_buf, 0, (int16_t) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ) ); - hCovState->num_apd_sections = ivas_get_APD_filt_orders( num_out_chans, output_Fs, hCovState->APD_filt_state[0].order ); + hTdDecorr_loc->num_apd_sections = ivas_get_APD_filt_orders( num_out_chans, output_Fs, hTdDecorr_loc->APD_filt_state[0].order ); for ( j = 0; j < num_out_chans; j++ ) { - for ( i = 0; i < hCovState->num_apd_sections; i++ ) + for ( i = 0; i < hTdDecorr_loc->num_apd_sections; i++ ) { - len = hCovState->APD_filt_state[0].order[i]; + len = hTdDecorr_loc->APD_filt_state[0].order[i]; - if ( ( hCovState->APD_filt_state[j].state[i] = (float *) count_malloc( sizeof( float ) * len ) ) == NULL ) + if ( ( hTdDecorr_loc->APD_filt_state[j].state[i] = (float *) malloc( sizeof( float ) * len ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV decoder" ); } - set_f( hCovState->APD_filt_state[j].state[i], 0, len ); + set_f( hTdDecorr_loc->APD_filt_state[j].state[i], 0, len ); } } - ivas_td_decorr_init( hCovState, num_out_chans, ducking_flag ); + ivas_td_decorr_init( hTdDecorr_loc, num_out_chans, ducking_flag ); if ( ducking_flag ) { - if ( ( error = ivas_spar_transient_det_open( &hCovState->pTrans_det, output_Fs ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_transient_det_open( &hTdDecorr_loc->pTrans_det, output_Fs ) ) != IVAS_ERR_OK ) { return error; } } else { - hCovState->pTrans_det = NULL; + hTdDecorr_loc->pTrans_det = NULL; } - *hTdDecorr = hCovState; + *hTdDecorr = hTdDecorr_loc; return error; } /*------------------------------------------------------------------------- - * ivas_spar_td_decorr_dec_close() + * ivas_td_decorr_dec_close() * - * Deallocate SPAR time domain decorrelator handle + * Deallocate time domain decorrelator handle *------------------------------------------------------------------------*/ -void ivas_spar_td_decorr_dec_close( - ivas_td_decorr_state_t **hTdDecorr /* i/o: SPAR Covar. decoder handle */ +void ivas_td_decorr_dec_close( + ivas_td_decorr_state_t **hTdDecorr /* i/o: TD decorrelator handle */ ) { int16_t i, j; @@ -182,24 +182,24 @@ void ivas_spar_td_decorr_dec_close( return; } - count_free( ( *hTdDecorr )->look_ahead_buf ); + free( ( *hTdDecorr )->look_ahead_buf ); ( *hTdDecorr )->look_ahead_buf = NULL; for ( j = 0; j < ( *hTdDecorr )->num_apd_outputs; j++ ) { for ( i = 0; i < ( *hTdDecorr )->num_apd_sections; i++ ) { - count_free( ( *hTdDecorr )->APD_filt_state[j].state[i] ); + free( ( *hTdDecorr )->APD_filt_state[j].state[i] ); ( *hTdDecorr )->APD_filt_state[j].state[i] = NULL; } } if ( ( *hTdDecorr )->pTrans_det != NULL ) { - ivas_spar_transient_det_close( &( *hTdDecorr )->pTrans_det ); + ivas_transient_det_close( &( *hTdDecorr )->pTrans_det ); } - count_free( ( *hTdDecorr ) ); + free( ( *hTdDecorr ) ); ( *hTdDecorr ) = NULL; return; diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index f5b75dd5f61b0d07fd025e071c9d945a680690c8..b75c08379121fbeab38909b5b787ca0fec8a31e2 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_rom_com.h" /*--------------------------------------------------------------- @@ -510,32 +510,39 @@ float lin_interp( * Ensure the input value is within the given limits *-------------------------------------------------------------------*/ -void check_bounds( - float *value, /* i/o: Input value / Adjusted value */ - const float low, /* i : Low limit */ - const float high /* i : High limit */ +/*! r: Adjusted value */ +float check_bounds( + const float value, /* i : Input value */ + const float low, /* i : Low limit */ + const float high /* i : High limit */ ) { - *value = min( max( *value, low ), high ); + float value_adj; - return; + value_adj = min( max( value, low ), high ); + + return value_adj; } + /*-------------------------------------------------------------------* * check_bounds_s() * * Ensure the input value is within the given limits *-------------------------------------------------------------------*/ -void check_bounds_s( - int16_t *value, /* i/o: Input value / Adjusted value */ - const int16_t low, /* i : Low limit */ - const int16_t high /* i : High limit */ +/*! r: Adjusted value */ +int16_t check_bounds_s( + const int16_t value, /* i : Input value */ + const int16_t low, /* i : Low limit */ + const int16_t high /* i : High limit */ ) { - *value = min( max( *value, low ), high ); + int16_t value_adj; - return; + value_adj = min( max( value, low ), high ); + + return value_adj; } @@ -947,11 +954,11 @@ void v_multc_acc( void lls_interp_n( - float x[], /* i/o: input/output vector */ - const int16_t N, /* i : length of the input vector */ - float *a, /* o : calculated slope */ - float *b, /* o : calculated offset */ - int16_t upd /* i : use 1 to update x[] with the interpolated output */ + float x[], /* i/o: input/output vector */ + const int16_t N, /* i : length of the input vector */ + float *a, /* o : calculated slope */ + float *b, /* o : calculated offset */ + const int16_t upd /* i : use 1 to update x[] with the interpolated output */ ) { int16_t i; @@ -990,6 +997,25 @@ void lls_interp_n( return; } +/* helper function for panning_wrap_angles */ +static float wrap_azi( + const float azi_deg ) +{ + float azi = azi_deg; + + /* Wrap azimuth value */ + while ( azi > 180 ) + { + azi -= 360.0f; + } + + while ( azi <= -180 ) + { + azi += 360; + } + + return azi; +} /*-------------------------------------------------------------------* * panning_wrap_angles() @@ -999,7 +1025,6 @@ void lls_interp_n( * elevation = [-90, 90] * Considers direction changes from large elevation values *-------------------------------------------------------------------*/ - void panning_wrap_angles( const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */ @@ -1012,56 +1037,52 @@ void panning_wrap_angles( azi = azi_deg; ele = ele_deg; - /* Special case when elevation is a multiple of 90; azimuth is irrelevant */ - if ( ( ele != 0 ) && ( fmodf( ele, 90 ) == 0 ) ) + if ( fabsf( ele ) < 90 ) { - azi = 0; - while ( fabsf( ele ) > 90 ) - { - ele -= 360; - } + *ele_wrapped = ele; + *azi_wrapped = wrap_azi( azi ); + return; } else { - /* Wrap elevation and adjust azimuth accordingly */ - while ( fabsf( ele ) > 90 ) + /* Special case when elevation is a multiple of 90; azimuth is irrelevant */ + if ( ( fmodf( ele, 90 ) == 0 ) && ( fmodf( ele, 180 ) != 0 ) ) { - /* Flip to other hemisphere */ - azi += 180; - - /* Compensate elevation accordingly */ - if ( ele > 90 ) + *azi_wrapped = 0; + while ( ele > 90 ) { - ele -= 180; + ele -= 360; } - else if ( ele < -90 ) + while ( ele < -90 ) { - ele += 180; + ele += 360; } + *ele_wrapped = ele; } - - /* Wrap azimuth value */ - while ( fabsf( azi ) > 180 ) + else { - azi = fmodf( azi + 180, 360 ); - if ( azi < 0 ) + /* Wrap elevation and adjust azimuth accordingly */ + while ( fabsf( ele ) > 90 ) { - azi += 360; + /* Flip to other hemisphere */ + azi += 180; + + /* Compensate elevation accordingly */ + if ( ele > 90 ) + { + ele = 180 - ele; + } + else if ( ele < -90 ) + { + ele = -180 - ele; + } } - azi -= 180; + *azi_wrapped = wrap_azi( azi ); + *ele_wrapped = ele; } - } - /* Set -180 to 180 for deduplication purposes; angles are otherwise identical */ - if ( azi == -180 ) - { - azi = 180; + return; } - - *azi_wrapped = azi; - *ele_wrapped = ele; - - return; } /*-------------------------------------------------------------------------* @@ -1165,8 +1186,7 @@ int16_t is_SIDrate( if ( ( ivas_total_brate == SID_1k75 ) || ( ivas_total_brate == SID_2k40 ) || - ( ivas_total_brate == IVAS_SID_4k4 ) || - ( ivas_total_brate == IVAS_SID_5k ) ) + ( ivas_total_brate == IVAS_SID_5k2 ) ) { sid_rate_flag = 1; } diff --git a/lib_com/ivas_transient_det.c b/lib_com/ivas_transient_det.c index 0b398ec9d156f7c5bb9bebf9e4d8e6fa0172e2c0..1e8f53c7ca5a1d17b7d49501169deaf7634914a6 100644 --- a/lib_com/ivas_transient_det.c +++ b/lib_com/ivas_transient_det.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,7 @@ #include "debug.h" #endif #include "math.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" #include "ivas_cnst.h" #include "ivas_prot.h" @@ -84,8 +84,8 @@ *-----------------------------------------------------------------------------------------*/ static void ivas_transient_det_init( - ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ - const int32_t sampling_rate /* i : sampling rate */ + ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ + const int32_t sampling_rate /* i : sampling rate */ ) { float filt_coeff_arr[3][IVAS_BIQUAD_FILT_LEN << 1] = { { 0 } }; @@ -159,19 +159,19 @@ static void ivas_transient_det_init( /*------------------------------------------------------------------------- - * ivas_spar_transient_det_open() + * ivas_transient_det_open() * * Allocate and initialize SPAR TD handle *------------------------------------------------------------------------*/ -ivas_error ivas_spar_transient_det_open( - ivas_trans_det_state_t **hTranDet_in, /* i/o: SPAR TD handle */ - const int32_t sampling_rate /* i : sampling rate */ +ivas_error ivas_transient_det_open( + ivas_trans_det_state_t **hTranDet_in, /* i/o: Transient detector handle */ + const int32_t sampling_rate /* i : sampling rate */ ) { ivas_trans_det_state_t *hTranDet; - if ( ( hTranDet = (ivas_trans_det_state_t *) count_malloc( sizeof( ivas_trans_det_state_t ) ) ) == NULL ) + if ( ( hTranDet = (ivas_trans_det_state_t *) malloc( sizeof( ivas_trans_det_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR TD\n" ); } @@ -185,13 +185,13 @@ ivas_error ivas_spar_transient_det_open( /*------------------------------------------------------------------------- - * ivas_spar_transient_det_close() + * ivas_transient_det_close() * - * Deallocate and initialize SPAR TD handle + * Deallocate and initialize Transient detector handle *------------------------------------------------------------------------*/ -void ivas_spar_transient_det_close( - ivas_trans_det_state_t **hTranDet /* i/o: SPAR TD handle */ +void ivas_transient_det_close( + ivas_trans_det_state_t **hTranDet /* i/o: Transient detector handle */ ) { if ( hTranDet == NULL || *hTranDet == NULL ) @@ -199,7 +199,7 @@ void ivas_spar_transient_det_close( return; } - count_free( *hTranDet ); + free( *hTranDet ); *hTranDet = NULL; return; @@ -211,28 +211,39 @@ void ivas_spar_transient_det_close( * * Transient detection process call *-----------------------------------------------------------------------------------------*/ - -int16_t ivas_transient_det_process( - ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ - float *pIn_pcm, /* i : input audio channels */ - const int16_t frame_len /* i : frame length in samples */ +void ivas_transient_det_process( + ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ + float *pIn_pcm, /* i : input audio channels */ + const int16_t frame_len, /* i : frame length in samples */ + int16_t transient_det[2] /* o: transient det outputs */ ) { + float in_duck_gain[L_FRAME48k]; + int16_t num_sf, sf, sf_samp, idx; float mem = hTranDet->in_duck_gain; - int16_t trans; - ivas_td_decorr_get_ducking_gains( hTranDet, pIn_pcm, NULL, NULL, frame_len, IVAS_TDET_ONLY ); + ivas_td_decorr_get_ducking_gains( hTranDet, pIn_pcm, in_duck_gain, NULL, frame_len, IVAS_TDET_ONLY ); + transient_det[0] = 0; + transient_det[1] = 0; if ( mem - hTranDet->in_duck_gain > IVAS_TDET_PARM_TRANS_THR ) { - trans = 1; + transient_det[0] = 1; } - else + + num_sf = 16; + sf_samp = frame_len / num_sf; + for ( sf = 1; sf <= num_sf; sf++ ) { - trans = 0; + idx = ( sf_samp * sf ) - 1; + if ( ( mem - in_duck_gain[idx] ) > ( IVAS_TDET_PARM_TRANS_THR * 1.1f ) ) + { + transient_det[1] = 1; + } + mem = in_duck_gain[idx]; } - return trans; + return; } @@ -269,7 +280,7 @@ static float ivas_calc_duck_gain( *-----------------------------------------------------------------------------------------*/ void ivas_td_decorr_get_ducking_gains( - ivas_trans_det_state_t *hTranDet, + ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ float *pIn_pcm, float *pIn_duck_gains, float *pOut_duck_gains, @@ -301,11 +312,12 @@ void ivas_td_decorr_get_ducking_gains( /* env slow */ ivas_filter_process( &hTranDet->env_slow, e_slow, frame_len ); - if ( tdet_flag == IVAS_TDET_ONLY ) + if ( tdet_flag ) { for ( i = 0; i < frame_len; i++ ) { in_duck_gain = ivas_calc_duck_gain( in_duck_gain, in_duck_coeff, e_slow[i], e_fast[i], duck_mult_fac ); + pIn_duck_gains[i] = in_duck_gain; } hTranDet->in_duck_gain = in_duck_gain; } diff --git a/lib_com/lag_wind.c b/lib_com/lag_wind.c index dba9f04de489a7a62cc79b107d121838f32a0e1b..c4c5e803beedaf2433793bce428f329326f7978e 100644 --- a/lib_com/lag_wind.c +++ b/lib_com/lag_wind.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_com/lerp.c b/lib_com/lerp.c index 4708dc5ca46a8c9159fb728662830596da90d7ad..1172710313bbb4057ca425e54c469f9260f74c4b 100644 --- a/lib_com/lerp.c +++ b/lib_com/lerp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------* diff --git a/lib_com/limit_t0.c b/lib_com/limit_t0.c index 33a3ba42316a8c64a178dfffe4ae7482f3bdcb42..0a844bbc5d72755f841126249cc52eeb5bb78682 100644 --- a/lib_com/limit_t0.c +++ b/lib_com/limit_t0.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------* * Local constants diff --git a/lib_com/logqnorm.c b/lib_com/logqnorm.c index 50ecd83898ee302a758ddb6c91b9e74de9382158..c8185dd5a20322a4be7941cecf359a6e91d647b8 100644 --- a/lib_com/logqnorm.c +++ b/lib_com/logqnorm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "prot.h" /* Function prototypes */ -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * logqnorm() diff --git a/lib_com/longarith.c b/lib_com/longarith.c index 2e5604d277ce8282485ac3b3e0fa3ded09c7ffb1..01a20c8417ea0091294f13b06829e567afcba36f 100644 --- a/lib_com/longarith.c +++ b/lib_com/longarith.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_com/low_rate_band_att.c b/lib_com/low_rate_band_att.c index 2ff62af41b8485eb9c0b751ec4beb7d14e51088f..393cae5ff24ba1eab58e016dc99736ad53d2e87b 100644 --- a/lib_com/low_rate_band_att.c +++ b/lib_com/low_rate_band_att.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * fine_gain_pred() diff --git a/lib_com/lpc_tools.c b/lib_com/lpc_tools.c index 7e84d83fb21f6e548a137dd855b90e3736759c8b..82c8cddbdac14a76317683c70f83bce9ec7d6efa 100644 --- a/lib_com/lpc_tools.c +++ b/lib_com/lpc_tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants diff --git a/lib_com/lsf_dec_bfi.c b/lib_com/lsf_dec_bfi.c index f6da9ffb21143c504ad7174b61d2169951dab5ba..70506b293c18856de3fad6c631b25648dc8fb9d5 100644 --- a/lib_com/lsf_dec_bfi.c +++ b/lib_com/lsf_dec_bfi.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * routine: lsf_dec_bfi() diff --git a/lib_com/lsf_msvq_ma.c b/lib_com/lsf_msvq_ma.c index 0f091463bd87ee0edca0a245912fe8d657fe4a9c..3396e9fde2ea604d13600ab510207d73dd1ebe71 100644 --- a/lib_com/lsf_msvq_ma.c +++ b/lib_com/lsf_msvq_ma.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "rom_com.h" #include "stl.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * midlsf_dec() diff --git a/lib_com/lsf_tools.c b/lib_com/lsf_tools.c index 3fc93a05f7ed6915b47b871eb53857c80c9a4510..19321e21d9bcea526d92d3f0fc6cebc6be6c87f2 100644 --- a/lib_com/lsf_tools.c +++ b/lib_com/lsf_tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -2079,7 +2079,7 @@ void msvq_dec( start = 0; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP v_add( uq + start, cb[i] + Idx[i] * maxn, uq + start, n ); IF( uq_ind != NULL ) @@ -2090,7 +2090,7 @@ void msvq_dec( uq_ind[start + j] = add( uq_ind[start + j], (Word16) ( cb[i][Idx[i] * maxn + j] * 2.0f * 1.28f ) ); } } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } return; diff --git a/lib_com/lsp_conv_poly.c b/lib_com/lsp_conv_poly.c index 1f882b5e904eb0556dbb31dc1f83d55f8a34f95d..d43d74fb5a8c73e6520a0a48fe1f6b34daa0d118 100644 --- a/lib_com/lsp_conv_poly.c +++ b/lib_com/lsp_conv_poly.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_com/mime.h b/lib_com/mime.h index 7ca2689dcf331a608e0c4cf6a68976cd4240ae0e..56f2fb4db96c6281ff0f0c57484480e56be8dd02 100644 --- a/lib_com/mime.h +++ b/lib_com/mime.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/modif_fs.c b/lib_com/modif_fs.c index a817f0c34865d17ebe2c0da4cb255179d0df3046..f1ae7c61d4571334e597980e53ff09970f80db54 100644 --- a/lib_com/modif_fs.c +++ b/lib_com/modif_fs.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * modify_Fs() @@ -113,7 +113,7 @@ int16_t modify_Fs( } } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* Retrieve and/or calculate the resampling parameters */ fac_num = cfg_ptr->fac_num; fac_den = (int16_t) ( ( cfg_ptr->fin * fac_num ) / cfg_ptr->fout ); @@ -133,7 +133,7 @@ int16_t modify_Fs( signal = signal_tab + 2 * L_FILT_MAX + L_FRAME48k - mem_len - lg; signal_ana = signal; mem_len_ana = mem_len; -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } /*-------------------------------------------------------------------* diff --git a/lib_com/move.h b/lib_com/move.h index f0e8238dec7b80e2e24e664722328923602f79e8..c7bee82cd41d3669da2a06759116db869ce61c29 100644 --- a/lib_com/move.h +++ b/lib_com/move.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/mslvq_com.c b/lib_com/mslvq_com.c index 4d0593ce56e3242437dea0cdbf349df50222493a..48384794aa4f882d3d0eaaa861ca9de8c66cd931 100644 --- a/lib_com/mslvq_com.c +++ b/lib_com/mslvq_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /*-----------------------------------------------------------------* diff --git a/lib_com/nelp.c b/lib_com/nelp.c index 63489ea27e74c0a5170bd68fb151784f369957a8..768b92f915f96879b0a2288a93a529db235d7a8e 100644 --- a/lib_com/nelp.c +++ b/lib_com/nelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * dequantize_uvg() diff --git a/lib_com/options.h b/lib_com/options.h index d5812b3bd9bbdf8311241bfa0e6ed4a329d38235..03b74eb731d05c68536e1071d9c741fe4dd9a924 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,6 @@ /* ################### Start compiler switches ######################## */ #define SUPPORT_JBM_TRACEFILE /* support for JBM tracefile, which is needed for 3GPP objective/subjective testing, but not relevant for real-world implementations */ -#define RAM_COUNTING_TOOL /* tool to automatically count the dynamically alocated static memory consumption */ /* #################### End compiler switches ######################### */ @@ -51,26 +50,25 @@ #ifndef RELEASE #define DEBUGGING /* Activate debugging part of the code */ #endif -/*#define WMOPS*/ /* Activate complexity and memory counters (! the codec must be already instrumented with the WMC Tool (use /ic and /op options) !) */ -/*#define WMOPS_PER_FRAME*/ /* Output complexity in WMOPS per frame to the file "res/wmops" (one float value per frame) */ -/*#define WMOPS_DETAIL*/ /* Activate complexity detail printout for every function. Increases runtime overhead */ -/*#define WMOPS_WC_FRAME_ANALYSIS*/ /* Output WMOPS analysis for worst case frame */ +/*#define WMOPS*/ /* Activate complexity and memory counters */ +/*#define WMOPS_PER_FRAME*/ /* Output per-frame complexity (writes one float value per frame to the file "wmops_analysis") */ +/*#define WMOPS_DETAIL*/ /* Output detailed complexity printout for every function. Increases runtime overhead */ +/*#define WMOPS_WC_FRAME_ANALYSIS*/ /* Output detailed complexity analysis for the worst-case frame */ +/*#define MEM_COUNT_DETAILS*/ /* Output detailed memory analysis for the worst-case frame (writes to the file "mem_analysis.csv") */ #ifdef DEBUGGING -/*#define MEM_COUNT_DETAILS*/ /* RAM counting tool: print per sub-structure details */ - -#define DEBUG_MODE_INFO /* output most important parameters to the subdirectory "res/" */ +/*#define DEBUG_MODE_INFO*/ /* output most important parameters to the subdirectory "res/" */ #ifdef DEBUG_MODE_INFO /*#define DEBUG_MODE_ACELP*/ /* output most important ACELP core parameters to the subdirectory "res/" */ /*#define DEBUG_MODE_TCX*/ /* output most important TCX core parameters to the subdirectory "res/" */ /*#define DEBUG_MODE_DFT*/ /* output most important DFT stereo parameters to the subdirectory "res/" */ /*#define DEBUG_MODE_TD*/ /* output most important TD stereo parameters to the subdirectory "res/ */ -/*#define DEBUG_MODE_DIRAC*/ /* output most important DIRAC parameters to the subdirectory "res/" */ +//#define DEBUG_MODE_DIRAC /* output most important DIRAC parameters to the subdirectory "res/" */ /*#define DEBUG_MODE_MDCT*/ /* output most important MDCT parameters to the subdirectory "res/" */ /*#define DEBUG_MODE_PARAM_MC */ /* output Parametric MC paramters to the subdirectory "res/" */ /*#define DEBUG_MODE_PARAM_ISM*/ /* output Parametric ISM paramters to the subdirectory "res/" */ -#define DEBUG_MODE_INFO_TWEAK /* enable command line switch to specify subdirectory for debug info output inside "./res/" */ +/*#define DEBUG_MODE_INFO_TWEAK*/ /* enable command line switch to specify subdirectory for debug info output inside "./res/" */ /*#define DEBUG_MODE_INFO_PLC */ /* define to output PLC related parameters */ /*#define DEBUG_MODE_INFO_ALLRAD*/ /* define to output generated HOA decoding mtx */ /*#define DEBUG_MODE_LFE */ /* define to output LFE relevant parameters */ @@ -114,9 +112,11 @@ /*#define TDREND_HRTF_TABLE_METHODS*/ /* Enable HRTF lookup from tables, for testing & evaluation. Supply file in table format to use. Note that a suitable HR filter lookup method should be written if the filters sample point grids are not in the formats. */ /*#define TDREND_STANDALONE*/ /* Used when renderer is built in standalone form, without IVAS encoding/decoding (see scripts/object_renderer_standalone). This is just here to ensure this is cleaned out by prepare_instrumentation.sh */ -/*#define DEBUG_SPAR_FOA*/ /* debug SPAR in-out */ +/*#define DEBUG_SBA*/ /* debug DIRAC/SPAR in-out */ +#ifdef DEBUG_SBA /*#define DEBUG_LBR_SBA*/ /* debug low bitrate SBA (SPAR+DirAC) */ -#ifdef DEBUG_SPAR_FOA +/*#define DEBUG_SBA_AUDIO_DUMP*/ /* SBA intermediate audio wav file dumping */ +/*#define DEBUG_SBA_MD_DUMP*/ /* SBA metadata and variable file dumping */ /*#define DEBUG_SPAR_MD_TARGET_TUNING*/ /* SPAR MD target bitrate tuning debug code */ /*#define DEBUG_SPAR_BYPASS_EVS_CODEC*/ /* bypass EVS coding in float precision, emulating EVS encoder/decoder delay */ /*#define DEBUG_SPAR_WRITE_OUT_COV*/ /* write covariance per frame into a text file for verification */ @@ -125,6 +125,7 @@ #endif /*#define SPAR_HOA_DBG*/ /* SPAR HOA debug statements */ /*#define DEBUG_BINAURAL_FILTER_DESIGN*/ /* debugging of Crend binaural filter design */ +#define DEBUG_AGC_ENCODER_CMD_OPTION /* Ability to force enable or disable AGC behaviour in DIRAC/SPAR via command line option */ #endif /* #################### End DEBUGGING switches ############################ */ @@ -134,19 +135,43 @@ #define BASOP_NOGLOB /* Disable global symbols in BASOPs, Overflow/Carry in BASOPs disabled, additional BASOPs in case of Overflow */ #define BITSTREAM_INDICES_MEMORY /* Don't count memory for bitstream Indice at the encoder - it is a temporary solution for development only */ -#define DEC_ICA_DELAY_INTERP /* ICA Decoder Target Delay Interpolation in TD stereo */ #define LSF_RE_USE_SECONDARY_CHANNEL /* TD stereo Secondary channel LSF Q improvement */ #ifdef LSF_RE_USE_SECONDARY_CHANNEL /*#define LSF_RE_USE_SECONDARY_CHANNEL_REUSEMODE */ /* switch to isolate the reuse mode case */ #endif #define DISABLE_ADAP_RES_COD_TMP /* temporary fix for IVAS-403, disables adaptive residual coding */ /*#define ITD_WINNER_GAIN_MODIFY */ /* ITD optimization - WORK IN PROGRESS */ +/*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ +#define FIX_103_RA_PARAMS_PARAM_BIN_REND /* Issue 103: Digest room acoustics parameters for Parametric Binaural Renderer*/ +/*#define SBA_HPF_TUNING_DEC*/ +#define FIX_350_MASA_DELAY_COMP /* Nokia: Issue 350: MASA audio/meta delay compensation */ +#define FIX_MDCT_BASED_BWD /* FhG: fixes for BWD for issues with reaction to transients for MDCT-stereo and MCT */ +#define DISCRETE_ISM_DTX_CNG /* FhG/VA: contribution 15 - DTX/CNG for (discrete) ISM */ +#define NCHAN_ISM_PARAMETER /* VA: make 'nchan_ism' parameter part of st_ivas/hEncoderConfig */ +#define FIX_382_MASA_META_FRAMING_ASYNC /* Nokia: Issue 382: detect potential MASA metadata framing offset */ +#define FIX_386_CORECODER_RECONFIG /* VA: Issue 386: Resolve ToDo comments in CoreCoder reconfig. */ + + +#define SBA2MONO /* FhG: Issue 365: Adapt processing of SBA mono output to be in line with stereo output (less delay, lower complexity) */ +#define FIX_379_EXT_METADATA /* Eri: Extended metadata issues */ +#define FIX_379_ANGLE /* Eri: Extended metadata issues related to angle structure */ + + +#define NOKIA_PARAMBIN_REQULARIZATION /* Nokia: Contribution - Configured reqularization factor for parametric binauralizer. */ +#define NOKIA_ADAPTIVE_BINAURAL_PROTOS /* Nokia: Contribution 28: Adaptive binaural prototypes */ +#define NOKIA_ADAPTIVE_BINAURAL_PROTOS_OPT /* Nokia: enable adaptive binaural prototype complexity optimizations */ + +#define FIX_389_EXT_REND_PCM_SR /* Nokia: Issue 389: Fix assignment of sample rate with PCM input. */ +#define FIX_390_EXT_REND_MASA_META_COPY /* Nokia: Issue 390: Fixes MASA metadata copying to renderer. */ +#define FIX_392_LATE_REVERB /* DLB : Issue 392: keep late reverb by default off when output config is not BINAURAL_ROOM*/ + +#define FIX_ISM_DTX_CLICKS /* FhG: fix for clicks in ISM DTX for inactive to active TCX transitions */ + +#define ISSUE_24_CLEANUP_MCT_LFE /* Issue 24: Cleanup LFE path withing MCT */ + +#define FIX_401_DIRAC_RENDERER_META_READ_INDICES /* Nokia: Issue 401: Fix metadata reading indices in DirAC renderer. */ -/*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ -/*#define FIX_IVAS_185_MDCT_ST_PLC_FADEOUT*/ /* IVAS-185 fix bug in TCX-PLC fadeout for MDCT-Stereo and improve fadeout by fading to background noise instead of white noise */ -/*#define FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10*/ /* IVAS-180 write last overlap mode in TCX10 frames to allow for correct TCX10/TCX5 subframe decomposition in TCX10 frames after a lost frame */ -/*#define FIX_I1_113*/ /* under review : MCT bit distribution optimization for SBA high bitrates*/ #define LBR_SBA /* Contribution 47: Master macro for low bitrate SBA (SPAR+DirAC) */ #ifdef LBR_SBA #define LBR_SBA_DM_COV_FIX /* Covariance smoothing and resetting fixes proposed at higher bitrates */ diff --git a/lib_com/parameter_bitmaping.c b/lib_com/parameter_bitmaping.c index 95d5b77bbe53f2295900696a6a533c959f642452..d722c8a3b326deedd3cde800baf021908ecb55f5 100644 --- a/lib_com/parameter_bitmaping.c +++ b/lib_com/parameter_bitmaping.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include "stat_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /********************************/ @@ -117,9 +117,9 @@ void GetParameters( { ParamBitMap const *const param = ¶msBitMap->params[iParam]; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP pSubStruct = param->GetParamValue( pParameter, index, &value ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /* If a function for encoding/decoding value is defined than it should take care of 0 */ if ( param->fZeroAllowed || ( param->EncodeValue != NULL ) ) { @@ -130,9 +130,9 @@ void GetParameters( *( *pStream )++ = value - 1; } ++*pnSize; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP *pnBits += ( param->nBits != 0 ) ? param->nBits : param->GetNumberOfBits( value, index ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP if ( ( param->pSubParamBitMap != NULL ) && ( value > 0 ) ) { GetParameters( param->pSubParamBitMap, value, ( pSubStruct != NULL ) ? pSubStruct : pParameter, pStream, pnSize, pnBits ); @@ -167,9 +167,9 @@ void SetParameters( /* If a function for encoding/decoding value is defined than it should take care of 0 */ value = *( *pStream )++ + ( param->fZeroAllowed || ( param->EncodeValue != NULL ) ? 0 : 1 ); -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP pSubStruct = param->SetParamValue( pParameter, index, value ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP ++*pnSize; if ( ( param->pSubParamBitMap != NULL ) && ( value > 0 ) ) { @@ -207,9 +207,9 @@ void WriteToBitstream( TEncodeValue EncodeValue; int16_t value; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP nBits = ( param->nBits != 0 ) ? param->nBits : param->GetNumberOfBits( **pStream, index ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP fShiftValue = !param->fZeroAllowed && ( param->EncodeValue == NULL ); EncodeValue = ( param->EncodeValue == NULL ) ? &FixedWidthEncoding : param->EncodeValue; value = PutIntoBitstream( pStream, EncodeValue, index, hBstr, nBits ) + ( fShiftValue ? 1 : 0 ); diff --git a/lib_com/phase_dispersion.c b/lib_com/phase_dispersion.c index 7e1a1a4b14fcf8ff5589d52887ac5b81f4fe6c43..a89b98c152e7c2abc13d180b4377189b25c4a60c 100644 --- a/lib_com/phase_dispersion.c +++ b/lib_com/phase_dispersion.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * phase_dispersion() diff --git a/lib_com/ppp.c b/lib_com/ppp.c index 9008e1b441cb5b74d6ef64f9f3eeacd2c2b32684..73570bbd960bca187f855f5c115e6a91c64948ff 100644 --- a/lib_com/ppp.c +++ b/lib_com/ppp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Interpol_delay() diff --git a/lib_com/pred_lt4.c b/lib_com/pred_lt4.c index 3226c31b5793929dbe65385bef3286b52550aca4..832c7d0dc5353604cdb85bf97c7613020ec18ea1 100644 --- a/lib_com/pred_lt4.c +++ b/lib_com/pred_lt4.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * pred_lt4() diff --git a/lib_com/preemph.c b/lib_com/preemph.c index 32283198cdf420e3ed4531c0100e87cb2f8942d4..5e5eb23416f8c62988a2b24d22c6e3c138f305e1 100644 --- a/lib_com/preemph.c +++ b/lib_com/preemph.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------* * preemph() diff --git a/lib_com/prot.h b/lib_com/prot.h index 9ddf214eb049b1a934375e3b3f734ca89686f5cb..65846708efb7b3d9dfb6e7fb2c665299a3a223ad 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,15 +37,13 @@ #ifndef PROT_H #define PROT_H +#include +#include #include #include "options.h" #ifdef DEBUGGING #include "debug.h" #endif -#include -#ifndef RAM_COUNTING_TOOL -#include -#endif #include "typedef.h" #include "stat_enc.h" #include "stat_dec.h" @@ -55,28 +53,8 @@ #include "ivas_stat_dec.h" #include "cnst.h" #include "stl.h" -#ifdef RAM_COUNTING_TOOL -#include "mem_count.h" -#endif #include "ivas_error_utils.h" -/*----------------------------------------------------------------------------------* - * Prototypes of RAM counting tool macros - *----------------------------------------------------------------------------------*/ - -#ifdef RAM_COUNTING_TOOL -#define count_malloc( n1 ) MALLOC_FCT_CALL( n1 ) -#define count_calloc( n1, n2 ) CALLOC_FCT_CALL( n1, n2 ) -#define count_free( ptr ) FREE_FCT_CALL( ptr ) -#else -#define count_malloc( n1 ) malloc( n1 ) -#define count_calloc( n1, n2 ) calloc( n1, n2 ) -#define count_free( ptr ) free( ptr ) -#endif - -#define dynamic_malloc( n1 ) malloc( n1 ) -#define dynamic_calloc( n1, n2 ) calloc( n1, n2 ) -#define dynamic_free( n1 ) free( n1 ) /*----------------------------------------------------------------------------------* * Prototypes of global macros @@ -261,13 +239,6 @@ void AGC_dec( const int16_t n /* i : vector size */ ); -/*! r: thresholded value */ -float thr_f( - const float x, /* i : input value */ - const float x_min, /* i : lower thresholod */ - const float x_max /* o : upper threshold */ -); - /*! r: index of the maximum value in the input vector */ int16_t maximum( const float *vec, /* i : input vector */ @@ -673,20 +644,6 @@ void evs_dec_previewFrame( ); -void read_indices_from_djb( - Decoder_State *st, /* i/o: decoder state structure */ - uint8_t *pt_stream, /* i : bitstream file */ - int16_t *CNG, - const int16_t num_bits, /* i : input frame length in bits */ - const Word16 isAMRWB_IOmode, /* i : AMRWB flag */ - const Word16 core_mode, /* i : core mode for frame */ - const Word16 qbit, /* i : Q bit for AMR-WB IO */ - const Word16 bitstreamformat, - const Word16 amrwb_rfc4867_flag, - const int16_t partialframe, /* i : partial frame information */ - const int16_t next_coder_type /* i : next coder type information */ -); - void getPartialCopyInfo( Decoder_State *st, /* i : decoder state structure */ int16_t *sharpFlag ); @@ -719,13 +676,11 @@ int16_t lev_dur( ); /*! r: delay value in ns */ -float get_delay( - const int16_t what_delay, /* i : what delay? (ENC or DEC) */ - const int32_t io_fs, /* i : input/output sampling frequency */ - const IVAS_FORMAT ivas_format, /* i : IVAS format */ - HANDLE_CLDFB_FILTER_BANK hCldfb, /* i : Handle of Cldfb analysis */ - RENDERER_TYPE renderer_type, /* i : IVAS rendering type */ - const int32_t binaural_latency_ns /* i : binaural renderer HRTF delay in ns */ +int32_t get_delay( + const int16_t enc_dec, /* i : encoder/decoder flag */ + const int32_t io_fs, /* i : input/output sampling frequency */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + HANDLE_CLDFB_FILTER_BANK hCldfb /* i : Handle of Cldfb analysis */ ); void decision_matrix_enc( @@ -733,11 +688,11 @@ void decision_matrix_enc( int16_t *hq_core_type /* o : HQ core type */ ); -void signalling_enc( +void signaling_enc( Encoder_State *st /* i : encoder state structure */ ); -int16_t signalling_mode1_tcx20_enc( +int16_t signaling_mode1_tcx20_enc( Encoder_State *st, /* i/o: encoder state structure */ const int16_t push /* i : flag to push indice */ ); @@ -1246,12 +1201,12 @@ int16_t vq_dec_lvq( ); void index_lvq( - float *quant, /* i : codevector to be indexed (2 8-dim subvectors)*/ - int16_t *idx_lead, /* i : leader class index for each subvector */ - int16_t *idx_scale, /* i : scale index for each subvector */ - const int16_t mode, /* i : integer signalling the quantizer structure for the current bitrate */ - int16_t *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ - const int16_t prediction_flag /* i : predictive mode or not */ + float *quant, /* i : codevector to be indexed (2 8-dim subvectors) */ + int16_t *idx_lead, /* i : leader class index for each subvector */ + int16_t *idx_scale, /* i : scale index for each subvector */ + const int16_t mode, /* i : integer signaling the quantizer structure for the current bitrate */ + int16_t *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ + const int16_t prediction_flag /* i : predictive mode or not */ ); int16_t qlsf_ARSN_tcvq_Dec_16k( @@ -2265,18 +2220,19 @@ void read_next_force( ); #endif ivas_error init_encoder( - Encoder_State *st, /* i/o: state structure */ - const int16_t idchan, /* i : channel ID */ - const int16_t var_SID_rate_flag, /* i : flag for variable SID update rate */ + Encoder_State *st, /* i/o: state structure */ + const int16_t idchan, /* i : channel ID */ + const int16_t var_SID_rate_flag, /* i : flag for variable SID update rate */ const int16_t interval_SID, /* i : interval for SID update */ - const int16_t vad_only_flag /* i : flag to indicate front-VAD structure */ + const int16_t vad_only_flag, /* i : flag to indicate front-VAD structure */ + const ISM_MODE ism_mode /* i : ISM mode */ ); void LPDmem_enc_init( LPD_state_HANDLE hLPDmem /* i/o: LP memories */ ); -void destroy_encoder( +void destroy_cldfb_encoder( Encoder_State *st /* i/o: state structure */ ); ivas_error evs_enc( @@ -2307,7 +2263,6 @@ void pre_proc( float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ float **inp, /* o : ptr. to inp. signal in the current frame*/ float fr_bands[2 * NB_BANDS], /* i : energy in frequency bands */ - float *Etot, /* i : total energy */ float *ener, /* o : residual energy from Levinson-Durbin */ #ifndef FIX_I4_OL_PITCH int16_t pitch_orig[3], /* o : open-loop pitch values for quantization */ @@ -2626,6 +2581,11 @@ void InitSWBencBuffer( TD_BWE_ENC_HANDLE hBWE_TD /* i/o: TD BWE data handle */ ); +void InitSWBencBufferStates( + TD_BWE_ENC_HANDLE hBWE_TD, /* i/o: TD BWE data handle */ + float *shb_speech /* o : SHB target signal (6-14kHz) at 16kHz */ +); + void swb_tbe_enc( Encoder_State *st, /* i/o: encoder state structure */ STEREO_ICBWE_ENC_HANDLE hStereoICBWE, /* i/o: IC-BWE state structure */ @@ -2780,10 +2740,11 @@ void fb_tbe_enc( ); void fb_tbe_dec( - Decoder_State *st, /* i/o: decoder state structure */ - const float fb_exc[], /* i : FB excitation from the SWB part */ - float *hb_synth, /* i/o: high-band synthesis */ - float *fb_synth_ref /* o : high-band synthesis 16-20 kHz */ + Decoder_State *st, /* i/o: decoder state structure */ + const float fb_exc[], /* i : FB excitation from the SWB part */ + float *hb_synth, /* i/o: high-band synthesis */ + float *fb_synth_ref, /* o : high-band synthesis 16-20 kHz */ + const int16_t output_frame /* i : output frame length */ ); void calc_tilt_bwe( @@ -3838,7 +3799,8 @@ int16_t dtx_hangover_addition( const int16_t cldfb_subtraction, /* i : */ int16_t *vad_hover_flag, /* o : VAD hangover flag */ VAD_HANDLE hVAD, /* i/o: VAD handle for L or R channel */ - NOISE_EST_HANDLE hNoiseEst /* i : Noise estimation handle */ + NOISE_EST_HANDLE hNoiseEst, /* i : Noise estimation handle */ + int16_t *rem_dtx_ho /* o : Expected remaining hangover frames */ ); int16_t wb_vad( @@ -3861,8 +3823,13 @@ void bw_detect( const float signal_in[], /* i : input signal */ float *spectrum, /* i : MDCT spectrum */ const float *enerBuffer /* i : energy buffer */ +#ifdef FIX_MDCT_BASED_BWD + , + const int16_t mct_on /* i : flag MCT mode */ +#endif ); + void set_bw( const int16_t element_mode, /* i : element mode */ const int32_t element_brate, /* i : element bitrate */ @@ -3895,9 +3862,10 @@ void td_cng_enc_init( ); void dtx( - Encoder_State *st, /* i/o: encoder state structure */ - const int16_t vad, /* i : VAD flag for DTX */ - const float speech[] /* i : Pointer to the speech frame */ + Encoder_State *st, /* i/o: encoder state structure */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t vad, /* i : VAD flag for DTX */ + const float speech[] /* i : Pointer to the speech frame */ ); void dtx_hangover_control( @@ -3917,8 +3885,7 @@ void updt_enc( ); void updt_enc_common( - Encoder_State *st, /* i/o: encoder state structure */ - const float Etot /* i : total energy */ + Encoder_State *st /* i/o: encoder state structure */ ); void updt_IO_switch_enc( @@ -4510,7 +4477,7 @@ void reset_rf_indices( const int16_t L_frame, /* i : frame length */ int16_t *rf_target_bits_write ); -void signalling_enc_rf( +void signaling_enc_rf( Encoder_State *st /* i/o: encoder state structure */ ); @@ -4776,7 +4743,7 @@ void lp_filt_exc_dec( const int16_t i_subfr, /* i : subframe index */ const int16_t L_subfr, /* i : subframe size */ const int16_t L_Frame, /* i : frame size */ - int16_t lp_flag, /* i : operation mode signalling */ + int16_t lp_flag, /* i : operation mode signaling */ float *exc /* i/o: pointer to the excitation signal frame */ ); @@ -5149,15 +5116,12 @@ void decod_amr_wb( ); ivas_error init_decoder( - Decoder_State *st, /* o : Decoder static variables structure */ - const int16_t idchan /* i : channel ID */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const MC_MODE mc_mode /* i : MC mode */ -#endif + Decoder_State *st, /* o : Decoder static variables structure */ + const int16_t idchan, /* i : channel ID */ + const MC_MODE mc_mode /* i : MC mode */ ); -void destroy_decoder( +void destroy_cldfb_decoder( Decoder_State *st /* o : Decoder static variables structure */ ); @@ -5429,14 +5393,16 @@ void IMDCT( float *acelp_zir ); void hq_hr_dec( - Decoder_State *st, /* i/o: decoder state structure */ - float *t_audio_q, /* o : transform-domain coefficients */ - const int16_t length, /* i : frame length */ - const int16_t num_bits, /* i : number of available bits */ - int16_t *ynrm, /* o : norm quantization index vector */ - int16_t *is_transient, /* o : transient flag */ - int16_t *hqswb_clas, /* o : HQ SWB class */ - float *SWB_fenv /* o : SWB frequency envelopes */ + Decoder_State *st, /* i/o: decoder state structure */ + float *t_audio_q, /* o : transform-domain coefficients */ + const int16_t length, /* i : frame length */ + const int16_t num_bits, /* i : number of available bits */ + int16_t *ynrm, /* o : norm quantization index vector */ + int16_t *is_transient, /* o : transient flag */ + int16_t *hqswb_clas, /* o : HQ SWB class */ + float *SWB_fenv, /* o : SWB frequency envelopes */ + const int16_t core_switching_flag /* i : Core switching flag */ + ); void hdecnrm_context( @@ -5860,10 +5826,11 @@ void env_adj( ); float env_stability( - const int16_t *ynrm, /* i : Norm vector for current frame */ - const int16_t nb_sfm, /* i : Number of sub-bands */ - int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ - int16_t *mem_env_delta /* i/o: Envelope stability memory for smoothing*/ + const int16_t *ynrm, /* i : Norm vector for current frame */ + const int16_t nb_sfm, /* i : Number of sub-bands */ + int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ + int16_t *mem_env_delta, /* i/o: Envelope stability memory for smoothing*/ + const int16_t core_switching_flag /* i : Core switching flag */ ); /*! r: New speech/music state */ @@ -5889,10 +5856,13 @@ void core_switching_post_enc( ); ivas_error core_switching_post_dec( - Decoder_State *st, /* i/o: decoder state structure */ - float *synth, /* i/o: output synthesis */ - float *output, /* i/o: LB synth/upsampled LB synth */ - float output_mem[], /* i : OLA memory from last TCX/HQ frame */ + Decoder_State *st, /* i/o: decoder state structure */ + float *synth, /* i/o: output synthesis */ + float *output, /* i/o: LB synth/upsampled LB synth */ + float output_mem[], /* i : OLA memory from last TCX/HQ frame */ +#ifdef FIX_ISM_DTX_CLICKS + const IVAS_FORMAT ivas_format, /* i : IVAS format */ +#endif const int16_t use_cldfb_for_dft, /* i : flag to use of CLDFB for DFT Stereo */ const int16_t output_frame, /* i : frame length */ const int16_t core_switching_flag, /* i : ACELP->HQ switching frame flag */ @@ -6753,7 +6723,7 @@ float correlation_shift( void init_coder_ace_plus( Encoder_State *st, /* i : Encoder state handle */ const int32_t last_total_brate, /* i : last total bitrate */ - const int16_t is_mct /* i : MCT mode flag */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ ); void core_coder_reconfig( @@ -6764,7 +6734,7 @@ void core_coder_reconfig( void core_coder_mode_switch( Encoder_State *st, /* i/o: encoder state structure */ const int32_t last_total_brate, /* i : last bitrate */ - const int16_t is_mct /* i : MCT mode flag */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ ); void enc_acelp_tcx_main( @@ -6780,22 +6750,17 @@ void enc_acelp_tcx_main( ); void getTCXMode( - Decoder_State *st, /* i/o: decoder memory state */ - Decoder_State *st0 /* i : bitstream */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t MCT_flag -#endif + Decoder_State *st, /* i/o: decoder memory state */ + Decoder_State *st0, /* i : bitstream */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ ); void getTCXWindowing( - const int16_t core, /* i : current frame mode */ - const int16_t last_core, /* i : last frame mode */ -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - const int16_t element_mode, -#endif - TCX_CONFIG_HANDLE hTcxCfg, /* i/o: TCX configuration handle */ - Decoder_State *st0 /* i : bitstream */ + const int16_t core, /* i : current frame mode */ + const int16_t last_core, /* i : last frame mode */ + const int16_t element_mode, /* i : element mode */ + TCX_CONFIG_HANDLE hTcxCfg, /* i/o: TCX configuration handle */ + Decoder_State *st0 /* i : bitstream */ ); void getLPCparam( @@ -7188,8 +7153,11 @@ void WindowSignal( int16_t *L_frame, /* i/o: frame length */ float out[], /* o : output windowed signal */ const int16_t truncate_aldo, /* i : nonzero to truncate long ALDO slope */ - const int16_t fullband, /* i : fullband flag */ - const int16_t isLfe /* i: LFE flag */ + const int16_t fullband /* i : fullband flag */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const int16_t isLfe /* i : LFE flag */ +#endif ); void HBAutocorrelation( @@ -7342,8 +7310,11 @@ void tcx_get_windows( const float **left_win, /* o : left overlap window */ int16_t *right_overlap, /* o : right overlap length */ const float **right_win, /* o : right overlap window */ - const int16_t fullband, /* i : fullband flag */ - const int16_t isLfe /* i : LFE flag */ + const int16_t fullband /* i : fullband flag */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const int16_t isLfe /* i : LFE flag */ +#endif ); void tcx_windowing_analysis( @@ -7404,13 +7375,13 @@ void ProcessStereoIGF( Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ int16_t ms_mask[2][MAX_SFB], /* i : bandwise MS mask */ float *pITFMDCTSpectrum[CPE_CHANNELS][2], /* i : MDCT spectrum fir ITF */ - float pPowerSpectrum[CPE_CHANNELS][N_MAX], /* i : MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ float *pPowerSpectrumMsInv[CPE_CHANNELS][2], /* i : inverse power spectrum */ float *inv_spectrum[CPE_CHANNELS][2], /* i : inverse spectrum */ const int16_t frameno, /* i : flag indicating index of current subframe*/ const int16_t sp_aud_decision0, /* i : sp_aud_decision0 */ const int32_t element_brate, /* i : element bitrate */ - const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ + const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ ); void AnalyzePowerSpectrum( @@ -7618,8 +7589,7 @@ void InitTnsConfigs( const int16_t igfStopFreq, const int32_t total_brate, const int16_t element_mode, - const int16_t is_mct /* i : MCT mode flag */ -); + const int16_t MCT_flag ); void SetAllowTnsOnWhite( STnsConfig tnsConfig[2][2], @@ -7879,17 +7849,18 @@ void coder_tcx( ); void coder_tcx_post( - Encoder_State *st, /* i/o: decoder memory state */ - float *A, - const float *Ai ); + Encoder_State *st, /* i/o: encoder memory state */ + float *A, /* o : Quantized LPC coefficients */ + const float *Ai /* i : Unquantized (interpolated) LPC coefficients */ +); void decoder_tcx( - Decoder_State *st, /* i/o: coder memory state */ - int16_t prm[], /* i : parameters */ - float A[], /* i : coefficients NxAz[M+1] */ - Word16 Aind[], /* i : frame-independent coefficients Az[M+1]*/ - float synth[], /* i/o: synth[-M..lg] */ - float synthFB[], + Decoder_State *st, /* i/o: coder memory state */ + int16_t prm[], /* i : parameters */ + float A[], /* i : coefficients NxAz[M+1] */ + Word16 Aind[], /* i : frame-independent coefficients Az[M+1]*/ + float synth[], /* i/o: synth[-M..lg] */ + float synthFB[], /* i/o: encoder memory state */ const int16_t bfi, /* i : Bad frame indicator */ const int16_t frame_cnt, /* i : frame counter in the super_frame */ const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ @@ -7899,13 +7870,9 @@ void decoder_tcx_post( Decoder_State *st, /* i/o: decoder memory state */ float *synth, float *synthFB, - float *A, - const int16_t bfi -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t isMCT -#endif -); + float *A, /* i : A(z) filter coefficients */ + const int16_t bfi, + const int16_t isMCT ); void coder_acelp( Encoder_State *st, /* i/o: coder memory state */ @@ -7955,12 +7922,10 @@ void decoder_acelp( ); void writeTCXMode( - Encoder_State *st, /* i/o: encoder state structure */ - BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t is_mct, -#endif - int16_t *nbits_start /* o : nbits start */ + Encoder_State *st, /* i/o: encoder state structure */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ + int16_t *nbits_start /* o : nbits start */ ); void writeTCXWindowing( @@ -7999,7 +7964,7 @@ void writeTCXparam( const int16_t pre_past_flag ); void enc_prm_rf( - Encoder_State *st, /* i/o: decoder memory state */ + Encoder_State *st, /* i/o: encoder memory state */ const int16_t rf_frame_type, const int16_t fec_offset ); @@ -8143,15 +8108,12 @@ void con_acelp( ); void con_tcx( - Decoder_State *st, /* i/o: coder memory state */ - float synth[], /* i/o: synth[] */ - const float coh, /* i : coherence of stereo signal */ - int16_t *noise_seed, /* i/o: noise seed for stereo */ - const int16_t only_left /* i : TD-PLC only in left channel */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const float *A_cng -#endif + Decoder_State *st, /* i/o: coder memory state */ + float synth[], /* i/o: synth[] */ + const float coh, /* i : coherence of stereo signal */ + int16_t *noise_seed, /* i/o: noise seed for stereo */ + const int16_t only_left, /* i : TD-PLC only in left channel */ + const float A_cng[] /* i : CNG LP filter coefficients */ ); /*! r: codebook index */ @@ -8566,9 +8528,10 @@ void generate_comfort_noise_dec( ); void generate_comfort_noise_dec_hf( - float **bufferReal, /* o : Real part of input bands */ - float **bufferImag, /* o : Imaginary part of input bands */ - HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */ + float **bufferReal, /* o : Real part of input bands */ + float **bufferImag, /* o : Imaginary part of input bands */ + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + const int16_t cng_flag /* i : CNG Flag */ ); void generate_masking_noise( @@ -8697,28 +8660,20 @@ void configureFdCngDec( void ApplyFdCng( float *timeDomainInput, -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT float *powerSpectrum, -#endif float **realBuffer, /* i/o: Real part of the buffer */ float **imagBuffer, /* i/o: Imaginary part of the buffer */ Decoder_State *st, const int16_t concealWholeFrame, /* i : binary flag indicating frame loss */ const int16_t is_music ); -void perform_noise_estimation_dec( - const float *timeDomainInput, -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - float *power_spectrum, -#endif - HANDLE_FD_CNG_DEC hFdCngDec, /* i/o: FD_CNG structure */ - const int16_t element_mode, /* i : element mode type */ - const int16_t bwidth, /* i : audio bandwidth */ - const int16_t L_frame, /* i : frame length at internal Fs */ - const int16_t last_L_frame, /* i : frame length of the last frame at internal Fs */ - const int32_t last_core_brate, /* i : previous frame core bitrate */ - const int16_t VAD /* i : VAD flag in the decoder */ +void generate_comfort_noise_dec( + float **bufferReal, /* o : Real part of input bands */ + float **bufferImag, /* o : Imaginary part of input bands */ + Decoder_State *st, /* i/o: decoder state structure */ + const int16_t nchan_out /* i : number of output channels */ ); + /*! r: CNG energy */ float cng_energy( const int16_t element_mode, /* i : element mode */ @@ -8822,40 +8777,40 @@ void ReadFromBitstream( int16_t **pStream, int16_t *pnSize ); -void const *GetTnsFilterOrder( void const *p, int16_t index, int16_t *pValue ); -void *SetTnsFilterOrder( void *p, int16_t index, int16_t value ); -void const *GetNumOfTnsFilters( void const *p, int16_t index, int16_t *pValue ); -void *SetNumOfTnsFilters( void *p, int16_t index, int16_t value ); -void const *GetTnsEnabled( void const *p, int16_t index, int16_t *pValue ); -void *SetTnsEnabled( void *p, int16_t index, int16_t value ); -void const *GetTnsEnabledSingleFilter( void const *p, int16_t index, int16_t *pValue ); -void *SetTnsEnabledSingleFilter( void *p, int16_t index, int16_t value ); -void const *GetTnsFilterCoeff( void const *p, int16_t index, int16_t *pValue ); -void *SetTnsFilterCoeff( void *p, int16_t index, int16_t value ); - -void const *GetTnsOnWhite( void const *p, int16_t index, int16_t *pValue ); -void *SetTnsOnWhite( void *p, int16_t index, int16_t value ); - -int16_t GetSWBTCX10TnsFilterCoeffBits( int16_t value, int16_t index ); -int16_t EncodeSWBTCX10TnsFilterCoeff( int16_t value, int16_t index ); -int16_t DecodeSWBTCX10TnsFilterCoeff( Decoder_State *st, int16_t index, int16_t *pValue ); -int16_t GetSWBTCX20TnsFilterCoeffBits( int16_t value, int16_t index ); -int16_t EncodeSWBTCX20TnsFilterCoeff( int16_t value, int16_t index ); -int16_t DecodeSWBTCX20TnsFilterCoeff( Decoder_State *st, int16_t index, int16_t *pValue ); - -int16_t GetWBTCX20TnsFilterCoeffBits( int16_t value, int16_t index ); -int16_t EncodeWBTCX20TnsFilterCoeff( int16_t, int16_t index ); -int16_t DecodeWBTCX20TnsFilterCoeff( Decoder_State *st, int16_t index, int16_t *pValue ); - -int16_t GetTnsFilterOrderBitsSWBTCX10( int16_t value, int16_t index ); -int16_t EncodeTnsFilterOrderSWBTCX10( int16_t value, int16_t index ); -int16_t DecodeTnsFilterOrderSWBTCX10( Decoder_State *st, int16_t index, int16_t *pValue ); -int16_t GetTnsFilterOrderBitsSWBTCX20( int16_t value, int16_t index ); -int16_t EncodeTnsFilterOrderSWBTCX20( int16_t value, int16_t index ); -int16_t DecodeTnsFilterOrderSWBTCX20( Decoder_State *st, int16_t index, int16_t *pValue ); -int16_t GetTnsFilterOrderBits( int16_t value, int16_t index ); -int16_t EncodeTnsFilterOrder( int16_t value, int16_t index ); -int16_t DecodeTnsFilterOrder( Decoder_State *st, int16_t index, int16_t *pValue ); +void const *GetTnsFilterOrder( void const *p, const int16_t index, int16_t *pValue ); +void *SetTnsFilterOrder( void *p, const int16_t index, const int16_t value ); +void const *GetNumOfTnsFilters( void const *p, const int16_t index, int16_t *pValue ); +void *SetNumOfTnsFilters( void *p, const int16_t index, const int16_t value ); +void const *GetTnsEnabled( void const *p, const int16_t index, int16_t *pValue ); +void *SetTnsEnabled( void *p, const int16_t index, const int16_t value ); +void const *GetTnsEnabledSingleFilter( void const *p, const int16_t index, int16_t *pValue ); +void *SetTnsEnabledSingleFilter( void *p, const int16_t index, const int16_t value ); +void const *GetTnsFilterCoeff( void const *p, const int16_t index, int16_t *pValue ); +void *SetTnsFilterCoeff( void *p, const int16_t index, const int16_t value ); + +void const *GetTnsOnWhite( void const *p, const int16_t index, int16_t *pValue ); +void *SetTnsOnWhite( void *p, const int16_t index, const int16_t value ); + +int16_t GetSWBTCX10TnsFilterCoeffBits( const int16_t value, const int16_t index ); +int16_t EncodeSWBTCX10TnsFilterCoeff( const int16_t value, const int16_t index ); +int16_t DecodeSWBTCX10TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue ); +int16_t GetSWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index ); +int16_t EncodeSWBTCX20TnsFilterCoeff( const int16_t value, const int16_t index ); +int16_t DecodeSWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue ); + +int16_t GetWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index ); +int16_t EncodeWBTCX20TnsFilterCoeff( const int16_t, const int16_t index ); +int16_t DecodeWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue ); + +int16_t GetTnsFilterOrderBitsSWBTCX10( const int16_t value, const int16_t index ); +int16_t EncodeTnsFilterOrderSWBTCX10( const int16_t value, const int16_t index ); +int16_t DecodeTnsFilterOrderSWBTCX10( Decoder_State *st, const int16_t index, int16_t *pValue ); +int16_t GetTnsFilterOrderBitsSWBTCX20( const int16_t value, const int16_t index ); +int16_t EncodeTnsFilterOrderSWBTCX20( const int16_t value, const int16_t index ); +int16_t DecodeTnsFilterOrderSWBTCX20( Decoder_State *st, const int16_t index, int16_t *pValue ); +int16_t GetTnsFilterOrderBits( const int16_t value, const int16_t index ); +int16_t EncodeTnsFilterOrder( const int16_t value, const int16_t index ); +int16_t DecodeTnsFilterOrder( Decoder_State *st, const int16_t index, int16_t *pValue ); void ResetTnsData( STnsData *pTnsData ); @@ -8870,8 +8825,7 @@ void InitTnsConfiguration( const int16_t igfStopFreq, const int32_t total_brate, const int16_t element_mode, - const int16_t is_mct /* i : MCT mode flag */ -); + const int16_t MCT_flag ); int16_t DetectTnsFilt( const STnsConfig *pTnsConfig, /* i : TNS Configuration struct */ @@ -9029,7 +8983,7 @@ ivas_error config_acelp1( const int16_t L_frame, /* i : frame length at internal Fs */ const int16_t GSC_noisy_speech, /* i : GSC on SWB noisy speech flag */ ACELP_config *acelp_cfg, /* i : ACELP bit-allocation */ - const int16_t signalling_bits, /* i : number of signalling bits */ + const int16_t signaling_bits, /* i : number of signaling bits */ const int16_t coder_type, /* i : coder type */ const int16_t tc_subfr, /* i : TC subfr ID */ const int16_t tc_call, /* i : TC call number (0,1,2) */ @@ -9205,15 +9159,13 @@ void longshiftleft( ); void open_decoder_LPD( - Decoder_State *st, /* i/o: decoder state structure */ - const int32_t total_brate, /* i : total bitrate */ - const int32_t last_total_brate, /* i : last total bitrate */ - const int16_t bwidth, /* i : audio bandwidth */ - const int16_t is_mct, /* i : MCT mode flag */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t last_element_mode, -#endif - const int16_t is_init /* i : indicate call during initialization */ + Decoder_State *st, /* i/o: decoder state structure */ + const int32_t total_brate, /* i : total bitrate */ + const int32_t last_total_brate, /* i : last total bitrate */ + const int16_t bwidth, /* i : audio bandwidth */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t last_element_mode, /* i : last element mode */ + const int16_t is_init /* i : indicate call during initialization */ ); void acelp_plc_mdct_transition( @@ -9247,16 +9199,13 @@ void reconfig_decoder_LPD( ); void mode_switch_decoder_LPD( - Decoder_State *st, /* i/o: decoder state structure */ - const int16_t bwidth, /* i : audio bandwidth */ - const int32_t total_brate, /* i : total bitrate */ - const int32_t last_total_brate, /* i : last frame total bitrate */ - const int16_t frame_size_index, /* i : index determining the frame size*/ - const int16_t is_mct /* i : MCT mode flag */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t last_element_mode -#endif + Decoder_State *st, /* i/o: decoder state structure */ + const int16_t bwidth, /* i : audio bandwidth */ + const int32_t total_brate, /* i : total bitrate */ + const int32_t last_total_brate, /* i : last frame total bitrate */ + const int16_t frame_size_index, /* i : index determining the frame size */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ + const int16_t last_element_mode /* i : last element mode */ ); void dec_acelp_tcx_frame( @@ -9536,12 +9485,8 @@ void TonalMDCTConceal_SaveFreqSignal( const float *mdctSpectrum, const uint16_t numSamples, const uint16_t nNewSamplesCore, - const float *scaleFactors -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t infoIGFStartLine -#endif -); + const float *scaleFactors, + const int16_t infoIGFStartLine ); void TonalMDCTConceal_UpdateState( TonalMDCTConcealPtr hTonalMDCTConc, @@ -9556,11 +9501,15 @@ void TonalMDCTConceal_SaveTimeSignal( const int16_t numSamples ); void TonalMDCTConceal_Detect( - const TonalMDCTConcealPtr hTonalMDCTConc, /*IN */ - const float pitchLag, /*IN */ - int16_t *umIndices, /*OUT*/ - const PsychoacousticParameters *psychParamsCurrent, /*IN*/ - const int16_t isLfe ); + const TonalMDCTConcealPtr hTonalMDCTConc, /*IN */ + const float pitchLag, /*IN */ + int16_t *umIndices, /*OUT*/ + const PsychoacousticParameters *psychParamsCurrent /*IN*/ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const int16_t isLfe +#endif +); void TonalMDCTConceal_Apply( TonalMDCTConcealPtr hTonalMDCTConc, /*IN */ @@ -9575,9 +9524,8 @@ void TonalMDCTConceal_InsertNoise( int16_t *pSeed, /*IN/OUT*/ const float tiltCompFactor, const float crossfadeGain, -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT const float concealment_noise[L_FRAME48k], -#endif + const float cngLevelBackgroundTrace_bfi, const int16_t crossOverFreq ); void DetectTonalComponents( @@ -9612,7 +9560,6 @@ void RefineTonalComponents( float floorPowerSpectrum, const PsychoacousticParameters *psychParamsCurrent ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ivas_error PsychoacousticParameters_Init( const int32_t sr_core, /* i : sampling rate of core-coder */ const int16_t nBins, /* i : Number of bins (spectral lines) */ @@ -9620,7 +9567,6 @@ ivas_error PsychoacousticParameters_Init( const int16_t isTCX20, /* i : Flag indicating if the subband division is for TCX20 or TCX10 */ const int16_t isWarped, /* i : Flag indicating if the scale is linear or warped */ PsychoacousticParameters *pPsychParams ); -#endif void concealment_init( const int16_t L_frameTCX, @@ -9689,16 +9635,19 @@ int16_t get_codec_mode( ); int16_t getTcxonly( - const int16_t element_mode, /* i : IVAS element mode */ - const int32_t total_brate, /* i : total bitrate */ - const int16_t is_mct /* i : MCT mode flag */ + const int16_t element_mode, /* i : IVAS element mode */ + const int32_t total_brate, /* i : total bitrate */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ ); int16_t getTnsAllowed( - const int32_t total_brate, /* i : total bitrate */ - const int16_t igf, /* i : flag indicating IGF activity*/ - const int16_t element_mode, /* i : IVAS element mode */ + const int32_t total_brate, /* i : total bitrate */ + const int16_t igf, /* i : flag indicating IGF activity*/ + const int16_t element_mode /* i : IVAS element mode */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , const MCT_CHAN_MODE mct_chan_mode /* i : MCT channel mode */ +#endif ); int16_t getCtxHm( @@ -9740,8 +9689,11 @@ int16_t getIgfPresent( const int16_t element_mode, /* i : IVAS element mode */ const int32_t total_brate, /* i : total bitrate */ const int16_t bwidth, /* i : audio bandwidth */ - const int16_t rf_mode, /* i : flag to signal the RF mode */ + const int16_t rf_mode /* i : flag to signal the RF mode */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , const int16_t mct_chan_mode /* i : MCT channel mode */ +#endif ); int16_t getCnaPresent( @@ -9771,7 +9723,7 @@ void SetModeIndex( Encoder_State *st, /* i : Encoder state */ const int32_t last_total_brate, /* i : last total bitrate */ const int16_t last_element_mode, /* i : last IVAS element mode */ - const int16_t is_mct /* i : MCT mode flag */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); int16_t getNumTcxCodedLines( @@ -9801,7 +9753,7 @@ void IGFEncApplyStereo( const IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS], /* i : instance handle of IGF Encoder */ const int16_t igfGridIdx, /* i : IGF grid index */ Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ - float pPowerSpectrum[CPE_CHANNELS][N_MAX], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ float *pPowerSpectrumMsInv[CPE_CHANNELS][2], /* i/o: inverse power spectrum */ float *inv_spectrum[CPE_CHANNELS][2], /* i : inverse spectrum */ const int16_t frameno, /* i : flag indicating index of current subframe */ @@ -9995,6 +9947,7 @@ void IGFSCFDecoderDecode( if 0 on input the decoder will be forced to encode without a reset */ ); +/*! r: offset value */ int16_t tbe_celp_exc_offset( const int16_t T0, /* i : Integer pitch */ const int16_t T0_frac /* i : Fractional part of the pitch */ @@ -10037,6 +9990,9 @@ void init_tcx_cfg( const int16_t infoIGFStopFreq, const int16_t element_mode, const int16_t ini_frame, - const int16_t is_mct, /* i : MCT mode flag */ - const MCT_CHAN_MODE mct_chan_mode /* i : MCT channel mode */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const MCT_CHAN_MODE mct_chan_mode /* i : MCT channel mode */ +#endif ); diff --git a/lib_com/pvq_com.c b/lib_com/pvq_com.c index 750c20adb9eb8c1450d7e3dc43cf444d5e3b2807..133b7b62f743e0bc0720904fc7af82385cc40f92 100644 --- a/lib_com/pvq_com.c +++ b/lib_com/pvq_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "prot.h" #include "stl.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local definitions @@ -691,6 +691,8 @@ void srt_vec_ind_f( return; } +#define WMC_TOOL_SKIP + /*-------------------------------------------------------------------* * UMult_32_32() * @@ -814,7 +816,6 @@ Word16 atan2_fx( Word16 man, expo, reciprocal; Word16 angle, w, z; -#define WMC_TOOL_MAN IF( L_sub( x, 0 ) == 0 ) { return 25736; /* EVS_PI/2 in Q14 */ @@ -973,3 +974,5 @@ Word16 atan2_fx( return angle; /* Q14 between 0 and EVS_PI/2 radian. */ } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/range_com.c b/lib_com/range_com.c index 083b95edbb4a68e23b43b9d81c5c80acbc7e5e6a..b01dc7156e972acaeed28c5dc20c8092f9f1b82c 100644 --- a/lib_com/range_com.c +++ b/lib_com/range_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * rc_get_bits2() diff --git a/lib_com/re8_ppv.c b/lib_com/re8_ppv.c index ab48b24cedee2149923b35d5d0bde24d36f7871a..f6c5ab6814fd7adb4791161132f666ee2b9b3e55 100644 --- a/lib_com/re8_ppv.c +++ b/lib_com/re8_ppv.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,8 +41,8 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" -#include "wmops.h" +#include "wmc_auto.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_com/re8_util.c b/lib_com/re8_util.c index e4600774b4013e10bc8e25a5ae9423f365949ea4..d23ae1c0cd7848b92fb9cbc928d4e51296690aa2 100644 --- a/lib_com/re8_util.c +++ b/lib_com/re8_util.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_com/realft.c b/lib_com/realft.c index 0c0b8236c56a600a27915a8fb73d58d7ede2d169..b7a3fef0d9db4561a1456b336c79522ef99b9457 100644 --- a/lib_com/realft.c +++ b/lib_com/realft.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * four1() diff --git a/lib_com/recovernorm.c b/lib_com/recovernorm.c index b5e35de26870acbf65af5f4c8965469e397c1b85..52e9edcd2a0c02c9249a8139441eb6791582d446 100644 --- a/lib_com/recovernorm.c +++ b/lib_com/recovernorm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * recovernorm() diff --git a/lib_com/reordvct.c b/lib_com/reordvct.c index a497f28e4a8b2a69b9ca0dbd4f67715a58fd88f4..182050bfb65a2449045a887e88171454d5d8181a 100644 --- a/lib_com/reordvct.c +++ b/lib_com/reordvct.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * reordvct() diff --git a/lib_com/residu.c b/lib_com/residu.c index a897f70f253baec9b0f38a79e762d2baa2eaa7e3..e220d81c01d2b60118d0b0186a47d6a6104ebe17 100644 --- a/lib_com/residu.c +++ b/lib_com/residu.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------* * residu() diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c index 30ae3c0a4770370149ff90849f4cee2a05e30de6..b0c0c61978cd93adcbd9db91a0c0bf6768d711cb 100644 --- a/lib_com/rom_com.c +++ b/lib_com/rom_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "rom_com.h" #include "prot.h" #include "basop_util.h" -#include "wmops.h" +#include "wmc_auto.h" /* clang-format off */ @@ -88,7 +88,7 @@ const FrameSizeParams FrameSizeConfig[FRAME_SIZE_NB] = /*----------------------------------------------------------------------------------* - * Conversion of ACELP signalling parameters (ACELP internal Fs, coder type, bandwidth, sharpening flag) to index + * Conversion of ACELP signaling parameters (ACELP internal Fs, coder type, bandwidth, sharpening flag) to index * (to be consulted with the decision matrix) * * - in order to retrieve the index, each section in this table starts with the bitrate diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index 83a7581491bd6569f7b4eb22f79bf3cb1e247e30..79971cba6a04ba94418cd46db8aa32c2d993191d 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/stab_est.c b/lib_com/stab_est.c index 0ee40153a6207d0663b5df98c13098920c9c55eb..63466220c68c882d71e6834c3b3e749a62166c39 100644 --- a/lib_com/stab_est.c +++ b/lib_com/stab_est.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_com/stat_com.h b/lib_com/stat_com.h index 7f82c9272faa9815561886b91c1f16630069f90b..79976efa88ab63a6d3eb8948712e899a1e5e1f12 100644 --- a/lib_com/stat_com.h +++ b/lib_com/stat_com.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -395,7 +395,7 @@ typedef struct int16_t frame_type_previous; - float A_cng[17]; + float A_cng[M + 1]; float exc_cng[L_FRAME16k]; int32_t CngBitrate; @@ -406,6 +406,7 @@ typedef struct float coherence; /* inter-channel coherence of noise */ int16_t no_side_flag; /* indicates whether the side noise shape should be zeroed-out or not */ + } FD_CNG_COM, *HANDLE_FD_CNG_COM; diff --git a/lib_com/stat_noise_uv_mod.c b/lib_com/stat_noise_uv_mod.c index 72b843d1db418a5d348d2b7cde03f3bd8bfb5fae..83c2d321cc584155851be33d275dc97ab459eb33 100644 --- a/lib_com/stat_noise_uv_mod.c +++ b/lib_com/stat_noise_uv_mod.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_com/stl.h b/lib_com/stl.h index c699fd899be89f5e14d4f2ca84c7479ce35a5d06..234aec9e1609d68771d2cd80be104a0d4b17126c 100644 --- a/lib_com/stl.h +++ b/lib_com/stl.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/swb_bwe_com.c b/lib_com/swb_bwe_com.c index 4e692fc22be61c7d46564faed3dad4ac07f6c834..4efbaa735d22eaa1acb8748e6c77c154c380e68f 100644 --- a/lib_com/swb_bwe_com.c +++ b/lib_com/swb_bwe_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * WB_BWE_gain_pred() diff --git a/lib_com/swb_bwe_com_hr.c b/lib_com/swb_bwe_com_hr.c index ebad781a99c4056a35e8c104f81913c28b7d25b0..fbdcf70b93b600faa5e949ec6e0776375d2d1337 100644 --- a/lib_com/swb_bwe_com_hr.c +++ b/lib_com/swb_bwe_com_hr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * swb_hr_nonzero_subband_noise_fill() diff --git a/lib_com/swb_bwe_com_lr.c b/lib_com/swb_bwe_com_lr.c index 963d881cb347378ab36d2eb03214795581872dea..daa7d167376ba9e5c2ef88de1601d8448af83935 100644 --- a/lib_com/swb_bwe_com_lr.c +++ b/lib_com/swb_bwe_com_lr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * hf_parinitiz() diff --git a/lib_com/swb_tbe_com.c b/lib_com/swb_tbe_com.c index 4291feaed934a14e5251457f2bb1e0d8a58f388e..235a3551f601478bffb52ef44ff941e41ea7704b 100644 --- a/lib_com/swb_tbe_com.c +++ b/lib_com/swb_tbe_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" #include @@ -89,6 +89,7 @@ void swb_tbe_reset( return; } + /*-------------------------------------------------------------------* * swb_tbe_reset_synth() * @@ -105,11 +106,14 @@ void swb_tbe_reset_synth( return; } + /*-------------------------------------------------------------------* * tbe_celp_exc_offset() * * Compute tbe bwe celp excitation offset *-------------------------------------------------------------------*/ + +/*! r: offset value */ int16_t tbe_celp_exc_offset( const int16_t T0, /* i : Integer pitch */ const int16_t T0_frac /* i : Fractional part of the pitch */ @@ -120,6 +124,8 @@ int16_t tbe_celp_exc_offset( return offset; } + + /*-------------------------------------------------------------------* * flip_and_downmix_generic() * @@ -1891,6 +1897,8 @@ void tbe_celp_exc( return; } + assert( bwe_exc != NULL && "BWE excitation is NULL" ); + if ( L_frame == L_FRAME ) { offset = tbe_celp_exc_offset( T0, T0_frac ); diff --git a/lib_com/syn_12k8.c b/lib_com/syn_12k8.c index 4323853f98348e1a3f4954f94931c427a9936dd1..15892f62c615bcdae800ca87e2ee9960a0d2293e 100644 --- a/lib_com/syn_12k8.c +++ b/lib_com/syn_12k8.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------ * syn_12k8() diff --git a/lib_com/syn_filt.c b/lib_com/syn_filt.c index d571b9cb7f84ea8ae628bd18ada205b7295197e9..08e687c12cdbe5fa7084314b2a387b856a213d99 100644 --- a/lib_com/syn_filt.c +++ b/lib_com/syn_filt.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include /*------------------------------------------------------------------* diff --git a/lib_com/tcq_position_arith.c b/lib_com/tcq_position_arith.c index 4c3c49e197c0f94bfd0566d27e5e0e5116bc68df..186956207473f5e0d1a3197ff7f79c407e49654f 100644 --- a/lib_com/tcq_position_arith.c +++ b/lib_com/tcq_position_arith.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" static void bitstream_save_bit( TCQ_PBITSTREAM pBS, const int16_t bit ); diff --git a/lib_com/tcx_ltp.c b/lib_com/tcx_ltp.c index 160a6e7875d79f59c00132a1739e153b15cf53cd..90dcb1515ce6bd332f2311975c12b9741ec828a2 100644 --- a/lib_com/tcx_ltp.c +++ b/lib_com/tcx_ltp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * Local constants diff --git a/lib_com/tcx_mdct.c b/lib_com/tcx_mdct.c index d9713c9cfcf16be802e9d5ef8e61640e72db0ed1..e8ac35d07aa1c67f1cc385de95ad4330e8d38464 100644 --- a/lib_com/tcx_mdct.c +++ b/lib_com/tcx_mdct.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * TCX_MDCT() diff --git a/lib_com/tcx_mdct_window.c b/lib_com/tcx_mdct_window.c index 2d1d474404858a9edc7438a2bbaadf2d9d710b35..0ef69587a8a690b4ee5917a5f6e12bace8317394 100644 --- a/lib_com/tcx_mdct_window.c +++ b/lib_com/tcx_mdct_window.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * mdct_window_sine() diff --git a/lib_com/tcx_utils.c b/lib_com/tcx_utils.c index 19e02204392a32401ca4ec80d62d03580d870602..7eede5ae650d3c9033968ca70034a6c1e38ce3ca 100644 --- a/lib_com/tcx_utils.c +++ b/lib_com/tcx_utils.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * tcx_get_windows() @@ -59,16 +59,20 @@ void tcx_get_windows( const float **left_win, /* o : left overlap window */ int16_t *right_overlap, /* o : right overlap length */ const float **right_win, /* o : right overlap window */ - const int16_t fullband, /* i : fullband flag */ - const int16_t isLfe /* i : LFE flag */ + const int16_t fullband /* i : fullband flag */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const int16_t isLfe /* i : LFE flag */ +#endif ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE /* LFE is only FULL_OVERLAP*/ if ( isLfe ) { assert( left_mode == FULL_OVERLAP && right_mode == FULL_OVERLAP ); } - +#endif if ( !fullband ) { /* Left part */ @@ -91,6 +95,7 @@ void tcx_get_windows( } else if ( left_mode == FULL_OVERLAP ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( isLfe ) { *left_overlap = hTcxCfg->tcx_mdct_window_length; @@ -98,9 +103,12 @@ void tcx_get_windows( } else { +#endif *left_overlap = hTcxCfg->tcx_mdct_window_length; *left_win = hTcxCfg->tcx_aldo_window_1_trunc; +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif } else { @@ -121,6 +129,7 @@ void tcx_get_windows( } else if ( right_mode == FULL_OVERLAP ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( isLfe ) { *right_overlap = hTcxCfg->tcx_mdct_window_length; @@ -128,9 +137,12 @@ void tcx_get_windows( } else { +#endif *right_overlap = hTcxCfg->tcx_mdct_window_delay; *right_win = hTcxCfg->tcx_aldo_window_2; +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif } else { @@ -164,6 +176,7 @@ void tcx_get_windows( } else if ( left_mode == FULL_OVERLAP ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( isLfe ) { *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB; @@ -171,9 +184,12 @@ void tcx_get_windows( } else { +#endif *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB; *left_win = hTcxCfg->tcx_aldo_window_1_FB_trunc; +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif } else { @@ -199,6 +215,7 @@ void tcx_get_windows( } else if ( right_mode == FULL_OVERLAP ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( isLfe ) { *right_overlap = hTcxCfg->tcx_mdct_window_lengthFB; @@ -206,9 +223,12 @@ void tcx_get_windows( } else { +#endif *right_overlap = hTcxCfg->tcx_mdct_window_delayFB; *right_win = hTcxCfg->tcx_aldo_window_2_FB; +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif } else { @@ -276,8 +296,11 @@ void WindowSignal( int16_t *L_frame, /* i/o: frame length */ float out[], /* o : output windowed signal */ const int16_t truncate_aldo, /* i : nonzero to truncate long ALDO slope */ - const int16_t fullband, /* i : fullband flag */ - const int16_t isLfe /* i : LFE flag */ + const int16_t fullband /* i : fullband flag */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const int16_t isLfe /* i : LFE flag */ +#endif ) { int16_t l, r; @@ -288,7 +311,12 @@ void WindowSignal( * Init * *-----------------------------------------------------------*/ - tcx_get_windows( hTcxCfg, left_overlap_mode, right_overlap_mode, &l, &left_win, &r, &right_win, fullband, isLfe ); + tcx_get_windows( hTcxCfg, left_overlap_mode, right_overlap_mode, &l, &left_win, &r, &right_win, fullband +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + isLfe +#endif + ); /* Init lengths */ @@ -314,7 +342,11 @@ void WindowSignal( tcx_windowing_analysis( in - l / 2 + offset, *L_frame, l, left_win, r, right_win, out ); - if ( left_overlap_mode == FULL_OVERLAP && truncate_aldo && !isLfe ) + if ( left_overlap_mode == FULL_OVERLAP && truncate_aldo +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && !isLfe +#endif + ) { /* fade truncated ALDO window to avoid discontinuities */ if ( !fullband ) @@ -995,16 +1027,16 @@ void InitTnsConfigs( const int16_t igfStopFreq, const int32_t total_brate, const int16_t element_mode, - const int16_t is_mct ) + const int16_t MCT_flag ) { if ( total_brate > ACELP_32k ) { - InitTnsConfiguration( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, is_mct ); + InitTnsConfiguration( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag ); } - InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, is_mct ); + InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag ); - InitTnsConfiguration( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, is_mct ); + InitTnsConfiguration( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag ); return; } diff --git a/lib_com/tec_com.c b/lib_com/tec_com.c index 18b2e79b94e8f6500f345825dff9610813cb7631..346d38292b237a1271c2d12d84dd9dbedfed14a6 100644 --- a/lib_com/tec_com.c +++ b/lib_com/tec_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "rom_com.h" #include "prot.h" #include "stat_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * Local constants diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c index 1be0b73b0c1a6e3e5bb1554b784d92089c772329..20e679c3167406981d5131f6f325e9defa87e545 100644 --- a/lib_com/tns_base.c +++ b/lib_com/tns_base.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "rom_com.h" #include "prot.h" #include "stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------------- @@ -78,7 +78,7 @@ void InitTnsConfiguration( const int16_t igfStopFreq, const int32_t total_brate, const int16_t element_mode, - const int16_t is_mct ) + const int16_t MCT_flag ) { int32_t nSampleRate; int16_t iFilter; @@ -111,8 +111,7 @@ void InitTnsConfiguration( } else if ( nSampleRate > 16000 ) { - - if ( ( element_mode > IVAS_SCE ) && ( total_brate >= ( is_mct ? IVAS_32k : IVAS_48k ) ) ) + if ( ( element_mode > IVAS_SCE ) && ( total_brate >= ( MCT_flag ? IVAS_32k : IVAS_48k ) ) ) { pTnsConfig->nMaxFilters = sizeof( tnsParameters32kHz_Stereo ) / sizeof( tnsParameters32kHz_Stereo[0] ); if ( nSampleRate == 100 * frameLength ) /* sub-frame length is <= 10 ms */ @@ -288,67 +287,67 @@ static int16_t DecodeUsingTable( Decoder_State *st, int16_t *pValue, const Codin /* TNS filter coefficients */ -void const *GetTnsFilterCoeff( void const *p, int16_t index, int16_t *pValue ) +void const *GetTnsFilterCoeff( void const *p, const int16_t index, int16_t *pValue ) { *pValue = ( (int16_t const *) p )[index] + INDEX_SHIFT; return NULL; } -void *SetTnsFilterCoeff( void *p, int16_t index, int16_t value ) +void *SetTnsFilterCoeff( void *p, const int16_t index, const int16_t value ) { ( (int16_t *) p )[index] = value - INDEX_SHIFT; return NULL; } -int16_t GetSWBTCX20TnsFilterCoeffBits( int16_t value, int16_t index ) +int16_t GetSWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return GetBitsFromTable( value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes ); } -int16_t EncodeSWBTCX20TnsFilterCoeff( int16_t value, int16_t index ) +int16_t EncodeSWBTCX20TnsFilterCoeff( const int16_t value, const int16_t index ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return EncodeUsingTable( value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes ); } -int16_t DecodeSWBTCX20TnsFilterCoeff( Decoder_State *st, int16_t index, int16_t *pValue ) +int16_t DecodeSWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return DecodeUsingTable( st, pValue, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes ); } -int16_t GetSWBTCX10TnsFilterCoeffBits( int16_t value, int16_t index ) +int16_t GetSWBTCX10TnsFilterCoeffBits( const int16_t value, const int16_t index ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return GetBitsFromTable( value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes ); } -int16_t EncodeSWBTCX10TnsFilterCoeff( int16_t value, int16_t index ) +int16_t EncodeSWBTCX10TnsFilterCoeff( const int16_t value, const int16_t index ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return EncodeUsingTable( value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes ); } -int16_t DecodeSWBTCX10TnsFilterCoeff( Decoder_State *st, int16_t index, int16_t *pValue ) +int16_t DecodeSWBTCX10TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return DecodeUsingTable( st, pValue, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes ); } -int16_t GetWBTCX20TnsFilterCoeffBits( int16_t value, int16_t index ) +int16_t GetWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return GetBitsFromTable( value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes ); } -int16_t EncodeWBTCX20TnsFilterCoeff( int16_t value, int16_t index ) +int16_t EncodeWBTCX20TnsFilterCoeff( const int16_t value, const int16_t index ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return EncodeUsingTable( value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes ); } -int16_t DecodeWBTCX20TnsFilterCoeff( Decoder_State *st, int16_t index, int16_t *pValue ) +int16_t DecodeWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue ) { assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) ); return DecodeUsingTable( st, pValue, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes ); @@ -357,67 +356,67 @@ int16_t DecodeWBTCX20TnsFilterCoeff( Decoder_State *st, int16_t index, int16_t * /* TNS filter order */ -void const *GetTnsFilterOrder( void const *p, int16_t index, int16_t *pValue ) +void const *GetTnsFilterOrder( void const *p, const int16_t index, int16_t *pValue ) { *pValue = ( (STnsFilter const *) p )[index].order; return ( (STnsFilter const *) p )[index].coefIndex; } -void *SetTnsFilterOrder( void *p, int16_t index, int16_t value ) +void *SetTnsFilterOrder( void *p, const int16_t index, const int16_t value ) { ( (STnsFilter *) p )[index].order = value; return ( (STnsFilter *) p )[index].coefIndex; } -int16_t GetTnsFilterOrderBitsSWBTCX20( int16_t value, int16_t index ) +int16_t GetTnsFilterOrderBitsSWBTCX20( const int16_t value, const int16_t index ) { (void) index; return GetBitsFromTable( value - 1, codesTnsOrderTCX20, nTnsOrderCodes ); } -int16_t EncodeTnsFilterOrderSWBTCX20( int16_t value, int16_t index ) +int16_t EncodeTnsFilterOrderSWBTCX20( const int16_t value, const int16_t index ) { (void) index; return EncodeUsingTable( value - 1, codesTnsOrderTCX20, nTnsOrderCodes ); } -int16_t DecodeTnsFilterOrderSWBTCX20( Decoder_State *st, int16_t index, int16_t *pValue ) +int16_t DecodeTnsFilterOrderSWBTCX20( Decoder_State *st, const int16_t index, int16_t *pValue ) { (void) index; return DecodeUsingTable( st, pValue, codesTnsOrderTCX20, nTnsOrderCodes ); } -int16_t GetTnsFilterOrderBitsSWBTCX10( int16_t value, int16_t index ) +int16_t GetTnsFilterOrderBitsSWBTCX10( const int16_t value, const int16_t index ) { (void) index; return GetBitsFromTable( value - 1, codesTnsOrderTCX10, nTnsOrderCodes ); } -int16_t EncodeTnsFilterOrderSWBTCX10( int16_t value, int16_t index ) +int16_t EncodeTnsFilterOrderSWBTCX10( const int16_t value, const int16_t index ) { (void) index; return EncodeUsingTable( value - 1, codesTnsOrderTCX10, nTnsOrderCodes ); } -int16_t DecodeTnsFilterOrderSWBTCX10( Decoder_State *st, int16_t index, int16_t *pValue ) +int16_t DecodeTnsFilterOrderSWBTCX10( Decoder_State *st, const int16_t index, int16_t *pValue ) { (void) index; return DecodeUsingTable( st, pValue, codesTnsOrderTCX10, nTnsOrderCodes ); } -int16_t GetTnsFilterOrderBits( int16_t value, int16_t index ) +int16_t GetTnsFilterOrderBits( const int16_t value, const int16_t index ) { (void) index; return GetBitsFromTable( value - 1, codesTnsOrder, nTnsOrderCodes ); } -int16_t EncodeTnsFilterOrder( int16_t value, int16_t index ) +int16_t EncodeTnsFilterOrder( const int16_t value, const int16_t index ) { (void) index; return EncodeUsingTable( value - 1, codesTnsOrder, nTnsOrderCodes ); } -int16_t DecodeTnsFilterOrder( Decoder_State *st, int16_t index, int16_t *pValue ) +int16_t DecodeTnsFilterOrder( Decoder_State *st, const int16_t index, int16_t *pValue ) { (void) index; return DecodeUsingTable( st, pValue, codesTnsOrder, nTnsOrderCodes ); @@ -425,13 +424,13 @@ int16_t DecodeTnsFilterOrder( Decoder_State *st, int16_t index, int16_t *pValue /* Number of TNS filters */ -void const *GetNumOfTnsFilters( void const *p, int16_t index, int16_t *pValue ) +void const *GetNumOfTnsFilters( void const *p, const int16_t index, int16_t *pValue ) { *pValue = (int16_t) abs( ( (STnsData const *) p )[index].nFilters ); return ( (STnsData const *) p )[index].filter; } -void *SetNumOfTnsFilters( void *p, int16_t index, int16_t value ) +void *SetNumOfTnsFilters( void *p, const int16_t index, const int16_t value ) { ( (STnsData *) p )[index].nFilters = (int16_t) abs( value ); return ( (STnsData *) p )[index].filter; @@ -439,13 +438,13 @@ void *SetNumOfTnsFilters( void *p, int16_t index, int16_t value ) /* TNS enabled/disabled flag */ -void const *GetTnsEnabled( void const *p, int16_t index, int16_t *pValue ) +void const *GetTnsEnabled( void const *p, const int16_t index, int16_t *pValue ) { *pValue = ( (STnsData const *) p )[index].nFilters != 0 ? 1 : 0; return NULL; } -void *SetTnsEnabled( void *p, int16_t index, int16_t value ) +void *SetTnsEnabled( void *p, const int16_t index, const int16_t value ) { (void) p, (void) index, (void) value; return NULL; @@ -453,25 +452,25 @@ void *SetTnsEnabled( void *p, int16_t index, int16_t value ) /* TNS on whitened spectra flag */ -void const *GetTnsOnWhite( void const *p, int16_t index, int16_t *pValue ) +void const *GetTnsOnWhite( void const *p, const int16_t index, int16_t *pValue ) { *pValue = ( (STnsData const *) p )[index].tnsOnWhitenedSpectra > 0 ? 1 : 0; return NULL; } -void *SetTnsOnWhite( void *p, int16_t index, int16_t value ) +void *SetTnsOnWhite( void *p, const int16_t index, const int16_t value ) { ( (STnsData *) p )[index].tnsOnWhitenedSpectra = value; return NULL; } -void const *GetTnsEnabledSingleFilter( void const *p, int16_t index, int16_t *pValue ) +void const *GetTnsEnabledSingleFilter( void const *p, const int16_t index, int16_t *pValue ) { *pValue = ( (STnsData const *) p )[index].nFilters != 0 ? 1 : 0; return ( (STnsData const *) p )[index].filter; } -void *SetTnsEnabledSingleFilter( void *p, int16_t index, int16_t value ) +void *SetTnsEnabledSingleFilter( void *p, const int16_t index, const int16_t value ) { ( (STnsData *) p )[index].nFilters = value; return ( (STnsData *) p )[index].filter; diff --git a/lib_com/tools.c b/lib_com/tools.c index 3d08b428fd6d54631740c7f36c7304c3e6b1b72b..db7c5a3f8e7a82c0653b81c6ba08031b6abf47a9 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * own_random() @@ -499,38 +499,6 @@ void mvl2l( } -/*---------------------------------------------------------------------* - * thr_f() - * - * Thresholding of input value such that x_min < x < x_max - *---------------------------------------------------------------------*/ - -/*! r: thresholded value */ -float thr_f( - const float x, /* i : input value */ - const float x_min, /* i : lower thresholod */ - const float x_max /* o : upper threshold */ -) -{ - float y; - - if ( x < x_min ) - { - y = x_min; - } - else if ( x > x_max ) - { - y = x_max; - } - else - { - y = x; - } - - return y; -} - - /*---------------------------------------------------------------------* * maximum() * @@ -799,6 +767,7 @@ float inv_sqrt( return (float) ( 1.0 / sqrt( x ) ); } + /*-------------------------------------------------------------------* * conv() * @@ -1071,6 +1040,7 @@ int16_t usquant( return idx; } + /*-------------------------------------------------------------------* * usdequant() * @@ -1343,7 +1313,7 @@ float var( float v; int16_t i; - m = mean( x, (const int16_t) len ); + m = mean( x, len ); v = 0.0f; for ( i = 0; i < len; i++ ) @@ -1476,8 +1446,7 @@ void polezero_filter( return; } -#define WMC_TOOL_MAN - +#define WMC_TOOL_SKIP static float fleft_shift( float input, const int16_t shift ) { return ( input * (float) pow( 2.0, (double) shift ) ); @@ -1487,7 +1456,7 @@ static float fright_shift( float input, const int16_t shift ) { return ( input * (float) pow( 0.5, (double) shift ) ); } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /*--------------------------------------------------------------------------------* @@ -1517,7 +1486,7 @@ float root_a( return 0.0; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "a" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ @@ -1536,7 +1505,7 @@ float root_a( mod_a *= 2.0; shift_a++; } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP shift_a &= 0xfffe; mod_a = fleft_shift( a, shift_a ); @@ -1584,21 +1553,23 @@ float root_a_over_b( { return 0.0; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP if ( isinf( a ) ) +#undef WMC_TOOL_SKIP { return FLT_MAX; } +#define WMC_TOOL_SKIP if ( isinf( b ) ) +#undef WMC_TOOL_SKIP { return 0.f; } -#undef WMC_TOOL_MAN a += 0x00000001; b += 0x00000001; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "a" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ @@ -1617,12 +1588,12 @@ float root_a_over_b( mod_a *= 2.0; shift_a++; } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP shift_a &= 0xfffe; mod_a = fleft_shift( a, shift_a ); -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "b" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ @@ -1641,7 +1612,7 @@ float root_a_over_b( mod_b *= 2.0; shift_b++; } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP shift_b &= 0xfffe; mod_b = fleft_shift( b, shift_b ); diff --git a/lib_com/trans_direct.c b/lib_com/trans_direct.c index d6e35d583eda5bf7ccf39a7192f7c2ee84d207f9..964ba36f76cb531d2dee5a5b7e750a42374f38c4 100644 --- a/lib_com/trans_direct.c +++ b/lib_com/trans_direct.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * direct_transform() diff --git a/lib_com/trans_inv.c b/lib_com/trans_inv.c index 18c5fe0431e33607140874eb7d535d882eba935b..1eea807b2ffe951fcb9df0598f8135a5a333ccc4 100644 --- a/lib_com/trans_inv.c +++ b/lib_com/trans_inv.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * Local constants diff --git a/lib_com/typedef.h b/lib_com/typedef.h index ec617a585742c3e6fa786746c689c40d1e73dae2..9b1ed7bc9327f535c43c82018a4ee7d6e3a5e031 100644 --- a/lib_com/typedef.h +++ b/lib_com/typedef.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_com/vlpc_2st_com.c b/lib_com/vlpc_2st_com.c index 86fdf68c5ff96114e7cc32be3f1f420811c94d25..e180454c3e412fbba0de5970fdc6ae0173705531 100644 --- a/lib_com/vlpc_2st_com.c +++ b/lib_com/vlpc_2st_com.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * lsf_weight_2st() diff --git a/lib_com/weight.c b/lib_com/weight.c index e50707b68821764d48b88c44799f57c09d8ae3ab..6c2e1c291af10340e0883d603fbb559fc1b5b309 100644 --- a/lib_com/weight.c +++ b/lib_com/weight.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * sfm2mqb() diff --git a/lib_com/weight_a.c b/lib_com/weight_a.c index 0eda2133cea20421320bb8ac3ef9ad1f735270c3..96b8014e41ceb31bed1edbd4067e1fe2f628d509 100644 --- a/lib_com/weight_a.c +++ b/lib_com/weight_a.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------ * weight_a() diff --git a/lib_com/wi.c b/lib_com/wi.c index 6cf3c1d2b183a5e4d4a4a12ace7fe25d0eb786bf..7ec30010fe0365b2eb6a84cc8a295790afd98ca8 100644 --- a/lib_com/wi.c +++ b/lib_com/wi.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants @@ -73,13 +73,15 @@ ivas_error DTFS_new( int16_t i; DTFS_STRUCTURE *dtfs = NULL; - dtfs = (DTFS_STRUCTURE *) count_malloc( sizeof( DTFS_STRUCTURE ) ); - - if ( dtfs == NULL ) + if ( ( dtfs = (DTFS_STRUCTURE *) malloc( sizeof( DTFS_STRUCTURE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTFS (SC-VBR) structure\n" ) ); } +#define WMC_TOOL_SKIP + MOVE( 2 ); + LOOP( 1 ); + MOVE( 2 ); dtfs->lag = 0; dtfs->nH = 0; dtfs->nH_4kHz = 0; @@ -94,6 +96,8 @@ ivas_error DTFS_new( dtfs->sampling_rate = -1; *dtfs_out = dtfs; +#undef WMC_TOOL_SKIP + return IVAS_ERR_OK; } @@ -110,19 +114,27 @@ void DTFS_copy( ) { int16_t k; + +#define WMC_TOOL_SKIP + LOOP( 1 ); for ( k = 0; k < MAXLAG_WI; k++ ) { + MOVE( 1 ); Xout->a[k] = Xinp.a[k]; } + LOOP( 1 ); for ( k = 0; k < MAXLAG_WI; k++ ) { + MOVE( 1 ); Xout->b[k] = Xinp.b[k]; } + MOVE( 1 ); Xout->lag = Xinp.lag; Xout->nH = Xinp.nH; Xout->nH_4kHz = Xinp.nH_4kHz; Xout->upper_cut_off_freq_of_interest = Xinp.upper_cut_off_freq_of_interest; Xout->upper_cut_off_freq = Xinp.upper_cut_off_freq; +#undef WMC_TOOL_SKIP return; } @@ -142,21 +154,34 @@ void DTFS_sub( ) { int16_t i; + +#define WMC_TOOL_SKIP + MULT( 1 ); + LOOP( 1 ); for ( i = 0; i <= X1.lag / 2; i++ ) { + MOVE( 1 ); + MULT( 1 ); tmp->a[i] = X1.a[i]; + MOVE( 1 ); tmp->b[i] = X1.b[i]; } + MULT( 1 ); + LOOP( 1 ); for ( i = 0; i <= X2.lag / 2; i++ ) { + MAC( 1 ); tmp->a[i] -= X2.a[i]; + ADD( 1 ); tmp->b[i] -= X2.b[i]; } + MOVE( 1 ); tmp->lag = max( X1.lag, X2.lag ); tmp->nH = max( X1.nH, X2.nH ); tmp->nH_4kHz = max( X1.nH_4kHz, X2.nH_4kHz ); tmp->upper_cut_off_freq_of_interest = X1.upper_cut_off_freq_of_interest; tmp->upper_cut_off_freq = X1.upper_cut_off_freq; +#undef WMC_TOOL_SKIP return; } @@ -181,12 +206,15 @@ static void DTFS_fast_fs_inv( N = X1_DTFS->lag; } +#define WMC_TOOL_SKIP /* Populate the dbuf array */ dbuf[1] = X1_DTFS->a[0]; dbuf[2] = 0.0; for ( i = 1; i < M_2; i++ ) { + MAC( 1 ); dbuf[2 * i + 1] = X1_DTFS->a[i] * N_2; + MAC( 1 ); dbuf[2 * i + 2] = X1_DTFS->b[i] * N_2; } @@ -200,15 +228,21 @@ static void DTFS_fast_fs_inv( /* Zero-padding in the frequency domain */ for ( ; i < N_2; i++ ) { + MOVE( 1 ); + MAC( 2 ); dbuf[2 * i + 1] = dbuf[2 * i + 2] = 0.0; } + FUNC( 3 ); realft( dbuf, N_2, -1 ); for ( i = 1; i <= N; i++ ) { + MULT( 1 ); + ADD( 1 ); out[i - 1] = dbuf[i] / N_2; } +#undef WMC_TOOL_SKIP return; } @@ -236,53 +270,94 @@ static float DTFS_alignment_weight( float pwf = 0.7f, tmplpc[M + 1]; DTFS_STRUCTURE X1_DTFS; +#define WMC_TOOL_SKIP + FUNC( 2 ); DTFS_copy( &X1_DTFS, refX1_DTFS ); + FUNC( 2 ); DTFS_adjustLag( &X1_DTFS, X2_DTFS.lag ); + FUNC( 3 ); + ADD( 1 ); DTFS_poleFilter( &X1_DTFS, LPC1, M + 1 ); + MOVE( 1 ); tmp = 1.0; + LOOP( 1 ); for ( k = 0, tmp = 1.0; k < M + 1; k++ ) { + MOVE( 1 ); + MULT( 2 ); tmplpc[k] = LPC1[k] * ( tmp *= pwf ); } - + FUNC( 3 ); DTFS_zeroFilter( &X1_DTFS, tmplpc, M + 1 ); + FUNC( 3 ); DTFS_poleFilter( &X2_DTFS, LPC2, M + 1 ); + MOVE( 1 ); + LOOP( 1 ); for ( k = 0, tmp = 1.0; k < M + 1; k++ ) { /* can be stored as a table */ + MULT( 1 ); tmplpc[k] = LPC2[k] * ( tmp *= pwf ); } + FUNC( 3 ); DTFS_zeroFilter( &X2_DTFS, tmplpc, M + 1 ); + MOVE( 1 ); + ADD( 1 ); maxcorr = (float) -HUGE_VAL; + MOVE( 1 ); fshift = Eshift; + MOVE( 1 ); + MULT( 1 ); Adiff = max( 6, 0.15f * X2_DTFS.lag ); + LOGIC( 1 ); if ( X2_DTFS.lag < 60 ) { + MOVE( 1 ); diff = 0.25; } else { + MOVE( 1 ); diff = 0.5; } + ADD( 1 ); + ADD( 1 ); + LOOP( 1 ); for ( n = Eshift - Adiff; n <= Eshift + Adiff; n += diff ) { + MOVE( 2 ); + ADD( 1 ); corr = tmp = 0.0f; /* bit-exact optimization - PI2/X2_DTFS.lag should be counted as a single divide */ + MULT( 1 ); tmp1 = (float) ( PI2 * n / X2_DTFS.lag ); + ADD( 1 ); + LOOP( 1 ); for ( k = 0; k <= min( X2_DTFS.lag >> 1, X2_DTFS.nH_4kHz ); k++, tmp += tmp1 ) { /* Not counting math function cos and sin since they will be implemented as look-up tables */ + MAC( 1 ); + ADD( 1 ); corr += (float) ( ( X1_DTFS.a[k] * X2_DTFS.a[k] + X1_DTFS.b[k] * X2_DTFS.b[k] ) * cos( tmp ) ); + MAC( 1 ); + ADD( 1 ); corr += (float) ( ( X1_DTFS.b[k] * X2_DTFS.a[k] - X1_DTFS.a[k] * X2_DTFS.b[k] ) * sin( tmp ) ); } + MOVE( 1 ); + MAC( 2 ); + ABS( 1 ); wcorr = (float) ( corr * ( 1.0f - 0.01f * fabs( n - Eshift ) ) ); + LOGIC( 1 ); if ( wcorr > maxcorr ) { + MOVE( 1 ); fshift = n; + MOVE( 1 ); maxcorr = wcorr; } } +#undef WMC_TOOL_SKIP return fshift; } @@ -303,32 +378,53 @@ float DTFS_alignment_full( int16_t k; float maxcorr, corr, tmp, tmp1, fshift, n, diff; +#define WMC_TOOL_SKIP + LOGIC( 1 ); if ( X1_DTFS.lag < X2_DTFS.lag ) { + FUNC( 2 ); DTFS_zeroPadd( X2_DTFS.lag, &X1_DTFS ); } + MOVE( 1 ); + ADD( 1 ); maxcorr = (float) -HUGE_VAL; /* bit-exact optimization - 1/num_steps can be constant => should be counted as a multiply */ + MOVE( 1 ); + MULT( 1 ); diff = (float) X2_DTFS.lag / num_steps; + LOOP( 1 ); for ( fshift = n = 0.0; n < (float) X2_DTFS.lag; n += diff ) { + MOVE( 2 ); corr = tmp = 0.0f; + MOVE( 1 ); + MULT( 2 ); tmp1 = (float) ( PI2 * n / X2_DTFS.lag ); + ADD( 1 ); + LOOP( 1 ); for ( k = 0; k <= min( X2_DTFS.lag >> 1, X2_DTFS.nH_4kHz ); k++, tmp += tmp1 ) { + MAC( 1 ); + ADD( 2 ); corr += (float) ( ( X1_DTFS.a[k] * X2_DTFS.a[k] + X1_DTFS.b[k] * X2_DTFS.b[k] ) * cos( tmp ) ); + MAC( 1 ); + ADD( 1 ); corr += (float) ( ( X1_DTFS.b[k] * X2_DTFS.a[k] - X1_DTFS.a[k] * X2_DTFS.b[k] ) * sin( tmp ) ); } + LOGIC( 1 ); if ( corr > maxcorr ) { + MOVE( 1 ); fshift = n; + MOVE( 1 ); maxcorr = corr; } } +#undef WMC_TOOL_SKIP return fshift; } @@ -350,12 +446,23 @@ void DTFS_phaseShift( { int16_t k; float tmp, tmp2 = 0.0f; + +#define WMC_TOOL_SKIP + ADD( 1 ); + LOOP( 1 ); for ( k = 0; k <= min( X->lag >> 1, X->nH ); k++, tmp2 += ph ) { + MOVE( 1 ); + ADD( 1 ); tmp = X->a[k]; + MOVE( 1 ); + MAC( 1 ); X->a[k] = (float) ( tmp * cos( tmp2 ) - X->b[k] * sin( tmp2 ) ); + MOVE( 1 ); + MAC( 1 ); X->b[k] = (float) ( tmp * sin( tmp2 ) + X->b[k] * cos( tmp2 ) ); } +#undef WMC_TOOL_SKIP return; } @@ -375,22 +482,36 @@ void DTFS_zeroPadd( int16_t i; float diff; +#define WMC_TOOL_SKIP + LOGIC( 1 ); if ( N == X->lag ) { +#undef WMC_TOOL_SKIP return; +#define WMC_TOOL_SKIP } + ADD( 1 ); + LOOP( 1 ); for ( i = ( X->lag >> 1 ) + 1; i <= N >> 1; i++ ) { + MOVE( 2 ); X->a[i] = X->b[i] = 0.0; } + MOVE( 1 ); X->lag = N; /* recompute nH for new lag */ X->nH = (int16_t) floor( X->upper_cut_off_freq / ( 12800.0 / X->lag ) ); + MOVE( 1 ); + MULT( 1 ); diff = 12800.0f / X->lag; + MULT( 1 ); + ADD( 1 ); + LOGIC( 1 ); if ( X->upper_cut_off_freq - ( diff * X->nH ) >= diff ) { X->nH++; } +#undef WMC_TOOL_SKIP return; } @@ -399,7 +520,7 @@ void DTFS_zeroPadd( /*-------------------------------------------------------------------* * DTFS_to_fs() * - * DTFS to fs conversion. + * DTFS to Fs conversion. *-------------------------------------------------------------------*/ void DTFS_to_fs( @@ -407,7 +528,7 @@ void DTFS_to_fs( const int16_t N, /* i : Length of input vector */ DTFS_STRUCTURE *X, /* o : DTFS structure with a, b, lag */ const int32_t sampling_rate, /* i : sampling rate */ - const int16_t FR_flag /* i : FR flag */ + const int16_t FR_flag /* i : FR flag */ ) { int16_t n; @@ -436,11 +557,19 @@ void DTFS_to_fs( X->sampling_rate = INT_FS_16k; } +#define WMC_TOOL_SKIP X->lag = N; + MOVE( 1 ); + MULT( 1 ); nH_band = (int16_t) floor( X->upper_cut_off_freq / ( 12800.0 / X->lag ) ); nH_4kHz = (int16_t) floor( 4000 / ( 12800.0 / X->lag ) ); + MOVE( 1 ); + MULT( 1 ); diff = 12800.0f / X->lag; + MULT( 1 ); + ADD( 1 ); + LOGIC( 1 ); if ( X->upper_cut_off_freq - ( diff * nH_band ) >= diff ) { nH_band++; @@ -450,53 +579,80 @@ void DTFS_to_fs( nH_4kHz++; } /* Number of harmonics excluding the ones at 0 and at pi */ + MOVE( 1 ); + MULT( 1 ); + ADD( 1 ); nH = ( N - 1 ) >> 1; /* The DC component */ X->a[0] = 0.0; X->b[0] = 0.0; + LOOP( 1 ); for ( n = 0; n < N; n++ ) { + ADD( 1 ); X->a[0] += x[n]; } + MULT( 1 ); X->a[0] /= N; /* Strictly set the DC componet to zero */ + MOVE( 1 ); X->a[0] = 0.0; /* The harmonics excluding the one at pi */ + LOOP( 1 ); for ( k = 1; k <= nH; k++ ) { X->a[k] = x[0]; X->b[k] = 0.0; + MOVE( 2 ); + MULT( 1 ); sum = tmp = (float) ( PI2 * k / N ); + LOOP( 1 ); for ( n = 1; n < N; n++, sum += tmp ) { + ADD( 1 ); X->a[k] += (float) ( x[n] * cos( sum ) ); + ADD( 1 ); X->b[k] += (float) ( x[n] * sin( sum ) ); } + MULT( 2 ); X->a[k] *= ( 2.0f / N ); + MULT( 2 ); X->b[k] *= ( 2.0f / N ); } /* The harmonic at 'pi' */ + LOGIC( 1 ); if ( N % 2 == 0 ) { + MOVE( 1 ); X->a[k] = 0.0; + MOVE( 1 ); tmp = 1.0; + LOOP( 1 ); for ( n = 0; n < N; n++, tmp *= -1.0 ) { + ADD( 1 ); X->a[k] += x[n] * tmp; } + MULT( 1 ); X->a[k] /= N; + MOVE( 1 ); X->b[k] = 0.0; } + ADD( 1 ); + LOOP( 1 ); for ( k = nH_band + 1; k <= min( ( X->lag >> 1 ), ( MAXLAG_WI - 1 ) ); k++ ) { + MOVE( 1 ); X->a[k] = 0.0; + MOVE( 1 ); X->b[k] = 0.0; } X->nH = nH_band; X->nH_4kHz = nH_4kHz; +#undef WMC_TOOL_SKIP return; } @@ -518,15 +674,25 @@ void DTFS_fs_inv( float phase, tmp; int16_t k, n; +#define WMC_TOOL_SKIP + LOOP( 1 ); for ( n = 0; n < N; n++ ) { + MOVE( 1 ); x[n] = X->a[0]; + MOVE( 2 ); + MAC( 1 ); tmp = phase = (float) ( PI2 * n / X->lag + ph0 ); + ADD( 1 ); + LOOP( 1 ); for ( k = 1; k <= min( X->lag >> 1, X->nH ); k++, tmp += phase ) { + MAC( 1 ); + ADD( 1 ); x[n] += (float) ( X->a[k] * cos( tmp ) + X->b[k] * sin( tmp ) ); } } +#undef WMC_TOOL_SKIP return; } @@ -577,12 +743,21 @@ static void DTFS_transform( IVAS_ERROR( error, "Error creating DTFS structure 3" ); } +#define WMC_TOOL_SKIP + FUNC( 2 ); DTFS_copy( tmp1_dtfs, X ); + FUNC( 2 ); DTFS_copy( tmp2_dtfs, X2 ); + FUNC( 3 ); DTFS_fast_fs_inv( tmp1_dtfs, x1_256, 256 ); + FUNC( 3 ); DTFS_fast_fs_inv( tmp2_dtfs, x2_256, 256 ); - + MOVE( 1 ); + MAC( 1 ); + ADD( 1 ); + LOG( 1 ); tmp = (float) ( log( 1.0 - WI_THRESHLD ) / ( X.lag - N ) ); + LOOP( 1 ); for ( i = 0; i < N; i++ ) { if ( FR_flag == 0 ) @@ -591,11 +766,13 @@ static void DTFS_transform( if ( N - WI_SAMPLE_THLD > X.lag ) { /* pre-computed and stored in a table */ + MOVE( 1 ); w = (float) ( 1.0 - exp( -( i + 1 ) * tmp ) ); } else { /* can be a look-up table */ + MOVE( 1 ); w = (float) ( i + 1 ) / N; } } @@ -618,23 +795,30 @@ static void DTFS_transform( w = (float) ( i + 1 ) / N1; } else - { w = 1.0; - } } } /* add sinc interpolation of two time domain waveforms at appropriate phase position */ - j = ( LL_OS * 10 + (int16_t) rint_new( phase[i] * LL_OS / PI2 ) ) % LL_OS; + MULT( 1 ); + DIV( 1 ); + FUNC( 1 ); + ADD( 1 ); + j = ( LL_OS * 10 + (int) rint_new( phase[i] * LL_OS / PI2 ) ) % LL_OS; if ( j < 0 ) { j = 0; } + MOVE( 1 ); + DIV( 1 ); k = j % WARP_OS_RATE; + MOVE( 1 ); + MULT( 1 ); l1 = j / WARP_OS_RATE; + MOVE( 2 ); set_f( x_r_fx, 0.0f, L_FRAME ); @@ -652,9 +836,12 @@ static void DTFS_transform( x_r_fx[m] = x1_256[m] * temp_w + x2_256[m] * w; } + LOOP( 1 ); for ( j1 = 0, sum1 = sum2 = 0.0; j1 < OSLENGTH; j1++ ) { /* mult or div by constants should be done once outside the loop */ + DIV( 1 ); + ADD( 1 ); m = ( 1000 * LL + l1 - OSLENGTH / 2 + j1 ) % LL; if ( m < 0 ) @@ -667,10 +854,11 @@ static void DTFS_transform( out[i] = sum1; } +#undef WMC_TOOL_SKIP - count_free( tmp1_dtfs ); - count_free( tmp2_dtfs ); - count_free( tmp3_dtfs ); + free( tmp1_dtfs ); + free( tmp2_dtfs ); + free( tmp3_dtfs ); return; } @@ -691,23 +879,43 @@ void DTFS_zeroFilter( float tmp, tmp1, tmp2, sum1, sum2; int16_t k, n; +#define WMC_TOOL_SKIP + MOVE( 1 ); + MULT( 1 ); tmp1 = (float) ( PI2 / X->lag ); + LOOP( 1 ); for ( k = 0; k <= min( X->lag >> 1, X->nH ); k++ ) { + MOVE( 2 ); + MULT( 1 ); tmp = tmp2 = k * tmp1; /* Calculate sum1 and sum2 */ + MOVE( 1 ); sum1 = 1.0; + MOVE( 1 ); sum2 = 0.0; + ADD( 1 ); + LOOP( 1 ); for ( n = 0; n < N; n++, tmp2 += tmp ) { + MULT( 1 ); + ADD( 2 ); sum1 += (float) ( LPC[n] * cos( tmp2 ) ); + MULT( 1 ); + ADD( 1 ); sum2 += (float) ( LPC[n] * sin( tmp2 ) ); } /* Calculate the circular convolution */ + MOVE( 1 ); tmp = X->a[k]; + MOVE( 1 ); + MAC( 1 ); X->a[k] = tmp * sum1 - X->b[k] * sum2; + MOVE( 1 ); + MAC( 1 ); X->b[k] = X->b[k] * sum1 + tmp * sum2; } +#undef WMC_TOOL_SKIP return; } @@ -728,24 +936,45 @@ void DTFS_poleFilter( float tmp, tmp1, tmp2, sum1, sum2; int16_t k, n; +#define WMC_TOOL_SKIP + MOVE( 1 ); + MULT( 1 ); tmp1 = (float) ( PI2 / X->lag ); + LOOP( 1 ); for ( k = 0; k <= min( X->lag >> 1, X->nH ); k++ ) { + MOVE( 2 ); + MULT( 1 ); tmp = tmp2 = k * tmp1; /* Calculate sum1 and sum2 */ + MOVE( 1 ); sum1 = 1.0; + MOVE( 1 ); sum2 = 0.0; + ADD( 1 ); + LOOP( 1 ); for ( n = 0; n < N; n++, tmp2 += tmp ) { + MULT( 1 ); + ADD( 2 ); sum1 += (float) ( LPC[n] * cos( tmp2 ) ); + MULT( 1 ); + ADD( 1 ); sum2 += (float) ( LPC[n] * sin( tmp2 ) ); } /* Calculate the circular convolution */ + MOVE( 1 ); tmp = X->a[k]; + MAC( 1 ); tmp2 = sum1 * sum1 + sum2 * sum2; + MAC( 1 ); + DIV( 1 ); X->a[k] = ( tmp * sum1 + X->b[k] * sum2 ) / tmp2; + MAC( 1 ); + ADD( 1 ); X->b[k] = ( -tmp * sum2 + X->b[k] * sum1 ) / tmp2; } +#undef WMC_TOOL_SKIP return; } @@ -765,17 +994,30 @@ static float DTFS_setEngy( int16_t k; float en1, tmp; +#define WMC_TOOL_SKIP + FUNC( 1 ); + MOVE( 1 ); en1 = DTFS_getEngy( *X_DTFS ); + LOGIC( 1 ); if ( en1 == 0.0 ) { +#undef WMC_TOOL_SKIP return 0.0; +#define WMC_TOOL_SKIP } + MOVE( 1 ); + DIV( 1 ); + SQRT( 1 ); tmp = (float) sqrt( en2 / en1 ); + LOOP( 1 ); for ( k = 0; k <= min( X_DTFS->lag >> 1, X_DTFS->nH ); k++ ) { + MULT( 1 ); X_DTFS->a[k] *= tmp; + MULT( 1 ); X_DTFS->b[k] *= tmp; } +#undef WMC_TOOL_SKIP return en1; } @@ -795,30 +1037,50 @@ void DTFS_adjustLag( int16_t k; float en, diff; +#define WMC_TOOL_SKIP + LOGIC( 1 ); if ( N == X_DTFS->lag ) { +#undef WMC_TOOL_SKIP return; +#define WMC_TOOL_SKIP } + LOGIC( 1 ); if ( N > X_DTFS->lag ) { + + FUNC( 2 ); DTFS_zeroPadd( N, X_DTFS ); } else { + FUNC( 1 ); + MOVE( 1 ); en = DTFS_getEngy( *X_DTFS ); + ADD( 1 ); + LOOP( 1 ); for ( k = ( N >> 1 ) + 1; k <= min( X_DTFS->lag >> 1, X_DTFS->nH ); k++ ) { + MOVE( 1 ); X_DTFS->a[k] = 0.0; + MOVE( 1 ); X_DTFS->b[k] = 0.0; } + FUNC( 2 ); DTFS_setEngy( X_DTFS, en ); + MOVE( 1 ); X_DTFS->lag = N; /* recompute nH for new lag */ X_DTFS->nH = (int16_t) floor( X_DTFS->upper_cut_off_freq / ( 12800.0 / X_DTFS->lag ) ); X_DTFS->nH_4kHz = (int16_t) floor( 4000.0 / ( 12800.0 / X_DTFS->lag ) ); + MOVE( 1 ); + MULT( 1 ); diff = 12800.0f / X_DTFS->lag; + MULT( 1 ); + ADD( 1 ); + LOGIC( 1 ); if ( X_DTFS->upper_cut_off_freq - ( diff * X_DTFS->nH ) >= diff ) { X_DTFS->nH++; @@ -828,6 +1090,7 @@ void DTFS_adjustLag( X_DTFS->nH_4kHz++; } } +#undef WMC_TOOL_SKIP return; } @@ -847,16 +1110,27 @@ float DTFS_getEngy( float en; en = 0.0f; +#define WMC_TOOL_SKIP + LOOP( 1 ); for ( k = 1; k <= min( ( X.lag - 1 ) >> 1, X.nH ); k++ ) { + MAC( 1 ); + ADD( 1 ); en += X.a[k] * X.a[k] + X.b[k] * X.b[k]; } + MULT( 1 ); en /= 2.0; + MULT( 1 ); + ADD( 1 ); en += X.a[0] * X.a[0]; + LOGIC( 1 ); if ( X.lag % 2 == 0 ) { + MAC( 1 ); + ADD( 1 ); en += X.a[k] * X.a[k] + X.b[k] * X.b[k]; } +#undef WMC_TOOL_SKIP return en; } @@ -875,19 +1149,31 @@ void DTFS_car2pol( int16_t k; float tmp; +#define WMC_TOOL_SKIP + LOOP( 1 ); for ( k = 1; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++ ) { + MOVE( 1 ); tmp = X->a[k]; + MOVE( 1 ); + FUNC( 2 ); + MULT( 1 ); X->a[k] = (float) ( 0.5f * sqrt( tmp * tmp + X->b[k] * X->b[k] ) ); + MOVE( 1 ); X->b[k] = (float) atan2( X->b[k], tmp ); } - + LOGIC( 1 ); if ( X->lag % 2 == 0 ) { + MOVE( 1 ); tmp = X->a[k]; + FUNC( 2 ); + MOVE( 1 ); X->a[k] = (float) sqrt( tmp * tmp + X->b[k] * X->b[k] ); + MOVE( 1 ); X->b[k] = (float) atan2( X->b[k], tmp ); } +#undef WMC_TOOL_SKIP return; } @@ -906,19 +1192,32 @@ void DTFS_pol2car( int16_t k; float tmp; +#define WMC_TOOL_SKIP + LOOP( 1 ); for ( k = 1; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++ ) { + MOVE( 1 ); tmp = X->b[k]; + MOVE( 1 ); + MULT( 2 ); X->b[k] = (float) ( 2.0f * X->a[k] * sin( tmp ) ); + MOVE( 1 ); + MULT( 2 ); X->a[k] = (float) ( 2.0f * X->a[k] * cos( tmp ) ); } - + LOGIC( 1 ); if ( X->lag % 2 == 0 ) { + MOVE( 1 ); tmp = X->b[k]; + MOVE( 1 ); + MULT( 1 ); X->b[k] = (float) ( X->a[k] * sin( tmp ) ); + MOVE( 1 ); + MULT( 1 ); X->a[k] = (float) ( X->a[k] * cos( tmp ) ); } +#undef WMC_TOOL_SKIP return; } @@ -947,11 +1246,20 @@ float DTFS_setEngyHarm( en1 = 0.0f; count = 0; + +#define WMC_TOOL_SKIP + LOGIC( 1 ); if ( f1 == 0.0 ) { + MULT( 1 ); + ADD( 1 ); en1 += X->a[0] * X->a[0]; count++; } + MOVE( 1 ); + ADD( 1 ); + ADD( 1 ); + LOOP( 1 ); for ( k = 1, tmp = diff; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++, tmp += diff ) { if ( X->a[k] < EPSILON ) @@ -959,8 +1267,11 @@ float DTFS_setEngyHarm( X->a[k] = 0; } + LOGIC( 1 ); if ( tmp > f1 && tmp <= f2 ) { + MULT( 1 ); + ADD( 1 ); en1 += X->a[k] * X->a[k]; count++; } @@ -971,6 +1282,8 @@ float DTFS_setEngyHarm( count = 1; } + + DIV( 1 ); en1 /= count; if ( en2 < 0.0 ) @@ -978,25 +1291,41 @@ float DTFS_setEngyHarm( en2 = 0.0; } + LOGIC( 1 ); if ( en1 > 0.0 ) { + MOVE( 1 ); + DIV( 1 ); + SQRT( 1 ); factor = (float) sqrt( en2 / en1 ); } else { + MOVE( 1 ); factor = 0.0f; } + LOGIC( 1 ); if ( g1 == 0.0 ) { + MULT( 1 ); X->a[k] *= factor; } + MOVE( 1 ); + ADD( 1 ); + ADD( 1 ); + LOOP( 1 ); for ( k = 1, tmp = diff; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++, tmp += diff ) { + ADD( 1 ); + ADD( 1 ); + LOGIC( 1 ); if ( tmp > g1 && tmp <= g2 ) { + MULT( 1 ); X->a[k] *= factor; } } +#undef WMC_TOOL_SKIP return (float) ( en1 + 1e-20 ); } @@ -1021,6 +1350,8 @@ static void cubicPhase( int16_t n; double diff; +#define WMC_TOOL_SKIP + ADD( 1 ); N -= (int16_t) L2; if ( N <= 0 ) @@ -1029,29 +1360,65 @@ static void cubicPhase( } /* Computation of the coefficients of the cubic phase function */ + MOVE( 1 ); + DIV( 1 ); f1 = (float) ( PI2 / L1 ); + MOVE( 1 ); + DIV( 1 ); f2 = (float) ( PI2 / L2 ); + MOVE( 1 ); + DIV( 1 ); ph1 = (float) fmod( (double) ( ph1 ), PI2 ); + MOVE( 1 ); + DIV( 1 ); ph2 = (float) fmod( (double) ( ph2 ), PI2 ); + MOVE( 1 ); coef[3] = ph1; + MOVE( 1 ); coef[2] = f1; + MOVE( 1 ); + MAC( 1 ); + ADD( 1 ); + FUNC( 1 ); + ADD( 1 ); factor = (float) ( anint( ( ph1 - ph2 + 0.5 * N * ( f2 + f1 ) ) / PI2 ) ); + MOVE( 1 ); + ADD( 1 ); c1 = f2 - f1; + MOVE( 1 ); + MAC( 1 ); + ADD( 2 ); c2 = (float) ( ph2 - ph1 - N * f1 + PI2 * factor ); + MOVE( 1 ); + MAC( 1 ); + DIV( 1 ); coef[0] = ( N * c1 - 2 * c2 ) / ( N * N * N ); + MOVE( 1 ); + MULT( 4 ); + DIV( 1 ); + ADD( 1 ); coef[1] = ( c1 - 3 * N * N * coef[0] ) / ( 2 * N ); - /* Computation of the phase value at each sample point */ + MOVE( 1 ); phOut[0] = ph1; + LOOP( 1 ); for ( n = 1; n < N; n++ ) { + MOVE( 1 ); phOut[n] = _POLY3( n, coef ); } + MOVE( 1 ); + MULT( 1 ); diff = (float) ( PI2 / L2 ); - for ( ; n < N + (int16_t) L2; n++ ) + ADD( 1 ); + LOOP( 1 ); + for ( ; n < N + (int) L2; n++ ) { + MOVE( 1 ); + ADD( 2 ); phOut[n] = (float) ( phOut[n - 1] + diff ); } +#undef WMC_TOOL_SKIP return; } @@ -1085,12 +1452,21 @@ void DTFS_to_erb( erb = &( erb_WB[0] ); } +#define WMC_TOOL_SKIP + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { + MOVE( 1 ); count[i] = 0; + MOVE( 1 ); out[i] = 0.0; } + MOVE( 1 ); + MULT( 1 ); diff = 12800.0f / X.lag; + MOVE( 2 ); + ADD( 1 ); + LOOP( 1 ); for ( i = j = 0, freq = 0.0; i <= min( X.lag >> 1, X.nH ); i++, freq += diff ) { if ( !( freq <= erb[num_erb] ) ) @@ -1098,8 +1474,10 @@ void DTFS_to_erb( freq = erb[num_erb]; } + LOOP( 1 ); for ( ; j < num_erb; j++ ) { + LOGIC( 1 ); if ( freq < erb[j + 1] ) { if ( X.a[i] < 0.0f ) @@ -1107,19 +1485,24 @@ void DTFS_to_erb( X.a[i] = 0.0f; } + ADD( 1 ); out[j] += X.a[i]; count[j]++; break; } } } + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { + LOGIC( 1 ); if ( count[i] > 1 ) { + DIV( 1 ); out[i] /= count[i]; } } +#undef WMC_TOOL_SKIP return; } @@ -1155,18 +1538,33 @@ void erb_slot( upper_cut_off_freq = 6400; erb = &( erb_WB[0] ); } + +#define WMC_TOOL_SKIP + MOVE( 1 ); + MULT( 1 ); nH_band = (int16_t) floor( upper_cut_off_freq / ( 12800.0 / lag ) ); + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { + MOVE( 1 ); out[i] = 0; + MOVE( 1 ); mfreq[i] = 0.0; } + MOVE( 1 ); + MULT( 1 ); diff = 12800.0f / lag; + MULT( 1 ); + ADD( 1 ); + LOGIC( 1 ); if ( upper_cut_off_freq - ( diff * nH_band ) >= diff ) { nH_band++; } + MOVE( 2 ); + ADD( 1 ); + LOOP( 1 ); for ( i = j = 0, freq = 0.0; i <= min( lag >> 1, nH_band ); i++, freq += diff ) { @@ -1175,26 +1573,33 @@ void erb_slot( freq = erb[num_erb]; } + MOVE( 1 ); freq = min( freq, upper_cut_off_freq ); + LOOP( 1 ); for ( ; j < num_erb; j++ ) { + LOGIC( 1 ); if ( freq < erb[j + 1] ) { + ADD( 1 ); mfreq[j] += freq; out[j]++; break; } } } - + LOOP( 1 ); for ( j = 0; j < num_erb; j++ ) { + LOGIC( 1 ); if ( out[j] > 1 ) { + DIV( 1 ); mfreq[j] /= out[j]; } } +#undef WMC_TOOL_SKIP return; } @@ -1232,24 +1637,38 @@ void DTFS_erb_inv( erb = &( erb_WB[0] ); } +#define WMC_TOOL_SKIP + MOVE( 1 ); f[m] = 0.0; + MOVE( 1 ); amp[m] = 0.0; m++; + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { + LOGIC( 1 ); if ( slot[i] != 0 ) { + MOVE( 1 ); f[m] = mfreq[i]; + MOVE( 1 ); amp[m] = in[i]; m++; } } + MOVE( 1 ); f[m] = upper_cut_off_freq; + MOVE( 1 ); amp[m] = 0.0; m++; + MOVE( 1 ); + MULT( 1 ); diff = 12800.0f / X->lag; + MOVE( 2 ); + ADD( 1 ); + LOOP( 1 ); for ( i = 0, j = 1, freq = 0.0; i <= min( X->lag >> 1, X->nH ); i++, freq += diff ) { if ( !( freq <= erb[num_erb] ) ) @@ -1262,17 +1681,27 @@ void DTFS_erb_inv( m = num_erb + 2; } + LOGIC( 1 ); if ( freq > upper_cut_off_freq ) { + MOVE( 1 ); freq = upper_cut_off_freq; } + LOOP( 1 ); for ( ; j < m; j++ ) { + LOGIC( 1 ); if ( freq <= f[j] ) { + MOVE( 1 ); + MAC( 2 ); + ADD( 1 ); X->a[i] = amp[j] * ( freq - f[j - 1] ) + amp[j - 1] * ( f[j] - freq ); + LOGIC( 1 ); if ( f[j] != f[j - 1] ) { + DIV( 1 ); + ADD( 1 ); X->a[i] /= ( f[j] - f[j - 1] ); } break; @@ -1281,6 +1710,7 @@ void DTFS_erb_inv( X->a[0] = 0.0f; } +#undef WMC_TOOL_SKIP return; } @@ -1303,19 +1733,36 @@ static void LPCPowSpect( float w, tmp, Re, Im; int16_t i, k; +#define WMC_TOOL_SKIP + LOOP( 1 ); for ( k = 0; k < Nf; k++ ) { + MOVE( 1 ); Re = 1.0; + MOVE( 1 ); Im = 0.0; /* Note that freq ranges between [0 UPPER_CUT_OFF_FREQ] */ + MOVE( 1 ); + MULT( 2 ); tmp = (float) ( freq[k] / 12800.0f * PI2 ); + MOVE( 1 ); + ADD( 1 ); + LOOP( 1 ); for ( i = 0, w = tmp; i < Np; i++, w += tmp ) { + MULT( 1 ); + ADD( 2 ); Re += (float) ( LPC[i] * cos( w ) ); + MULT( 1 ); + ADD( 1 ); Im -= (float) ( LPC[i] * sin( w ) ); } + MOVE( 1 ); + MAC( 1 ); + DIV( 1 ); out[k] = 1.0f / ( Re * Re + Im * Im ); } +#undef WMC_TOOL_SKIP return; } @@ -1352,22 +1799,38 @@ void erb_diff( AmpCB1 = AmpCB1_WB; } +#define WMC_TOOL_SKIP + FUNC( 3 ); erb_slot( l, cslot, mfreq, num_erb ); + FUNC( 3 ); erb_slot( pl, pslot, t_prev_erb, num_erb ); + MOVE( 1 ); + ADD( 1 ); + LOOP( 1 ); for ( i = 0, tmp = 1.0f; i < M + 1; i++ ) { + MOVE( 1 ); + MULT( 2 ); + ADD( 1 ); LPC[i] = curr_lsp[i] * ( tmp *= 0.78f ); } + FUNC( 5 ); + ADD( 1 ); LPCPowSpect( mfreq, num_erb, LPC, M + 1, PowSpect ); + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { + MOVE( 1 ); t_prev_erb[i] = prev_erb[i]; } + LOGIC( 1 ); if ( pl > l ) { + MOVE( 1 ); tmp = t_prev_erb[0]; + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { if ( pslot[i] < 0 ) @@ -1375,66 +1838,98 @@ void erb_diff( pslot[i] = 0; } + LOGIC( 1 ); if ( pslot[i] != 0 ) { + MOVE( 1 ); tmp = t_prev_erb[i]; } else { + MOVE( 1 ); t_prev_erb[i] = tmp; } } } else if ( l > pl ) { + MOVE( 1 ); tmp = t_prev_erb[num_erb - 1]; + ADD( 1 ); + LOOP( 1 ); for ( i = num_erb - 1; i >= 0; i-- ) { + LOGIC( 1 ); if ( pslot[i] != 0 ) { + MOVE( 1 ); tmp = t_prev_erb[i]; } else { + MOVE( 1 ); t_prev_erb[i] = tmp; } } } + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { + MOVE( 1 ); + ADD( 1 ); out[i] = curr_erb[i] - t_prev_erb[i]; } /* First Band Amplitude Search */ + MOVE( 1 ); mmse = (float) HUGE_VAL; + MOVE( 1 ); mmseindex = -1; + LOOP( 1 ); for ( j = 0; j < ERB_CBSIZE1; j++ ) { + MOVE( 1 ); tmp = 0.0; + LOOP( 1 ); for ( i = 1; i < 11; i++ ) { + LOGIC( 1 ); if ( cslot[i] != 0 ) { + ADD( 1 ); + LOGIC( 1 ); if ( AmpCB1[j][i - 1] < -t_prev_erb[i] ) { + MOVE( 1 ); + MULT( 1 ); + MULT( 1 ); tmp1 = PowSpect[i] * SQR( curr_erb[i] ); } else { + MOVE( 1 ); + MAC( 1 ); + MULT( 1 ); tmp1 = (float) ( PowSpect[i] * SQR( out[i] - AmpCB1[j][i - 1] ) ); } + LOGIC( 1 ); if ( AmpCB1[j][i - 1] < out[i] ) { + MULT( 1 ); tmp1 *= 0.9f; } + ADD( 1 ); tmp += tmp1; } } + LOGIC( 1 ); if ( tmp < mmse ) { + MOVE( 1 ); mmse = tmp; + MOVE( 1 ); mmseindex = j; } } @@ -1444,33 +1939,50 @@ void erb_diff( mmseindex = 0; } + MOVE( 1 ); index[0] = mmseindex; /* Second Band Amplitude Search */ + MOVE( 1 ); mmse = (float) HUGE_VAL; + MOVE( 1 ); mmseindex = -1; + LOOP( 1 ); for ( j = 0; j < ERB_CBSIZE2; j++ ) { + MOVE( 1 ); tmp = 0.0; for ( i = 11; i < num_erb; i++ ) { if ( num_erb == NUM_ERB_NB ) { + LOGIC( 1 ); if ( cslot[i] != 0 ) { + ADD( 1 ); + LOGIC( 1 ); if ( AmpCB2_NB[j][i - 11] < -t_prev_erb[i] ) { + MOVE( 1 ); + MULT( 1 ); + MULT( 1 ); tmp1 = PowSpect[i] * SQR( curr_erb[i] ); } else { + MOVE( 1 ); + MAC( 1 ); + MULT( 1 ); tmp1 = (float) ( PowSpect[i] * SQR( out[i] - AmpCB2_NB[j][i - 11] ) ); } + LOGIC( 1 ); if ( AmpCB2_NB[j][i - 11] < out[i] ) { + MULT( 1 ); tmp1 *= 0.9f; } + ADD( 1 ); tmp += tmp1; } } @@ -1478,27 +1990,41 @@ void erb_diff( { if ( cslot[i] != 0 ) { + ADD( 1 ); + LOGIC( 1 ); if ( AmpCB2_WB[j][i - 11] < -t_prev_erb[i] ) { + MOVE( 1 ); + MULT( 1 ); + MULT( 1 ); tmp1 = PowSpect[i] * SQR( curr_erb[i] ); } else { + MOVE( 1 ); + MAC( 1 ); + MULT( 1 ); tmp1 = (float) ( PowSpect[i] * SQR( out[i] - AmpCB2_WB[j][i - 11] ) ); } + LOGIC( 1 ); if ( AmpCB2_WB[j][i - 11] < out[i] ) { + MULT( 1 ); tmp1 *= 0.9f; } + ADD( 1 ); tmp += tmp1; } } } + LOGIC( 1 ); if ( tmp < mmse ) { + MOVE( 1 ); mmse = tmp; + MOVE( 1 ); mmseindex = j; } } @@ -1508,7 +2034,9 @@ void erb_diff( mmseindex = 0; } + MOVE( 1 ); index[1] = mmseindex; +#undef WMC_TOOL_SKIP return; } @@ -1540,17 +2068,26 @@ void erb_add( { AmpCB1 = AmpCB1_WB; } + +#define WMC_TOOL_SKIP + FUNC( 3 ); erb_slot( l, cslot, t_prev_erb, num_erb ); + FUNC( 3 ); erb_slot( pl, pslot, t_prev_erb, num_erb ); + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { + MOVE( 1 ); t_prev_erb[i] = prev_erb[i]; } + LOGIC( 1 ); if ( pl > l ) { + MOVE( 1 ); tmp = t_prev_erb[0]; + LOOP( 1 ); for ( i = 0; i < num_erb; i++ ) { if ( !( pslot[i] >= 0 ) ) @@ -1558,68 +2095,93 @@ void erb_add( pslot[i] = 0; } + LOGIC( 1 ); if ( pslot[i] != 0 ) { + MOVE( 1 ); tmp = t_prev_erb[i]; } else { + MOVE( 1 ); t_prev_erb[i] = tmp; } } } else if ( l > pl ) { + MOVE( 1 ); tmp = t_prev_erb[num_erb - 1]; + ADD( 1 ); + LOOP( 1 ); for ( i = num_erb - 1; i >= 0; i-- ) { + LOGIC( 1 ); if ( pslot[i] != 0 ) { + MOVE( 1 ); tmp = t_prev_erb[i]; } else { + MOVE( 1 ); t_prev_erb[i] = tmp; } } } + LOOP( 1 ); for ( i = 1; i < 11; i++ ) { + LOGIC( 1 ); if ( cslot[i] != 0 ) { + MOVE( 1 ); + ADD( 1 ); curr_erb[i] = (float) ( AmpCB1[index[0]][i - 1] + t_prev_erb[i] ); + MOVE( 1 ); curr_erb[i] = max( 0.0f, curr_erb[i] ); } else { + MOVE( 1 ); curr_erb[i] = 0.0; } } + LOOP( 1 ); for ( i = 11; i < ( num_erb - 2 ); i++ ) { + LOGIC( 1 ); if ( cslot[i] != 0 ) { + MOVE( 1 ); if ( num_erb == NUM_ERB_NB ) { + ADD( 1 ); curr_erb[i] = (float) ( AmpCB2_NB[index[1]][i - 11] + t_prev_erb[i] ); + MOVE( 1 ); curr_erb[i] = max( 0.0f, curr_erb[i] ); } else if ( num_erb == NUM_ERB_WB ) { + ADD( 1 ); curr_erb[i] = (float) ( AmpCB2_WB[index[1]][i - 11] + t_prev_erb[i] ); + MOVE( 1 ); curr_erb[i] = max( 0.0f, curr_erb[i] ); } } else { + MOVE( 1 ); curr_erb[i] = 0.0f; } } +#undef WMC_TOOL_SKIP return; } + /*-------------------------------------------------------------------* * WIsyn() * @@ -1643,7 +2205,7 @@ ivas_error WIsyn( error = IVAS_ERR_OK; - if ( ( phase = (float *) count_malloc( N * sizeof( float ) ) ) == NULL ) + if ( ( phase = (float *) malloc( N * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for WI structure\n" ) ); } @@ -1653,52 +2215,81 @@ ivas_error WIsyn( return IVAS_ERROR( error, "Error creating new DTFS structure\n" ); } +#define WMC_TOOL_SKIP + FUNC( 2 ); DTFS_copy( CURRCW_DTFS, *CURRCW_DTFS_out ); /* Calculating the expected alignment shift */ + MOVE( 1 ); + MULT( 2 ); + INDIRECT( 1 ); + INDIRECT( 1 ); alignment = (float) ( *ph_offset / PI2 * PREVCW.lag ); + LOGIC( 1 ); if ( flag == 1 ) { + MULT( 1 ); alignment *= I; } /* Calculating the expected alignment shift */ + MOVE( 1 ); + DIV( 1 ); + ADD( 2 ); + DIV( 1 ); tmp = (float) fmod( ( N % ( ( PREVCW.lag + CURRCW_DTFS->lag ) >> 1 ) + alignment ), CURRCW_DTFS->lag ); /* Compute the alignment shift */ if ( FR_flag == 0 ) { + FUNC( 5 ); + MOVE( 1 ); alignment = DTFS_alignment_weight( PREVCW, *CURRCW_DTFS, tmp, curr_lpc, curr_lpc ); } else /* FR case */ { + FUNC( 5 ); + MOVE( 1 ); alignment = DTFS_alignment_full( PREVCW, *CURRCW_DTFS, CURRCW_DTFS->lag * 2 ); } + MOVE( 1 ); + MULT( 2 ); tmp = (float) ( PI2 * alignment / CURRCW_DTFS->lag ); + FUNC( 2 ); DTFS_phaseShift( CURRCW_DTFS, tmp ); - DTFS_phaseShift( CURRCW_DTFS_out, (float) ( PI2 * alignment / CURRCW_DTFS_out->lag ) ); + FUNC( 2 ); + MULT( 2 ); + DTFS_phaseShift( CURRCW_DTFS_out, (float) ( PI2 * alignment / CURRCW_DTFS->lag ) ); /* Compute the cubic phase track and transform to 1-D signal */ + FUNC( 6 ); cubicPhase( *ph_offset, tmp, (float) PREVCW.lag, (float) CURRCW_DTFS->lag, N, phase ); if ( FR_flag == 0 ) { + FUNC( 6 ); DTFS_transform( PREVCW, *CURRCW_DTFS, phase, out, N, 0 ); } else { + FUNC( 6 ); DTFS_transform( PREVCW, *CURRCW_DTFS, phase, out, N, 1 ); } /* Adjust the phase offset and wrap it between 0 and 2pi */ + LOGIC( 1 ); if ( flag == 2 ) { + MULT( 1 ); tmp *= I; } + MOVE( 1 ); + DIV( 1 ); *ph_offset = (float) fmod( (double) ( tmp ), PI2 ); +#undef WMC_TOOL_SKIP - count_free( phase ); - count_free( CURRCW_DTFS ); + free( phase ); + free( CURRCW_DTFS ); return error; } diff --git a/lib_com/window.c b/lib_com/window.c index a3bf82ac7e98cd60ad5095dc4ae733729b94ec90..093dbd4fc62342b2d96d2706ef31a04c1a36a201 100644 --- a/lib_com/window.c +++ b/lib_com/window.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,16 +33,17 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ #include +#include #include "options.h" #ifdef DEBUGGING #include "debug.h" #endif -#include #include "prot.h" +#define WMC_TOOL_SKIP + /*------------------------------------------------------------------- * ham_cos_window() * @@ -75,3 +76,5 @@ void ham_cos_window( return; } + +#undef WMC_TOOL_SKIP diff --git a/lib_com/window_ola.c b/lib_com/window_ola.c index 7a5b1536363e383e59e75686df7884a6eedc79c3..07798af16ed4fcdadbe7dfbfb90251c0c9235d04 100644 --- a/lib_com/window_ola.c +++ b/lib_com/window_ola.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * window_ola() diff --git a/lib_com/wtda.c b/lib_com/wtda.c index cd8d588ed5493d566d7d990f1ddabde182670c74..3bd839e5ac4f9b28121f77ad819a2f59cc7ef316 100644 --- a/lib_com/wtda.c +++ b/lib_com/wtda.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_com.h" #include -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif diff --git a/lib_debug/debug.c b/lib_debug/debug.c index 5ee8f10e31963161ba751ee449caae658d759e4b..85e48e8bae0b71aaa6c4dfc4484b6ddbd53dd285 100644 --- a/lib_debug/debug.c +++ b/lib_debug/debug.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,6 @@ #include #include #include "options.h" -#include "prot.h" #ifdef DEBUGGING #include "debug.h" #ifdef DEBUG_MODE_INFO @@ -46,6 +45,7 @@ #endif #endif #endif +#include "cnst.h" #include #include #include @@ -53,7 +53,7 @@ #include #else #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_debug/debug.h b/lib_debug/debug.h index 9b38b16b6622dc674444d79e307fcf2765a7bc52..3d59cb00a0555a73c094ba80aa34de7fd9013710 100644 --- a/lib_debug/debug.h +++ b/lib_debug/debug.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,12 +36,17 @@ #include "options.h" #include #include +#ifdef DEBUG_SBA +#include "sba_debug.h" +#endif /*------------------------------------------------------------------------------------------* * Global variables used for debugging *------------------------------------------------------------------------------------------*/ +#ifdef DEBUGGING extern int32_t frame; +#endif #ifdef DEBUGGING extern uint16_t g_nPrintedLines; diff --git a/lib_debug/mem_count.c b/lib_debug/mem_count.c deleted file mode 100644 index b12639ae3fcb3e100477cab505ba97e378bc1e7a..0000000000000000000000000000000000000000 --- a/lib_debug/mem_count.c +++ /dev/null @@ -1,906 +0,0 @@ -/* - * Memory Counting Tool - * - * Copyright 2022 VoiceAge Corporation. All Rights Reserved. - * - * This software is protected by copyright law and by international treaties. - * VoiceAge Corporation retains full ownership rights in their respective contributions in the software. - * No license of any kind, including but not limited to patent license, of any foregoing parties is - * hereby granted by implication, estoppel or otherwise. - * - * This software is provided "AS IS", without any express or implied warranties. The software is in the - * development stage. It is intended exclusively for experts who have experience with such software and - * solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - * and/or fitness for a particular purpose are hereby disclaimed and excluded. - * - * Written by : Guy J. Richard - August 2017 - * - */ - -#include -#include "options.h" -#include "mem_count.h" - -#include /* for printf, ... */ -#include /* for stricmp, ... */ -#include /* for alloc, NULL, ... */ -#include /* for tolower */ - -/* Mostly to get a 'int32_t' */ -#if !defined( _MSC_VER ) || _MSC_VER >= 1600 -#include -#else -#include -#endif - -#ifdef RAM_COUNTING_TOOL - -#if defined( _MSC_VER ) && _MSC_VER < 1600 -typedef UINT32 uint32_t; -typedef INT32 int32_t; -typedef UINT64 uint64_t; -typedef INT64 int64_t; -#endif - -#ifndef TRUE -#define TRUE ( 0 == 0 ) -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -/* How to use the tool notes - ========================= - - The tool measure SRAM memory allocated by malloc(), calloc() and - deallocated by free(). - - In order to run the tool, one needs to: - 1) Prepend 'count_' to all calls to 'malloc', 'calloc' and 'free' except debug files. - 2) Add the following code into e.g. prot.h, so that all files with calls to these functions see it. - #ifdef RAM_COUNTING_TOOL - #define count_malloc(n1) MALLOC_FCT_CALL(n1) - #define count_calloc(n1,n2) CALLOC_FCT_CALL(n1, n2) - #define count_free(ptr) FREE_FCT_CALL(ptr) - #else - #define count_malloc(n1) malloc(n1) - #define count_calloc(n1,n2) calloc(n1, n2) - #define count_free(ptr) free(ptr) - #endif - 3) Call mem_count_init() at the beginning of encoding/decoding - - The first param allows to set a limit on the RAM that can be allocated. - While the codec is running, if memory is requested such that the maximum - is passed (Mem Alloc > Limit), the codec will stop and the summary will - be printed. - - The second param allows to decide the units (bytes, shorts or longs). - Please note that the unit specified is combined with the limit param to - produce the total size that can be allocated. Ex ..init(1000, USE_16BITS); - will set the limit to 1000 x 16 Bits Word (2000 bytes in total). - 4) Call mem_count_summary() at the end of encoding/decoding to print-out the results. - - The first parameter allows to overwrite the initial units configuration. - The Total size allocated (always in bytes internally) will be converted - to the unit selected before being reported. - - The switch 'RAM_COUNTING_TOOL' also has to be defined to enable memory counting. - - There is a define 'MEM_COUNT_DETAILS' in options.h that enables printing per - sub-structure details when DEBUGGING is activated. -*/ - -/*-------------------------------------------------------------------* - * LOCAL CONSTANTS - *-------------------------------------------------------------------*/ - -/* This is the maximum number of allocations for which to keep information. - It can be increased if required. */ -#define MAX_INFO_RECORDS 3000 - -/* This is the length after which the function name - will be truncated when the summary is printed. */ -#define MAX_FUNCTION_NAME_LENGTH 18 - -/* This is the length after which the parameter to - the allocating function will be truncated when - the summary is printed. */ -#define MAX_PARAMS_LENGTH 36 - -/* This is the value (in bytes) towards which the block size - is rounded. For example, a block of 123 bytes, when using - a 32 bits system, will end up taking 124 bytes since - the last unused byte cannot be used for another block. */ -#ifdef MEM_ALIGN_64BITS -#define BLOCK_ROUNDING 8 -#else /* Align on 32 Bits Instead */ -#define BLOCK_ROUNDING 4 -#endif - -#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) - -/* Special Value to See if Memory was ever written */ -#define MAGIC_VALUE_OOB 0x12A534F0 /* Put Before & After Buffer */ -#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* To Detect if Memory was Written */ -/* OOB Flags */ -#define OOB_START 0x1 -#define OOB_END 0x2 - -/*-------------------------------------------------------------------* - * LOCAL MACROS - *-------------------------------------------------------------------*/ - -#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) -#define IS_CALLOC( str ) ( ( size_str[0] ) == 'c' ) - -#define WARNING( msg ) \ - do \ - { \ - printf( "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, msg ); \ - } while ( 0 ) -#define ERROR( msg ) \ - do \ - { \ - WARNING( msg ); \ - exit( -1 ); \ - } while ( 0 ) - -/*-------------------------------------------------------------------* - * LOCAL TYPES - *-------------------------------------------------------------------*/ - -typedef struct -{ - void *block_ptr; - size_t block_size; - int lineno; - char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ - char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */ - int used; - int OOB_Flag; - int seq_no; /* To Help Sorting by Order of Creation when all else is identical */ - int noccurances; -} allocator_record; - -typedef allocator_record allocation_list[MAX_INFO_RECORDS]; - -/*-------------------------------------------------------------------* - * LOCAL DATA - *-------------------------------------------------------------------*/ - -static allocation_list Current_Allocations, Peak_Allocations, Freed_Allocations; -static size_t RAM_Limit = NO_RAM_LIMIT; /* Always in Bytes */ -static size_t Current_RAM = 0, Peak_RAM = 0; /* In Bytes */ -static unsigned int Num_Records_Cur_RAM = 0, Num_Records_Peak_RAM = 0, Num_Records_Freed_RAM = 0; -static int Seq_No = 0; - -static size_t Stat_Cnt_Size = USE_BYTES; - -#ifndef DISABLE_NULL_PTR_FREE_WARNING -static allocation_list Missing_Allocations; -static unsigned int Num_Records_Missing_Alloc_Warnings = 0; -#endif - -/*-------------------------------------------------------------------* - * LOCAL CONST DATA - *-------------------------------------------------------------------*/ - -/* Suffix after numeral value printed in the summary */ -/* One char for each size */ -static const char Count_suffix[] = "BsL"; /* Using 's' because 'S' - looks a lot like '5'. */ -/* */ -static const char *Count_Name[] = { "Bytes", "Shorts", "Longs" }; - -/*-------------------------------------------------------------------* - * GLOBAL FUNCTIONS - *-------------------------------------------------------------------*/ - -/* It is not necessary to call dyn_mem_stats_init() since all static - variables are pre-initialised. It can be used to run stats again. */ -void mem_count_init( size_t limit, Counting_Size cnt_size ) -{ - if ( cnt_size != USE_DEFAULT ) - Stat_Cnt_Size = cnt_size; - Current_RAM = Peak_RAM = 0; - RAM_Limit = limit << Stat_Cnt_Size; - Num_Records_Cur_RAM = Num_Records_Peak_RAM = Num_Records_Freed_RAM = 0; -#ifndef DISABLE_NULL_PTR_FREE_WARNING - Num_Records_Missing_Alloc_Warnings = 0; -#endif - Seq_No = 0; -} - -/* This Function basically uses 'malloc' to allocate memory but also - records information about which functions allocated memory, the peak, ... - When, dyn_mem_print_stats() is called, all this info is printed as - well as the memory that has not been de-allocated; it is useful to - find memory leaks. */ -void *mem_alloc( - const char *func_name, - int func_lineno, - size_t size, - char *size_str /* the first char indicates m-alloc or c-alloc */ ) -{ - size_t rounded_size; - void *block_ptr; - char *tmp_ptr; - allocator_record *record_ptr; - size_t n, f; - int32_t fill_value; - int32_t *ptr32; - int32_t mask, temp; - unsigned int check; - - /* Do not Support Empty Requests */ - if ( size == 0 ) - { - ERROR( "Size of Zero not Supported" ); - } - - if ( Num_Records_Cur_RAM == MAX_INFO_RECORDS ) - { - ERROR( "Too Many Allocs. Increase 'MAX_INFO_RECORDS'" ); - } - - /* Round Up Block Size */ - rounded_size = ROUND_BLOCK_SIZE( size ); - - /* Allocate using the standard mem allocator. - Allocate a bit More to Have Room for Signature Values */ - block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 ); - - /* the split line is to prevent a 'search/replace' adding a '_' to the name */ - /* We request more memory to have room to put signatures at the start - and end of the allocated buffer to check for OOBounds accesses. */ - /* Stop if it Failed */ - if ( block_ptr == NULL ) - { - ERROR( "Out of System RAM" ); - } - - /* Cannot use #if sizeof(int32_t) to catch this at compile time - because the preprocessor doesn't know anything about types - or sizes. */ - check = sizeof( int32_t ); - if ( check != 4 ) - { - ERROR( "Expecting 'int32_t' to be a 32 Bits Integer" ); - } - - /* Set Signatures and Fill (or Clear) Memory */ - ptr32 = (int32_t *) block_ptr; - /* Signature at Start of Block */ - n = N_32BITS_BLOCKS; - do - { - *ptr32++ = MAGIC_VALUE_OOB; - } while ( --n ); - /* Fill with Pattern or Clear Memory */ - fill_value = MAGIC_VALUE_USED; - if ( IS_CALLOC( size_str ) ) - { - fill_value = 0x00000000; - } - n = size / sizeof( int32_t ); - while ( n-- ) - { - *ptr32++ = fill_value; - } - n = rounded_size - size; - /* When Initializing with '0' */ - /* Need to Adapt the Magic Value */ - f = n % sizeof( int32_t ); - if ( f != 0 ) - { - /* For f=, shift by [1->24, 2->16, 3->8] */ - mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */ - temp = MAGIC_VALUE_OOB & mask; - if ( fill_value != 0x0 ) - { /* Using M-Alloc */ - /* Merge Fill Value */ - temp += ( ~mask ) & MAGIC_VALUE_USED; - } /* for C-Alloc, the code in (1) hereabove already introduces zeros */ - *ptr32++ = temp; - } - n /= sizeof( int32_t ); - n += N_32BITS_BLOCKS; - /* Signature at End of Block */ - do - { - *ptr32++ = MAGIC_VALUE_OOB; - } while ( --n ); - - /* Adjust Pointer (Magic Value Before and After the Memory Region Requested) */ - tmp_ptr = (char *) block_ptr; - tmp_ptr += BLOCK_ROUNDING; - block_ptr = (void *) tmp_ptr; - - /* Save Information about Function Requesting the RAM */ - record_ptr = &Current_Allocations[Num_Records_Cur_RAM]; - - /* Save Name (and NUL Terminate it) */ - strncpy( record_ptr->name, func_name, MAX_FUNCTION_NAME_LENGTH ); - record_ptr->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; - /* Save Params (and NUL Terminate it) - There string starts with a Marker (either 'm' or 'c') - that indicates the type of allocation requested. */ - strncpy( record_ptr->params, size_str, MAX_PARAMS_LENGTH ); - record_ptr->params[MAX_PARAMS_LENGTH] = '\0'; - /* Save Other Info */ - record_ptr->lineno = func_lineno; - record_ptr->block_ptr = block_ptr; - record_ptr->block_size = size; - record_ptr->used = -1; /* By default do not check mem usage */ - record_ptr->seq_no = ++Seq_No; - record_ptr->noccurances = 1; - - /* Increase # of Records */ - Num_Records_Cur_RAM++; - /* Update Amount of RAM Allocated */ - Current_RAM += rounded_size; - - /* Is this the Worst Case */ - if ( Peak_RAM < Current_RAM ) - { /* Yes */ - /* Update the Peak RAM */ - Peak_RAM = Current_RAM; - /* Keep the Information */ - memmove( Peak_Allocations, Current_Allocations, sizeof( allocator_record ) * Num_Records_Cur_RAM ); - Num_Records_Peak_RAM = Num_Records_Cur_RAM; - } - - /* Limit Busted? */ - if ( RAM_Limit != NO_RAM_LIMIT ) - { - if ( Current_RAM > RAM_Limit ) - { - char info_msg[100]; - - mem_count_summary( USE_DEFAULT ); - - sprintf( info_msg, "Alloc Limit of %lu %s was Passed", (unsigned long) RAM_Limit >> Stat_Cnt_Size, Count_Name[Stat_Cnt_Size] ); - ERROR( info_msg ); - } - } - - return block_ptr; -} - -/* Calculate Memory Usage of Block (Look for Signature) */ -static void mem_set_usage( allocator_record *record_ptr ) -{ - int total_bytes_used; - - size_t n; - int32_t *ptr32; - char *ptr8; - size_t total_bytes; - int32_t fill_value; - - fill_value = MAGIC_VALUE_USED; - if ( ( record_ptr->params[0] ) == 'c' ) - { - fill_value = 0x00000000; - } - - total_bytes = record_ptr->block_size; - - /* Check 4 bytes at a time */ - ptr32 = (int32_t *) record_ptr->block_ptr; - total_bytes_used = 0; - for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- ) - { - if ( *ptr32++ != fill_value ) - total_bytes_used += sizeof( int32_t ); - } - - /* Check Remaining Bytes (If Applicable) */ - ptr8 = (char *) ptr32; - for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- ) - { - if ( *ptr8++ != (char) fill_value ) - total_bytes_used++; - /* Update Value */ - fill_value >>= 8; - } - - /* Save Space Used */ - record_ptr->used = total_bytes_used; -} - -static void mem_check_OOB( allocator_record *record_ptr ) -{ - int32_t *ptr32; - unsigned int OOB_Flag = 0x0; - int32_t mask; - size_t i; - int f; - - ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS; - /* Check at Beginning of Block */ - i = N_32BITS_BLOCKS; - do - { - if ( *ptr32++ ^ MAGIC_VALUE_OOB ) - OOB_Flag |= OOB_START; - } while ( --i ); - - /* Advance to End (Snap to lowest 32 Bits) */ - ptr32 += record_ptr->block_size / sizeof( int32_t ); - - /* Calculate Unused Space That has been - added to get to the rounded Block Size */ - i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size; - - /* Partial Check (For Block Size that have been rounded) */ - f = i % sizeof( int32_t ); - if ( f != 0 ) - { - mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); - if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask ) - OOB_Flag |= OOB_END; - } - - /* Full Check (all 32 Bits) for Remaining */ - i /= sizeof( int32_t ); - i += N_32BITS_BLOCKS; - do - { - if ( *ptr32++ ^ MAGIC_VALUE_OOB ) - OOB_Flag |= OOB_END; - } while ( --i ); - - record_ptr->OOB_Flag = OOB_Flag; -} - -/* Just to make the code cleaner */ -static int is_same_record( const allocator_record *record_ptr1, allocator_record *record_ptr2 ) -{ - return record_ptr2->block_size == record_ptr1->block_size && - record_ptr2->lineno == record_ptr1->lineno && - strcmp( record_ptr2->name, record_ptr1->name ) == 0 && - strcmp( record_ptr2->params, record_ptr1->params ) == 0 && - record_ptr2->OOB_Flag == record_ptr1->OOB_Flag - ? 1 - : 0; -} - -/* This Function basically uses 'free' and removes the - Information about the memory block from the list of - currently allocated Memory */ -void mem_free( const char *func_name, int func_lineno, void *ptr ) -{ - unsigned int i, j, k; - char *tmp_ptr; - allocator_record *record_ptr, *record_ptr2; - - char info_msg[100]; - - /* Search for the Block Pointer in the List */ - record_ptr = &Current_Allocations[0]; - for ( i = 0; i < Num_Records_Cur_RAM; i++ ) - { - /* Same Pointer? */ - if ( ptr == record_ptr->block_ptr ) - { /* Yes, Found it */ - if ( Num_Records_Freed_RAM == MAX_INFO_RECORDS ) - { - ERROR( "Too Many Allocs. Increase 'MAX_INFO_RECORDS'" ); - } - - for ( j = 0; j < Num_Records_Peak_RAM; j++ ) - { - /* Is this Block Part of the Peak RAM? */ - if ( memcmp( record_ptr, &Peak_Allocations[j], sizeof( *record_ptr ) ) == 0 ) - { - break; /* Stop the 'j' loop */ - } - } - - mem_set_usage( record_ptr ); - mem_check_OOB( record_ptr ); - - /* De-Allocated Block was Part of Peak RAM? */ - if ( j == Num_Records_Peak_RAM ) - { /* No */ - /* Here, in order to avoid filling this list with repetitive blocks */ - /* that are allocated and deallocated repeatedly, we look for a block */ - /* that has the same module, line #, size & same OOB characteristics. */ - /* We then just increase the # of occurances of this block definition. */ - /* The % used will be merged */ - record_ptr2 = &Freed_Allocations[0]; - for ( k = 0; k < Num_Records_Freed_RAM; k++ ) - { - /* Same Block but allocated many times */ - if ( is_same_record( record_ptr2, record_ptr ) ) - { - record_ptr2->noccurances++; - record_ptr2->used += record_ptr->used; - break; - } - record_ptr2++; - } - /* Found it */ - } - else - { - /* Force Add to List */ - k = Num_Records_Freed_RAM; - } - - if ( k == Num_Records_Freed_RAM ) - { /* No */ - /* Add to List */ - memmove( &Freed_Allocations[Num_Records_Freed_RAM], record_ptr, sizeof( allocator_record ) ); - /* Increase # of Records for Deallocated Block List */ - Num_Records_Freed_RAM++; - } - - /* De-Allocated Block was Part of Peak RAM? */ - if ( j != Num_Records_Peak_RAM ) - { /* Yes */ - /* Update Block Info There too (The Info here is Bytes Used and OOB Flags) */ - memmove( &Peak_Allocations[j], record_ptr, sizeof( *record_ptr ) ); - } - - /* First Adjust Pointer to Get to the Start of the Block */ - tmp_ptr = (char *) ptr; - tmp_ptr -= BLOCK_ROUNDING; - ptr = (void *) tmp_ptr; - /* De-allocate using the standard memory facilities */ - fr\ -ee( ptr ); /* the split line is to prevent a 'search/replace' adding a '_' to the name */ - - /* Decrease # of Records */ - Num_Records_Cur_RAM--; - /* Update (decrease) Amount of RAM Allocated */ - Current_RAM -= ROUND_BLOCK_SIZE( record_ptr->block_size ); - - /* Erase the entry (Move the Last One over it) */ - memmove( record_ptr, &Current_Allocations[Num_Records_Cur_RAM], sizeof( allocator_record ) ); - - return; - } - record_ptr++; - } - - /* Not Found, Problem! */ - if ( ptr != NULL ) - { - /* Stop */ - sprintf( info_msg, "Invalid Pointer: '%p'", ptr ); - ERROR( info_msg ); - } -#ifndef DISABLE_NULL_PTR_FREE_WARNING - else - { /* Warn about Freeing of NULL Pointers */ - /* Search to Warn Only Once. */ - record_ptr = &Missing_Allocations[0]; - for ( i = 0; i < Num_Records_Missing_Alloc_Warnings; i++ ) - { - /* Same Name? */ - if ( strncmp( record_ptr->name, func_name, MAX_FUNCTION_NAME_LENGTH ) == 0 ) - { /* Yes */ - /* Same Line Number? */ - if ( record_ptr->lineno == func_lineno ) - { /* Yes */ - /* No Need to Warn Again */ - return; - } - } - record_ptr++; - } - /* Save Name */ - strncpy( record_ptr->name, func_name, MAX_FUNCTION_NAME_LENGTH ); - record_ptr->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; - - /* Save Line No */ - record_ptr->lineno = func_lineno; - /* Save Pointer */ - record_ptr->block_ptr = ptr; - /* Save Size */ - record_ptr->block_size = 0; /* It is an Unknown Block, so there is no size, we put a '0' */ - - Num_Records_Missing_Alloc_Warnings++; - - WARNING( "Trying to Free 'NULL' Pointer" ); - } -#endif -} - -#ifdef MEM_COUNT_DETAILS -/* Used to Sort Block Information Records */ -static int compare_mem_records( const void *ptr1, const void *ptr2 ) -{ - const allocator_record *record_ptr1 = (const allocator_record *) ptr1, - *record_ptr2 = (const allocator_record *) ptr2; - int result; - - /* Sort First by 'Name', then by 'Line No' and finaly by 'Block Size' */ - - /* Compare Function Name */ - result = strcmp( record_ptr1->name, record_ptr2->name ); - /* Same Function Name? */ - if ( result == 0 ) - { /* Yes */ - /* Compare Line Number */ - result = record_ptr1->lineno - record_ptr2->lineno; - /* Same Line Number */ - if ( result == 0 ) - { /* Yes */ - /* Compare Block Size */ - result = record_ptr1->block_size - record_ptr2->block_size; - /* Same Size? */ - if ( result == 0 ) - { - result = record_ptr1->seq_no - record_ptr2->seq_no; - } - } - } - - return result; -} - -static void mem_print_records( allocator_record *record_ptr, int num_records, Counting_Size cnt_size, int print_size ) -{ - int i, sum, total; - char *last_name = NULL; - int single_flag; - char chr = Count_suffix[cnt_size]; - size_t nwords, rounded_block_size; - char nblocks_str[22]; - char quantity_str[22]; - char format_str[50]; - char *tmp_ptr; - int nblocks; - - char *OOB_str[] = { "- ", "beg", "end", "b+e" }; - - strcpy( format_str, "\n %-*s %5i %-*s %3s %3.0f%% %8s" ); - if ( print_size != FALSE ) - strcat( format_str, " %6u" ); - - /* Sort it */ - qsort( record_ptr, num_records, sizeof( allocator_record ), compare_mem_records ); - - single_flag = 0; - - nblocks = 0; - - if ( num_records > 0 ) - { - /* Print Header */ - printf( " %-*s Ln No %-*s OOB Used Quantity%s", MAX_FUNCTION_NAME_LENGTH, "Function Name", MAX_PARAMS_LENGTH, "Parameters ('m' or 'c' alloc)", print_size != FALSE ? " Size" : "" ); - - total = sum = 0; - for ( i = num_records - 1; i >= 0; i-- ) - { - if ( sum == 0 ) - { - last_name = record_ptr->name; - } - - rounded_block_size = ROUND_BLOCK_SIZE( record_ptr->block_size ) >> cnt_size; - nwords = rounded_block_size * record_ptr->noccurances; - - /* Calc Usage (It has already been done for a De-Allocated Block - That was part of the Peak Mem. But not for a Block that is - still allocated (never freed). */ - if ( record_ptr->used < 0 ) - { - mem_set_usage( record_ptr ); - /* Check Out of Bounds Too */ - mem_check_OOB( record_ptr ); - } - - sprintf( quantity_str, "%i", record_ptr->noccurances ); - - /* Print Quantity x Size */ - tmp_ptr = strchr( quantity_str, '\0' ); - *tmp_ptr++ = 'x'; - sprintf( tmp_ptr, "%i", (int) rounded_block_size ); - - printf( format_str, MAX_FUNCTION_NAME_LENGTH, record_ptr->name, record_ptr->lineno, MAX_PARAMS_LENGTH, record_ptr->params, OOB_str[record_ptr->OOB_Flag], ( record_ptr->used * 100.0f / record_ptr->block_size / record_ptr->noccurances ), quantity_str, (uint32_t) nwords ); - /* Count $ of Blocks */ - nblocks += record_ptr->noccurances; - /* Add Size */ - sum += nwords; - /* Advance */ - record_ptr++; - - if ( print_size != FALSE ) - { - /* End Reached or New Function? */ - if ( i == 0 || strcmp( last_name, record_ptr->name ) != 0 ) - { - /* Cumulate Total */ - total += sum; - - if ( i == 0 && total == sum ) - single_flag = 1; -#ifdef MEM_COUNT_TOTAL_PER_FUNC - /* Print 'Total' on the Line if there is only one Function - that allocated all the RAM */ - printf( " %7i%c", sum, chr ); -#endif - /* Reset Sum */ - sum = 0; - } - } - } - /* Print the Total */ - if ( !single_flag && print_size != FALSE ) - { -#ifdef MEM_COUNT_TOTAL_PER_FUNC -#define SPACES 9 -#else -#define SPACES 0 -#endif - - sprintf( nblocks_str, "%i Blocks", nblocks ); - - printf( "\n %*s %*s %*s --------\n", MAX_FUNCTION_NAME_LENGTH, "", MAX_PARAMS_LENGTH, "", SPACES, "" ); - printf( " %-*s %-*s %*s%7i%c\n", MAX_FUNCTION_NAME_LENGTH, "Total", MAX_PARAMS_LENGTH, nblocks_str, SPACES, "", total, chr ); - } - else - printf( "\n" ); - } - else - { - printf( " \n" ); - } -} -#endif - -/* Print Memory Summary. - Return Peak Memory Used (according to Units Specified) */ -size_t mem_count_summary( Counting_Size cnt_size ) -{ - size_t size; -#ifdef MEM_COUNT_DETAILS - unsigned int i, j; - size_t num; - allocation_list Allocations; -#endif - if ( cnt_size == USE_DEFAULT ) - cnt_size = Stat_Cnt_Size; - - size = Peak_RAM >> cnt_size; -#ifdef MEM_COUNT_DETAILS - printf( "\n\n====== STATIC RAM COUNTING TOOL: MEMORY SUMMARY ======\n\n" ); - - printf( " NOTES\n" - " 1) %c = %s, %c = %s (16 Bits Words) & %c = %s (32 Bits Words).\n" - " 2) The '%%' of 'Used' memory is not very reliable for c-alloc.\n" - " 3) The Out Of Bounds (OOB) Checking is primitive as it checks\n" - " only for writing before and past the buffer when it is freed\n" - " or when the summary is printed.\n" - " 4) Quantity Filed format is N x Block Size.\n" - " When it is 1: Size = Block Size\n" - " Otherwise, Size = The Total Size Allocated for the 'N' Blocks.\n" - "\n", - Count_suffix[USE_BYTES], Count_Name[USE_BYTES], Count_suffix[USE_16BITS], Count_Name[USE_16BITS], Count_suffix[USE_32BITS], Count_Name[USE_32BITS] ); - - /* Create a Temporary List of Block to Print */ - /* from all the Block Allocated in the Peak */ - /* Scenario. We want to Merge Entries allocated */ - /* from the exact same code location and having */ - /* the same block size. In order to simplifiy the */ - /* printout. */ - num = 0; - for ( i = 0; i < Num_Records_Peak_RAM; i++ ) - { - /* Check if an Identical Block Before Adding to List */ - for ( j = 0; j < num; j++ ) - { - if ( is_same_record( &Peak_Allocations[i], &Allocations[j] ) ) - { - Allocations[j].noccurances++; - Allocations[j].used += Peak_Allocations[i].used; - break; - } - } - - /* Unique Block? */ - if ( j == num ) - { /* Yes */ - /* Add to List */ - memmove( &Allocations[num++], &Peak_Allocations[i], sizeof( allocator_record ) ); - } - } - /* Print the Peak Allocated */ - printf( " Peak Memory Allocated\n" ); - mem_print_records( &Allocations[0], num, cnt_size, TRUE ); - printf( "\n" ); - - /* Create a Temporary List of Block to Print */ - /* from all the Block Allocated BUT excluding */ - /* blocks that are part of the peak (and that */ - /* are already printed). */ - /* This is done every time the summary is printed */ - /* so that the code can continue to be executed */ - /* and the summary can be printed again with blocks */ - /* that are part of the peak having changed and thus */ - /* those that end up in this 'catch all' category. */ - num = 0; - for ( i = 0; i < Num_Records_Freed_RAM; i++ ) - { - /* Check if Record is in the Peak */ - for ( j = 0; j < Num_Records_Peak_RAM; j++ ) - { - /* Is this Block Part of the Peak RAM OR Still Allocated ? */ - if ( is_same_record( &Freed_Allocations[i], &Peak_Allocations[j] ) ) - { /* Yes */ - break; /* Stop the 'j' loop */ - } - } - /* If part of the Peak, skip it */ - if ( j == Num_Records_Peak_RAM ) - { /* Not Part of Peak */ - /* Check if an Identical Block Before Adding to List */ - for ( j = 0; j < num; j++ ) - { -#ifndef MEM_COUNT_SEPARATE_OTHER_BLOCKS - /* Just Check for Same Size, Params and OOB Result */ - if ( Freed_Allocations[i].block_size == Allocations[j].block_size && - strcmp( Freed_Allocations[i].params, Allocations[j].params ) == 0 && - Freed_Allocations[i].OOB_Flag == Allocations[j].OOB_Flag ) - { - Allocations[j].noccurances += Freed_Allocations[i].noccurances; - Allocations[j].used += Freed_Allocations[i].used; - /* Indicate that Locations are Multiple */ - strncpy( Allocations[j].name, "MULTIPLE LOCATIONS", MAX_FUNCTION_NAME_LENGTH ); - /* Wipe the Line # */ - Allocations[j].lineno = 0; - break; - } -#else - if ( is_same_record( &Freed_Allocations[i], &Allocations[j] ) ) - { - Allocations[j].noccurances++; - Allocations[j].used += Freed_Allocations[i].used; - break; - } -#endif - } - - /* Unique Block? */ - if ( j == num ) - { /* Yes */ - /* Add to List */ - memmove( &Allocations[num++], &Freed_Allocations[i], sizeof( allocator_record ) ); - } - } - } - - if ( num != 0 ) - { - /* Print all Other Block (Those that have been Freed but are not Part - of the Peak Memory). */ - printf( " Other Memory Allocated\n" ); - mem_print_records( &Allocations[0], num, cnt_size, FALSE /*Do not print the size column*/ ); - printf( "\n" ); - } - - /* If we have busted the RAM Limit, we will end up in the - summary function (here) and abort. Hence, no point printing - the memory still allocated, it will be the same as the Peak! */ - if ( RAM_Limit == 0 || Current_RAM <= RAM_Limit ) - { - /* Print the Not Deallocated */ - printf( " Memory Still Allocated\n" ); - mem_print_records( &Current_Allocations[0], Num_Records_Cur_RAM, cnt_size, TRUE ); - printf( "\n" ); - } -#endif - -#ifndef MEM_COUNT_DETAILS - if ( Num_Records_Cur_RAM > 0 ) - { - printf( "\nWarning: Part of the SRAM is still allocated! Activate MEM_COUNT_DETAILS for more details.\n" ); - } -#endif - printf( "Peak SRAM Allocated: %i%c\n\n\n", (int) size, Count_suffix[cnt_size] ); - - return size; -} - -#endif diff --git a/lib_debug/mem_count.h b/lib_debug/mem_count.h deleted file mode 100644 index d30fc3ab1ada926bbbeb4aaa4ed2eedc8ca4359b..0000000000000000000000000000000000000000 --- a/lib_debug/mem_count.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * mem_count.h - * - * Copyright 2022 VoiceAge Corporation. All Rights Reserved. - * - * This software is protected by copyright law and by international treaties. - * VoiceAge Corporation retains full ownership rights in their respective contributions in the software. - * No license of any kind, including but not limited to patent license, of any foregoing parties is - * hereby granted by implication, estoppel or otherwise. - * - * This software is provided "AS IS", without any express or implied warranties. The software is in the - * development stage. It is intended exclusively for experts who have experience with such software and - * solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - * and/or fitness for a particular purpose are hereby disclaimed and excluded. - * - * Written by : Guy J. Richard - August 2017 - * - */ - -#ifndef __MEM_COUNT_H__ -#define __MEM_COUNT_H__ - -#include -#include "options.h" -#include /* for size_t, ... */ - -#ifdef RAM_COUNTING_TOOL -/*-------------------------------------------------------------------* - * Global Constants - *-------------------------------------------------------------------*/ - -#define NO_RAM_LIMIT 0 - -/* Define this when using 64 Bits values in the code (ex: double) */ -/*#define MEM_ALIGN_64BITS */ /* Will Align on 32 Bits if not Defined */ - -/*#define DISABLE_NULL_PTR_FREE_WARNING*/ - -/*#define MEM_COUNT_DETAILS*/ - -/*#define MEM_COUNT_SEPARATE_OTHER_BLOCKS */ /* Print separate lines with location details if the same block is allocated in multiple places and is not a part of the Peak memory */ - /* if not defined, MULTIPLE LOCATIONS is printed instead */ - -/*-------------------------------------------------------------------* - * Global Types - *-------------------------------------------------------------------*/ - -typedef enum -{ - USE_DEFAULT = -1, - USE_BYTES, - USE_16BITS, - USE_32BITS -} Counting_Size; - -/*-------------------------------------------------------------------* - * Global Macros - *-------------------------------------------------------------------*/ - -#define STRINGIFY( x ) #x -#define TO_STRING( x ) STRINGIFY( x ) - -#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) ) -#define __func__ __FUNCTION__ -#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ < 199901L -#if ( __GNUC__ >= 2 ) -#define __func__ __FUNCTION__ -#else -#define __func__ "" -#endif -#elif defined( __GNUC__ ) -#define __func__ __extension__ __FUNCTION__ -#endif - -/* MALLOC_FCT_CALL, FREE_FCT_CALL, ... are defined here because 'wmc_auto.h' uses */ -/* them to map malloc, free & calloc to a Memory Counting Mechanism. If the WMC Tool */ -/* is not used, then these definitions will have no effect and are harmless. */ -#define MALLOC_FCT_CALL( size ) mem_alloc( __func__, __LINE__, size, "m:" TO_STRING( size ) ) -#define FREE_FCT_CALL( ptr ) mem_free( __func__, __LINE__, ptr ) -#define CALLOC_FCT_CALL( n, sz ) mem_alloc( __func__, __LINE__, ( n ) * ( sz ), "c:" TO_STRING( n ) ", " TO_STRING( sz ) ) - - -/*-------------------------------------------------------------------* - * Prototypes - *-------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" -{ -#endif - - extern void mem_count_init( size_t limit, Counting_Size cnt_size ); - extern size_t mem_count_summary( Counting_Size cnt_size ); - - extern void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str ); - extern void mem_free( const char *func_name, int func_lineno, void *ptr ); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif diff --git a/lib_debug/memory.c b/lib_debug/memory.c deleted file mode 100644 index afd292ddbcc62e607829daa65541bf3cb7baf6c2..0000000000000000000000000000000000000000 --- a/lib_debug/memory.c +++ /dev/null @@ -1,187 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include "options.h" -#include -#include -#include -#include - -#include "prot.h" -#include "debug.h" -#include "wmops.h" -#include "rom_enc.h" -#include "rom_dec.h" -#include "rom_com.h" -#include "stat_enc.h" -#include "stat_dec.h" - -#ifdef WMOPS - -/*-------------------------------------------------------------------* - * Memory counting tool - *--------------------------------------------------------------------*/ - -int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ -int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */ -int32_t wc_frame = 0; /* Frame corresponding to the worst-case stack usage */ -char location_max_stack[256] = "undefined"; -#define MAX_FCT_NAME_LENGTH 30 -typedef struct -{ - char function_name[MAX_FCT_NAME_LENGTH + 1]; - int16_t *stack_ptr; -} caller_info; -int current_calls = 0; -#define MAX_RECORDABLE_CALLS 40 -caller_info stack_callers[2][MAX_RECORDABLE_CALLS]; - - -/*-------------------------------------------------------------------* - * reset_stack() - * - * Initialize/reset the base stack counter.. - *--------------------------------------------------------------------*/ - -void reset_stack() -{ - int16_t something; - - ptr_base_stack = &something; - ptr_max_stack = ptr_base_stack; -} - -/*-------------------------------------------------------------------* - * push_stack() - * - * Check the current stack pointer and update the maximum stack pointer, if new maximum found. - *--------------------------------------------------------------------*/ - -int push_stack( const char *filename, const char *fctname ) -{ - int16_t something; - - (void) *filename; /* to avoid compilation warning */ - - /* Is there room to save the caller's information? */ - if ( current_calls >= MAX_RECORDABLE_CALLS ) - { /* No */ - fprintf( stderr, "memory.c: No more room to store call stack info. Please increase MAX_RECORDABLE_CALLS" ); - exit( -1 ); - } - /* Valid Function Name? */ - if ( fctname[0] == 0 ) - { /* No */ - fprintf( stderr, "memory.c: Invalid function name for call stack info." ); - exit( -1 ); - } - /* Save the Name of the Calling Function in the Table */ - strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FCT_NAME_LENGTH ); - stack_callers[0][current_calls].function_name[MAX_FCT_NAME_LENGTH] = 0; /* Nul Terminate */ - /* Save the Stack Pointer */ - stack_callers[0][current_calls].stack_ptr = &something; - /* Increase Stack Calling Tree Level */ - current_calls++; - /* Is this the First Time or the Worst Case? */ - if ( &something < ptr_max_stack || ptr_max_stack == NULL ) - { /* Yes */ - /* Save Info about it */ - ptr_max_stack = &something; - wc_frame = frame; - strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); - location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; - - /* Save Call Tree */ - memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls ); - - /* Terminate the List (Unless Full) */ - if ( current_calls < MAX_RECORDABLE_CALLS ) - { - stack_callers[1][current_calls].function_name[0] = 0; - } - } - return 0 /* for Now */; -} - -int pop_stack( const char *filename, const char *fctname ) -{ - caller_info *caller_info_ptr; - - (void) *filename; /* to avoid compilation warning */ - - /* Decrease Stack Calling */ - current_calls--; - - /* Get Pointer to Caller Information */ - caller_info_ptr = &stack_callers[0][current_calls]; - - /* Check if Names Match */ - if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FCT_NAME_LENGTH ) != 0 ) - { - fprintf( stderr, "memory.c: Invalid pop_stack()" ); - exit( -1 ); - } - - /* Erase Entry */ - caller_info_ptr->function_name[0] = 0; - - return 0 /* for Now */; -} - -void print_stack_call_tree( void ) -{ - caller_info *caller_info_ptr; - int call_level; - - fprintf( stdout, "Stack Call Tree (frame #%5d) Stack Usage in words\n", wc_frame ); - caller_info_ptr = &stack_callers[1][0]; - for ( call_level = 0; call_level < MAX_RECORDABLE_CALLS; call_level++ ) - { - /* Done? */ - if ( caller_info_ptr->function_name[0] == 0 ) - break; - /* Print Name */ - fprintf( stdout, "%-42s", caller_info_ptr->function_name ); - /* Print Stack Usage (Based on Difference) */ - if ( call_level != 0 ) - { - fprintf( stdout, "%ld\n", ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) / sizeof( float ) ); - } - else - fprintf( stdout, "\n" ); - /* Advance */ - caller_info_ptr++; - } - fprintf( stdout, "\n" ); -} - -#endif /* WMOPS */ diff --git a/lib_debug/sba_debug.c b/lib_debug/sba_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..040cadf88774b68fad67286377ef5ad721c15ee5 --- /dev/null +++ b/lib_debug/sba_debug.c @@ -0,0 +1,421 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include +#include +#include +#include "options.h" +#include "ivas_cnst.h" +#include "sba_debug.h" +#include +#include "wmc_auto.h" +#ifdef DEBUG_SBA +#include +#include "tinywaveout_c.h" + +/*-------------------------------------------------------------------* + * Global variables used for debugging but not under DEBUGGING flag + *--------------------------------------------------------------------*/ + +#define MAX_IN_FILE_LEN ( 1000 ) +#define MAX_PLUG_IN_FILE_LEN ( MAX_IN_FILE_LEN ) +#define MAX_DEBUG_TAG_LEN ( 50 ) +#define NUM_DEBUG_FILES ( 4 ) +#define MAX_TAG_LEN ( 200 ) + +WAVEFILEOUT *spar_foa_enc_wav[3]; +WAVEFILEOUT *spar_foa_dec_wav[4]; +float max_diff = 0; +int32_t dbg_frm_num; +int32_t dbg_band; +int32_t dbg_type; +int32_t iter_max = 0; +FILE *fFb_pcm = NULL; +int8_t file_names[NUM_DEBUG_FILES][MAX_TAG_LEN + MAX_DEBUG_TAG_LEN]; + + +#ifdef DEBUG_AGC +FILE *agcOut = NULL; /* temporary AGC bitstream */ +#endif + +/*-----------------------------------------------------------------------------------------* + * Function description + * cstrcpy() - Custom implementation of strcpy + * + * Inputs: + * const char* _Source -> Source buffer + * _SizeInBytes -> Destination buffer size in bytes + * + * Outputs: + * char* _Destination -> Destination buffer + *-----------------------------------------------------------------------------------------*/ + +static void cstrcpy( char *_Destination, size_t _SizeInBytes, const char *_Source ) +{ + size_t SourceSizeInBytes = strlen( _Source ); + if ( _SizeInBytes > SourceSizeInBytes ) + { + strcpy( _Destination, _Source ); + } + else + { + assert( 0 ); + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function description + * cstrcat() - Custom implementation of strcat + * + * Inputs: + * const char* _Source -> Source buffer + * _SizeInBytes -> Destination buffer size in bytes + * + * Outputs: + * char* _Destination -> Destination buffer + *-----------------------------------------------------------------------------------------*/ + +static void cstrcat( char *_Destination, size_t _SizeInBytes, const char *_Source ) +{ + size_t SourceSizeInBytes = strlen( _Source ); + size_t DestSizeInBytes = _SizeInBytes - strlen( _Destination ); + if ( DestSizeInBytes > SourceSizeInBytes ) + { + strcat( _Destination, _Source ); + } + else + { + assert( 0 ); + } + + return; +} + + +#ifdef DEBUG_AGC +void ivas_close_agc_debug_files( void ) +{ + if ( agcOut != NULL ) + { + fclose( agcOut ); + agcOut = NULL; + } + + return; +} + +void ivas_open_agc_debug_files( int16_t agc ) +{ + /* Temporary AGC file */ + if ( agc > 0 ) + { + char agcFilename[50] = "agcBitstream.bin"; + if ( ( agcOut = fopen( agcFilename, "wb" ) ) == NULL ) + { + fprintf( stderr, "Error: Gain Control bitstream file %s could not be opened\n\n", agcFilename ); + exit( -1 ); + } + fprintf( stdout, "Temporary gain control bitstream file %s is opened\n", agcFilename ); + } + + return; +} +#endif + +static void UpdateWave( + const uint32_t sampleRate, + const uint32_t numChannels, + const uint32_t bps, + WAVEFILEOUT *spar_wav ) +{ + uint32_t blockAlignment = 0; + uint16_t writeValue16; + uint32_t writeValue32; + + writeValue16 = LittleEndian16( (int16_t) numChannels ); + /*Fseek to number of channel writing position*/ + fseek( spar_wav->theFile, 22, SEEK_SET ); + fwrite( &writeValue16, sizeof( writeValue16 ), 1, spar_wav->theFile ); + blockAlignment = numChannels * ( bps >> 3 ); + writeValue16 = LittleEndian16( (int16_t) blockAlignment ); + fseek( spar_wav->theFile, 4, SEEK_CUR ); + writeValue32 = LittleEndian32( sampleRate * blockAlignment ); + fwrite( &writeValue32, sizeof( writeValue32 ), 1, spar_wav->theFile ); + fwrite( &writeValue16, sizeof( writeValue16 ), 1, spar_wav->theFile ); + + return; +} + + +void ivas_spar_dump_signal_wav( + const int16_t input_frame, + float **ppPcm, + float pcm_array[IVAS_SPAR_MAX_CH][L_FRAME48k], + const int16_t no_channel, + WAVEFILEOUT *wave_file, + char *location ) +{ + float tmp_value; + int16_t pcm_value, i, j, k; + int16_t debug_tmp[IVAS_SPAR_MAX_CH * L_FRAME48k * 2]; + + k = 0; + int16_t Clipping = 0; + float largest_value = 0; + float db_value = 0; + + for ( j = 0; j < input_frame; j++ ) + { + for ( i = 0; i < no_channel; i++, k++ ) + { + if ( ppPcm ) + { + tmp_value = roundf( ppPcm[i][j] * PCM16_TO_FLT_FAC ); + } + else + { + tmp_value = roundf( pcm_array[i][j] * PCM16_TO_FLT_FAC ); + } + if ( tmp_value > MAX16B_FLT ) + { + largest_value = (float) fabs( tmp_value ) > largest_value ? (float) fabs( tmp_value ) : largest_value; + tmp_value = MAX16B; + Clipping++; + } + else if ( tmp_value < MIN16B_FLT ) + { + largest_value = (float) fabs( tmp_value ) > largest_value ? (float) fabs( tmp_value ) : largest_value; + tmp_value = MIN16B; + Clipping++; + } + pcm_value = (int16_t) tmp_value; + /*pcm_value = (tmp_value > MAX16B_FLT) ? MAX16B : (tmp_value < MIN16B_FLT) ? MIN16B + : (short)tmp_value;*/ + debug_tmp[k] = pcm_value; + } + } + if ( Clipping ) + { + db_value = 20.f * (float) log( largest_value ); + fprintf( stderr, "%d\t Clipping detected ", Clipping ); + } + + WriteWavShort( wave_file, debug_tmp, ( no_channel * input_frame ) ); + + if ( db_value ) + { + fprintf( stderr, "\t In %s largest clipped sample in dB %f \n", location, db_value ); + } + + return; +} + + +void ivas_close_sba_decoder_debug_files( + const int32_t fs, + const int16_t n_ch, + const int16_t n_transport, + const int16_t pca_ingest_channels ) +{ + if ( spar_foa_dec_wav[0] != NULL ) + { + UpdateWave( fs, n_transport, 32, spar_foa_dec_wav[0] ); + CloseWav( spar_foa_dec_wav[0] ); + } + if ( spar_foa_dec_wav[1] != NULL ) + { + UpdateWave( fs, n_transport, 16, spar_foa_dec_wav[1] ); + CloseWav( spar_foa_dec_wav[1] ); + } + if ( spar_foa_dec_wav[2] != NULL ) + { + UpdateWave( fs, pca_ingest_channels, 16, spar_foa_dec_wav[2] ); + CloseWav( spar_foa_dec_wav[2] ); + } + if ( spar_foa_dec_wav[3] != NULL ) + { + UpdateWave( fs, n_ch, 16, spar_foa_dec_wav[3] ); + CloseWav( spar_foa_dec_wav[3] ); + } + + return; +} + + +void ivas_close_sba_encoder_debug_files( void ) +{ + + if ( spar_foa_enc_wav[0] != NULL ) + { + CloseWav( spar_foa_enc_wav[0] ); + } + if ( spar_foa_enc_wav[1] != NULL ) + { + CloseWav( spar_foa_enc_wav[1] ); + } + if ( spar_foa_enc_wav[2] != NULL ) + { + CloseWav( spar_foa_enc_wav[2] ); + } + + /* Enable print max diff to a file */ + + /* FILE *fp = fopen("max_diff.txt", "a"); + fprintf(fp, "%s\n", file_names[0]); + fprintf(fp, "max diff = %0.15f\n frame_no = %d\n band num = %d\n coeff type %d\n", max_diff, dbg_frm_num, dbg_band, dbg_type); + fclose(fp); */ + + /* Enable print max eig iters to a file */ + + /*FILE *fp = fopen("max_iters.txt", "a"); + fprintf(fp, "%s\n", file_names[0]); + fprintf(fp, "%d\n", iter_max); + fclose(fp); */ + + return; +} + + +void ivas_open_sba_decoder_debug_files( + const int32_t fs, + const int16_t n_ch, + const int16_t n_transport ) +{ + int8_t fb_wav_dump_path[4][MAX_PLUG_IN_FILE_LEN] = { "", "", "", "" }; + + cstrcat( (char *) fb_wav_dump_path[0], sizeof( fb_wav_dump_path[0] ), "dec_out.wav" ); + spar_foa_dec_wav[0] = CreateWav( (const char *) fb_wav_dump_path[0], fs, n_ch, 32 /* const uint32_t writeWaveExt */ ); + + cstrcat( (char *) fb_wav_dump_path[1], sizeof( fb_wav_dump_path[1] ), "agc_dec_out.wav" ); + spar_foa_dec_wav[1] = CreateWav( (const char *) fb_wav_dump_path[1], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + + cstrcat( (char *) fb_wav_dump_path[2], sizeof( fb_wav_dump_path[2] ), "pca_dec.wav" ); + spar_foa_dec_wav[2] = CreateWav( (const char *) fb_wav_dump_path[2], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + + cstrcat( (char *) fb_wav_dump_path[3], sizeof( fb_wav_dump_path[3] ), "cldfbSynthesis.wav" ); + spar_foa_dec_wav[3] = CreateWav( (const char *) fb_wav_dump_path[3], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + + return; +} + + +void ivas_open_sba_encoder_debug_files( + const int32_t fs, + const int16_t n_transport, + const char *file_tag, + const int32_t ivas_total_brate, + const int16_t dtx_on ) +{ + int8_t fb_wav_dump_path[3][MAX_PLUG_IN_FILE_LEN] = { "spar_foa_enc", "spar_foa_enc", "spar_foa_enc" }; + + if ( file_tag != NULL ) + { + cstrcpy( (char *) file_names[0], sizeof( file_names[0] ), (const char *) file_tag ); + } + + /* ivas_total_brate */ + switch ( ivas_total_brate ) + { + case IVAS_24k4: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr24k" ); + break; + case IVAS_32k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr32k" ); + break; + case IVAS_48k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr48k" ); + break; + case IVAS_64k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr64k" ); + break; + case IVAS_80k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr80k" ); + break; + case IVAS_96k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr96k" ); + break; + case IVAS_128k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr128k" ); + break; + case IVAS_160k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr160k" ); + break; + case IVAS_192k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr192k" ); + break; + case IVAS_256k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr256k" ); + break; + case IVAS_384k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr384k" ); + break; + case IVAS_512k: + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr512k" ); + break; + } + + /* DTX */ + if ( dtx_on ) + { + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_DTX1" ); + } + else + { + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_DTX0" ); + } + + cstrcpy( (char *) file_names[1], sizeof( file_names[1] ), (const char *) file_names[0] ); + cstrcpy( (char *) file_names[2], sizeof( file_names[2] ), (const char *) file_names[0] ); + cstrcpy( (char *) file_names[3], sizeof( file_names[3] ), (const char *) file_names[0] ); + cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_pcm.txt" ); + + cstrcat( (char *) fb_wav_dump_path[0], sizeof( fb_wav_dump_path[0] ), (const char *) file_names[2] ); + cstrcat( (char *) fb_wav_dump_path[0], sizeof( fb_wav_dump_path[0] ), "_pca_enc.wav" ); + spar_foa_enc_wav[0] = CreateWav( (const char *) fb_wav_dump_path[0], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + + cstrcat( (char *) fb_wav_dump_path[1], sizeof( fb_wav_dump_path[1] ), (const char *) file_names[2] ); + cstrcat( (char *) fb_wav_dump_path[1], sizeof( fb_wav_dump_path[1] ), "_fb_mixer_enc.wav" ); + spar_foa_enc_wav[1] = CreateWav( (const char *) fb_wav_dump_path[1], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + + cstrcat( (char *) fb_wav_dump_path[2], sizeof( fb_wav_dump_path[2] ), (const char *) file_names[2] ); + cstrcat( (char *) fb_wav_dump_path[2], sizeof( fb_wav_dump_path[2] ), "_agc_enc.wav" ); + spar_foa_enc_wav[2] = CreateWav( (const char *) fb_wav_dump_path[2], fs, n_transport, 16 /* const uint32_t writeWaveExt */ ); + + return; +} + +#endif /* DEBUG_SBA */ diff --git a/lib_debug/spar_debug.h b/lib_debug/sba_debug.h similarity index 67% rename from lib_debug/spar_debug.h rename to lib_debug/sba_debug.h index 530996d81b87385ef40c213e47de39aece8fd572..cd4fd58c11a22f39e99b8d73a6c6dd12ce7212d1 100644 --- a/lib_debug/spar_debug.h +++ b/lib_debug/sba_debug.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,31 +30,31 @@ *******************************************************************************************************/ -#ifndef SPAR_DEBUG_H -#define SPAR_DEBUG_H +#ifndef SBA_DEBUG_H +#define SBA_DEBUG_H #include "options.h" #include #include - -/*------------------------------------------------------------------------------------------* - * Global variables used for debugging - *------------------------------------------------------------------------------------------*/ -#ifdef DEBUG_SPAR_FOA -typedef struct spar_debug_t -{ - const char *file_tag; - int32_t ivas_total_brate; - int16_t dtx_on; - int16_t agc; -} spar_debug_t; +#ifdef DEBUG_SBA +#include "cnst.h" +#include "ivas_cnst.h" +#include "tinywaveout_c.h" + +#ifdef DEBUG_SBA_AUDIO_DUMP +extern WAVEFILEOUT *spar_foa_enc_wav[3]; +extern WAVEFILEOUT *spar_foa_dec_wav[4]; +#endif #ifdef DEBUG_AGC -void ivas_close_agc_debug_files( spar_debug_t *pDebug_params ); -void ivas_open_agc_debug_files( spar_debug_t *pDebug_params ); +void ivas_close_agc_debug_files( void ); +void ivas_open_agc_debug_files( int16_t agc ); #endif -void ivas_close_remove_debug_files( void ); -void ivas_open_debug_files( spar_debug_t *pDebug_params ); +void ivas_spar_dump_signal_wav( const int16_t input_frame, float **ppPcm, float pcm_array[IVAS_SPAR_MAX_CH][L_FRAME48k], const int16_t no_channel, WAVEFILEOUT *wave_file, char *location ); +void ivas_close_sba_encoder_debug_files( void ); +void ivas_open_sba_encoder_debug_files( const int32_t fs, const int16_t n_transport, const char *file_tag, const int32_t ivas_total_brate, const int16_t dtx_on ); +void ivas_close_sba_decoder_debug_files( const int32_t fs, const int16_t n_ch, const int16_t n_transport, const int16_t pca_ingest_channels ); +void ivas_open_sba_decoder_debug_files( const int32_t fs, const int16_t n_ch, const int16_t n_transport ); #endif -#endif /* SPAR_DEBUG_H */ +#endif /* SBA_DEBUG_H */ diff --git a/lib_debug/segsnr.c b/lib_debug/segsnr.c deleted file mode 100644 index 561a4e239d4987558e9c0346c44520ed35370466..0000000000000000000000000000000000000000 --- a/lib_debug/segsnr.c +++ /dev/null @@ -1,103 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "wmops.h" -#include -#include "options.h" -#include "prot.h" - -#define WMC_TOOL_MAN - -#ifdef OUTPUT_SNR -/*_____________________________________________________________________ - | | - | FUNCTION NAME segsnr | - | Computes the segmential signal-to-noise ratio between the | - | signal x and its estimate xe of length n samples. The segment | - | length is nseg samples. | - | - | INPUT - | x[0:n-1] Signal of n samples. - | xe[0:n-1] Estimated signal of n samples. - | n Signal length. - | nseg Segment length, must be a submultiple of n. - | - | RETURN VALUE - | snr Segmential signal to noise ratio in dB. - |_____________________________________________________________________| -*/ - -float segsnr( float x[], float xe[], int16_t n, int16_t nseg ) -{ - float snr = 0.0f; - float signal, noise, error, fac; - int16_t i, j; - LOOP( 1 ); - for ( i = 0; i < n; i += nseg ) - { - signal = 1e-6f; - MOVE( 2 ); - noise = 1e-6f; - LOOP( 1 ); - for ( j = 0; j < nseg; j++ ) - { - signal += ( *x ) * ( *x ); - MAC( 1 ); - error = *x++ - *xe++; - ADD( 1 ); - noise += error * error; - MAC( 1 ); - } - snr += (float) log10( signal / noise ); - TRANS( 1 ); - DIV( 1 ); - ADD( 1 ); - } - fac = ( (float) ( 10 * nseg ) ) / (float) n; - DIV( 1 ); - MULT( 1 ); - snr = fac * snr; - MULT( 1 ); - ADD( 1 ); - BRANCH( 1 ); - if ( snr < -99.0f ) - { - snr = -99.0f; - MOVE( 1 ); - } - return ( snr ); -} -#endif diff --git a/lib_debug/snr.c b/lib_debug/snr.c index a524b35c26e6d5f6004cd8a3600f82060785e81e..f6e6fa9d5219bbb0d41e3394571bd770794bc97a 100644 --- a/lib_debug/snr.c +++ b/lib_debug/snr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,15 +32,15 @@ #include #include "options.h" -#include "rom_com.h" #ifdef DEBUGGING #include "debug.h" #endif #include #include -#include "wmops.h" +#include +#include "wmc_auto.h" #include "cnst.h" -#include "prot.h" +#include "ivas_cnst.h" #ifdef DEBUGGING @@ -79,6 +79,150 @@ static float mem_deemph_y[MAX_INPUT_CHANNELS] = { 0 }; static float mem_synth_snr[MAX_INPUT_CHANNELS][M]; +/*-------------------------------------------------------------------* + * Local functions - they are copies of functions declared in prot.h but + here we do not want to include prot.h due to its dependencies + *--------------------------------------------------------------------*/ + +static void set_f( + float y[], /* i/o: Vector to set */ + const float a, /* i : Value to set the vector to */ + const int16_t N /* i : Lenght of the vector */ +) +{ + int16_t i; + + for ( i = 0; i < N; i++ ) + { + y[i] = a; + } + + return; +} + + +static float sum2_f( + const float *vec, /* i : input vector */ + const int16_t lvec /* i : length of input vector */ +) +{ + int16_t i; + float tmp; + + tmp = 0.0f; + for ( i = 0; i < lvec; i++ ) + { + tmp += vec[i] * vec[i]; + } + + return tmp; +} + + +static void mvr2r( + const float x[], /* i : input vector */ + float y[], /* o : output vector */ + const int16_t n /* i : vector size */ +) +{ + int16_t i; + + if ( n <= 0 ) + { + /* cannot transfer vectors with size 0 */ + return; + } + + if ( y < x ) + { + for ( i = 0; i < n; i++ ) + { + y[i] = x[i]; + } + } + else + { + for ( i = n - 1; i >= 0; i-- ) + { + y[i] = x[i]; + } + } + + return; +} + +static void residu( + const float *a, /* i : LP filter coefficients */ + const int16_t m, /* i : order of LP filter */ + const float *x, /* i : input signal (usually speech) */ + float *y, /* o : output signal (usually residual) */ + const int16_t l /* i : size of filtering */ +) +{ + float s; + int16_t i, j; + + for ( i = 0; i < l; i++ ) + { + s = x[i]; + for ( j = 1; j <= m; j++ ) + { + s += a[j] * x[i - j]; + } + y[i] = s; + } + + return; +} + +static void deemph( + float *signal, /* i/o: signal */ + const float mu, /* i : deemphasis factor */ + const int16_t L, /* i : vector size */ + float *mem /* i/o: memory (y[-1]) */ +) +{ + int16_t i; + + signal[0] = signal[0] + mu * ( *mem ); + for ( i = 1; i < L; i++ ) + { + signal[i] = signal[i] + mu * signal[i - 1]; + } + + *mem = signal[L - 1]; + + if ( ( *mem < 1e-10 ) & ( *mem > -1e-10 ) ) + { + *mem = 0; + } + + return; +} + +static void weight_a( + const float *a, /* i : LP filter coefficients */ + float *ap, /* o : weighted LP filter coefficients */ + const float gamma, /* i : weighting factor */ + const int16_t m /* i : order of LP filter */ +) +{ + float f; + int16_t i; + + ap[0] = a[0]; + f = gamma; + + for ( i = 1; i <= m; i++ ) + { + ap[i] = f * a[i]; + f *= gamma; + } + + return; +} + + /*-------------------------------------------------------------------* * snr() * @@ -252,7 +396,7 @@ void snr_celp( noise2 = sum2_f( &noise[i], L_subfr ) + 0.001f; if ( signal2 < noise2 ) signal2 = noise2; - subframe_snr = 10.0f * (float) log10( signal2 / noise2 ); + subframe_snr = 10.0f * log10f( signal2 / noise2 ); if ( L_frame == L_FRAME ) { diff --git a/lib_debug/spar_debug.c b/lib_debug/spar_debug.c deleted file mode 100644 index a1dd7a9ee8cda973600de8c2feaa15871254bf5e..0000000000000000000000000000000000000000 --- a/lib_debug/spar_debug.c +++ /dev/null @@ -1,283 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include -#include -#include -#include -#include "options.h" -#include "ivas_cnst.h" -#include "prot.h" -#include "spar_debug.h" -#include -#include "wmops.h" - - -/*-------------------------------------------------------------------* - * Global variables used for debugging but not under DEBUGGING flag - *--------------------------------------------------------------------*/ -#ifdef DEBUG_SPAR_FOA -#define MAX_IN_FILE_LEN ( 1000 ) -#define MAX_PLUG_IN_FILE_LEN ( MAX_IN_FILE_LEN ) -#define MAX_DEBUG_TAG_LEN ( 50 ) -#define NUM_DEBUG_FILES ( 4 ) -#define MAX_TAG_LEN ( 200 ) - -FILE *fEvs_enc_in; -FILE *fMd_data; -FILE *fModels_data; -FILE *fEig_iters; -FILE *fFb_out[4]; -float max_diff = 0; -int32_t dbg_frm_num; -int32_t dbg_band; -int32_t dbg_type; -int32_t iter_max = 0; -FILE *fFb_pcm = NULL; -int8_t file_names[NUM_DEBUG_FILES][MAX_TAG_LEN + MAX_DEBUG_TAG_LEN]; - - -#ifdef DEBUG_AGC -FILE *agcOut; /* temporary AGC bitstream */ -#endif - -/*-----------------------------------------------------------------------------------------* - * Function description - * cstrcpy() - Custom implementation of strcpy - * - * Inputs: - * const char* _Source -> Source buffer - * _SizeInBytes -> Destination buffer size in bytes - * - * Outputs: - * char* _Destination -> Destination buffer - *-----------------------------------------------------------------------------------------*/ - -static void cstrcpy( char *_Destination, size_t _SizeInBytes, const char *_Source ) -{ - size_t SourceSizeInBytes = strlen( _Source ); - if ( _SizeInBytes > SourceSizeInBytes ) - { - strcpy( _Destination, _Source ); - } - else - { - assert( 0 ); - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function description - * cstrcat() - Custom implementation of strcat - * - * Inputs: - * const char* _Source -> Source buffer - * _SizeInBytes -> Destination buffer size in bytes - * - * Outputs: - * char* _Destination -> Destination buffer - *-----------------------------------------------------------------------------------------*/ - -static void cstrcat( char *_Destination, size_t _SizeInBytes, const char *_Source ) -{ - size_t SourceSizeInBytes = strlen( _Source ); - size_t DestSizeInBytes = _SizeInBytes - strlen( _Destination ); - if ( DestSizeInBytes > SourceSizeInBytes ) - { - strcat( _Destination, _Source ); - } - else - { - assert( 0 ); - } - - return; -} - - -#ifdef DEBUG_AGC -void ivas_close_agc_debug_files( spar_debug_t *pDebug_params ) -{ - if ( pDebug_params->agc > 0 ) /* temporary */ - { - if ( agcOut != NULL ) - { - fclose( agcOut ); - } - } -} - -void ivas_open_agc_debug_files( spar_debug_t *pDebug_params ) -{ - /* Temporary AGC file */ - if ( pDebug_params->agc > 0 ) - { - char agcFilename[50] = "agcBitstream.bin"; - if ( ( agcOut = fopen( agcFilename, "wb" ) ) == NULL ) - { - fprintf( stderr, "Error: Gain Control bitstream file %s could not be opened\n\n", agcFilename ); - exit( -1 ); - } - fprintf( stdout, "Temporary gain control bitstream file %s is opened\n", agcFilename ); - } -} - -#endif - - -void ivas_close_remove_debug_files( void ) -{ - if ( fEvs_enc_in != NULL ) - fclose( fEvs_enc_in ); - if ( fMd_data != NULL ) - fclose( fMd_data ); - if ( fModels_data != NULL ) - fclose( fModels_data ); - if ( fEig_iters != NULL ) - fclose( fEig_iters ); - - /* Enable print max diff to a file */ - - /* FILE *fp = fopen("max_diff.txt", "a"); - fprintf(fp, "%s\n", file_names[0]); - fprintf(fp, "max diff = %0.15f\n frame_no = %d\n band num = %d\n coeff type %d\n", max_diff, dbg_frm_num, dbg_band, dbg_type); - fclose(fp); */ - - /* Enable print max eig iters to a file */ - - /*FILE *fp = fopen("max_iters.txt", "a"); - fprintf(fp, "%s\n", file_names[0]); - fprintf(fp, "%d\n", iter_max); - fclose(fp); */ -} - -void ivas_open_debug_files( spar_debug_t *pDebug_params ) -{ -#ifndef MSVS_DEBUG - int8_t evs_in_path[MAX_PLUG_IN_FILE_LEN] = "spar_foa_bs/enc/evs_pcm_in/"; - int8_t mat_md_path[MAX_PLUG_IN_FILE_LEN] = "spar_foa_bs/enc/mat_md/"; - int8_t models_data_path[MAX_PLUG_IN_FILE_LEN] = "spar_foa_bs/enc/ec_models/"; - int8_t fb_pcm_dump_path[4][MAX_PLUG_IN_FILE_LEN] = { "spar_foa_bs/fb_dumps/", "spar_foa_bs/fb_dumps/", "spar_foa_bs/fb_dumps/", "spar_foa_bs/fb_dumps/" }; -#else - int8_t evs_in_path[MAX_PLUG_IN_FILE_LEN] = "../scripts/ivas_pytests/tests/restricted/system_tests/spar_foa_bs/enc/evs_pcm_in/"; - int8_t mat_md_path[MAX_PLUG_IN_FILE_LEN] = "../scripts/ivas_pytests/tests/restricted/system_tests/spar_foa_bs/enc/mat_md/"; - int8_t models_data_path[MAX_PLUG_IN_FILE_LEN] = "../scripts/ivas_pytests/tests/restricted/system_tests/spar_foa_bs/enc/ec_models/"; - int8_t fb_pcm_dump_path[4][MAX_PLUG_IN_FILE_LEN] = { "../scripts/ivas_pytests/tests/restricted/system_tests/spar_foa_bs/fb_dumps/", "../tests/restricted/system_tests/spar_foa_bs/fb_dumps/", "../tests/restricted/system_tests/spar_foa_bs/fb_dumps/", "../tests/restricted/system_tests/spar_foa_bs/fb_dumps/" }; -#endif - - if ( pDebug_params->file_tag != NULL ) - { - cstrcpy( (char *) file_names[0], sizeof( file_names[0] ), (const char *) pDebug_params->file_tag ); - } - - /* ivas_total_brate */ - switch ( pDebug_params->ivas_total_brate ) - { - case 32000: - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr32k" ); - break; - case 64000: - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr64k" ); - break; - case 96000: - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr96k" ); - break; - case 160000: - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr160k" ); - break; - case 256000: - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr256k" ); - break; - case 384000: - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr384k" ); - break; - case 512000: - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_ivasbr512k" ); - break; - } - - /* fb id */ - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_48dly" ); - - /* DTX */ - if ( pDebug_params->dtx_on ) - { - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_DTX1" ); - } - else - { - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_DTX0" ); - } - - cstrcpy( (char *) file_names[1], sizeof( file_names[1] ), (const char *) file_names[0] ); - cstrcpy( (char *) file_names[2], sizeof( file_names[2] ), (const char *) file_names[0] ); - cstrcpy( (char *) file_names[3], sizeof( file_names[3] ), (const char *) file_names[0] ); - cstrcat( (char *) file_names[0], sizeof( file_names[0] ), "_pcm.txt" ); - - cstrcat( (char *) evs_in_path, sizeof( evs_in_path ), (const char *) file_names[0] ); - fEvs_enc_in = fopen( (const char *) evs_in_path, "rb" ); - - cstrcat( (char *) file_names[1], sizeof( file_names[1] ), ".md" ); - cstrcat( (char *) mat_md_path, sizeof( mat_md_path ), (const char *) file_names[1] ); - fMd_data = fopen( (const char *) mat_md_path, "rb" ); - - cstrcat( (char *) file_names[3], sizeof( file_names[3] ), ".txt" ); - cstrcat( (char *) models_data_path, sizeof( models_data_path ), (const char *) file_names[3] ); - fModels_data = fopen( (const char *) models_data_path, "rb" ); - - fEig_iters = NULL; - /*Enable this below to dump iteration count for each frame - fEig_iters = fopen(strcat(eig_iter_dmp_path, strcat(file_names[1], "_eig_iters.txt")), "wb"); */ - - /* Enable for fb pcm dumps */ - cstrcat( (char *) fb_pcm_dump_path[0], sizeof( fb_pcm_dump_path[0] ), (const char *) file_names[2] ); - cstrcat( (char *) fb_pcm_dump_path[0], sizeof( fb_pcm_dump_path[0] ), "/ch1.raw" ); - fFb_out[0] = fopen( (const char *) fb_pcm_dump_path[0], "wb" ); - - cstrcat( (char *) fb_pcm_dump_path[1], sizeof( fb_pcm_dump_path[1] ), (const char *) file_names[2] ); - cstrcat( (char *) fb_pcm_dump_path[1], sizeof( fb_pcm_dump_path[1] ), "/ch2.raw" ); - fFb_out[1] = fopen( (const char *) fb_pcm_dump_path[1], "wb" ); - - cstrcat( (char *) fb_pcm_dump_path[2], sizeof( fb_pcm_dump_path[2] ), (const char *) file_names[2] ); - cstrcat( (char *) fb_pcm_dump_path[2], sizeof( fb_pcm_dump_path[2] ), "/ch3.raw" ); - fFb_out[2] = fopen( (const char *) fb_pcm_dump_path[2], "wb" ); - - cstrcat( (char *) fb_pcm_dump_path[3], sizeof( fb_pcm_dump_path[3] ), (const char *) file_names[2] ); - cstrcat( (char *) fb_pcm_dump_path[3], sizeof( fb_pcm_dump_path[3] ), "/ch4.raw" ); - fFb_out[3] = fopen( (const char *) fb_pcm_dump_path[3], "wb" ); -} - -#endif /* DEBUG_SPAR_FOA */ diff --git a/lib_debug/wmc_auto.c b/lib_debug/wmc_auto.c new file mode 100644 index 0000000000000000000000000000000000000000..029640a1dba8bce33cafd82907ef5bb5e5d5dabe --- /dev/null +++ b/lib_debug/wmc_auto.c @@ -0,0 +1,1926 @@ +/* + * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * + * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, + * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file + * or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". + * + * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor + * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software + * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. + * + * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) + */ + +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#include +#else +#include +#endif + +#include "options.h" +#include "wmc_auto.h" + + +#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ + +#ifdef WMOPS + +/*-------------------------------------------------------------------* + * Complexity counting tool + *--------------------------------------------------------------------*/ + +#define MAX_RECORDS 1024 +#define MAX_CHAR 64 +#define MAX_STACK 64 +#define DOUBLE_MAX 0x80000000 + +struct wmops_record +{ + char label[MAX_CHAR]; + long call_number; + long update_cnt; + int call_tree[MAX_RECORDS]; + double start_selfcnt; + double current_selfcnt; + double max_selfcnt; + double min_selfcnt; + double tot_selfcnt; + double start_cnt; /* The following take into account the decendants */ + double current_cnt; + double max_cnt; + double min_cnt; + double tot_cnt; +#ifdef WMOPS_WC_FRAME_ANALYSIS + int32_t current_call_number; + double wc_cnt; + double wc_selfcnt; + int32_t wc_call_number; +#endif +}; + +double ops_cnt; +double prom_cnt; +double inst_cnt[NUM_INST]; + +static struct wmops_record wmops[MAX_RECORDS]; +static int stack[MAX_STACK]; +static int sptr; +static int num_records; +static int current_record; +static long update_cnt; +static double start_cnt; +static double max_cnt; +static double min_cnt; +static double inst_cnt_wc[NUM_INST]; +static long fnum_cnt_wc; + +static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0; + + +void reset_wmops( void ) +{ + int i, j; + + for ( i = 0; i < MAX_RECORDS; i++ ) + { + strcpy( &wmops[i].label[0], "\0" ); + wmops[i].call_number = 0; + wmops[i].update_cnt = 0; + for ( j = 0; j < MAX_RECORDS; j++ ) + { + wmops[i].call_tree[j] = -1; + } + wmops[i].start_selfcnt = 0.0; + wmops[i].current_selfcnt = 0.0; + wmops[i].max_selfcnt = 0.0; + wmops[i].min_selfcnt = DOUBLE_MAX; + wmops[i].tot_selfcnt = 0.0; + wmops[i].start_cnt = 0.0; + wmops[i].current_cnt = 0.0; + wmops[i].max_cnt = 0.0; + wmops[i].min_cnt = DOUBLE_MAX; + wmops[i].tot_cnt = 0.0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].wc_cnt = 0.0; + wmops[i].wc_selfcnt = 0.0; + wmops[i].current_call_number = 0; +#endif + } + + for ( i = 0; i < MAX_STACK; i++ ) + { + stack[i] = -1; + } + sptr = 0; + num_records = 0; + current_record = -1; + update_cnt = 0; + + max_cnt = 0.0; + min_cnt = DOUBLE_MAX; + start_cnt = 0.0; + ops_cnt = 0.0; +} + + +void push_wmops( const char *label ) +{ + int new_flag; + int i, j; + + /* Check if new function record label */ + new_flag = 1; + for ( i = 0; i < num_records; i++ ) + { + if ( strcmp( wmops[i].label, label ) == 0 ) + { + new_flag = 0; + break; + } + } + + /* Configure new record */ + if ( new_flag ) + { + if ( num_records >= MAX_RECORDS ) + { + fprintf( stdout, "push_wmops(): exceeded MAX_RECORDS count.\n\n" ); + exit( -1 ); + } + strcpy( wmops[i].label, label ); + num_records++; + } + + /* Push current context onto stack */ + if ( current_record >= 0 ) + { + if ( sptr >= MAX_STACK ) + { + fprintf( stdout, "\r push_wmops(): stack exceeded, try inreasing MAX_STACK\n" ); + exit( -1 ); + } + stack[sptr++] = current_record; + + /* accumulate op counts */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + + /* update call tree */ + for ( j = 0; j < MAX_RECORDS; j++ ) + { + if ( wmops[i].call_tree[j] == current_record ) + { + break; + } + else if ( wmops[i].call_tree[j] == -1 ) + { + wmops[i].call_tree[j] = current_record; + break; + } + } + } + + /* init current record */ + current_record = i; + wmops[current_record].start_selfcnt = ops_cnt; + wmops[current_record].start_cnt = ops_cnt; + wmops[current_record].call_number++; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[current_record].current_call_number++; +#endif + + return; +} + + +void pop_wmops( void ) +{ + + /* Check for underflow */ + if ( current_record < 0 ) + { + fprintf( stdout, "\r pop_wmops(): stack underflow, too many calls to pop_wmops()\n" ); + exit( -1 ); + } + + /* update count of current record */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; + + /* Get back previous context from stack */ + if ( sptr > 0 ) + { + current_record = stack[--sptr]; + wmops[current_record].start_selfcnt = ops_cnt; + } + else + { + current_record = -1; + } + + return; +} + + +void update_wmops( void ) +{ + int i; + double current_cnt; +#ifdef WMOPS_PER_FRAME + static FILE *fid = NULL; + const char filename[] = "wmops_analysis"; + float tmpF; +#endif + + if ( sptr != 0 ) + { + fprintf( stdout, "update_wmops(): Stack must be empty!\n" ); + exit( -1 ); + } + +#ifdef WMOPS_PER_FRAME + /* Check, if the output file has already been opened */ + if ( fid == NULL ) + { + fid = fopen( filename, "wb" ); + + if ( fid == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", filename ); + exit( -1 ); + } + } + + /* Write current complexity to the external file */ + tmpF = (float) ( FAC * wmops[0].current_cnt ); + fwrite( &tmpF, sizeof( float ), 1, fid ); +#endif + +#ifdef WMOPS_WC_FRAME_ANALYSIS + if ( ops_cnt - start_cnt > max_cnt ) + { + for ( i = 0; i < num_records; i++ ) + { + wmops[i].wc_cnt = wmops[i].current_cnt; + wmops[i].wc_selfcnt = wmops[i].current_selfcnt; + wmops[i].wc_call_number = wmops[i].current_call_number; + } + } +#endif + + for ( i = 0; i < num_records; i++ ) + { + wmops[i].tot_selfcnt += wmops[i].current_selfcnt; + wmops[i].tot_cnt += wmops[i].current_cnt; + + if ( wmops[i].current_selfcnt > 0 ) + { + if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt ) + { + wmops[i].max_selfcnt = wmops[i].current_selfcnt; + } + + if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt ) + { + wmops[i].min_selfcnt = wmops[i].current_selfcnt; + } + } + + wmops[i].current_selfcnt = 0; + + if ( wmops[i].current_cnt > 0 ) + { + if ( wmops[i].current_cnt > wmops[i].max_cnt ) + { + wmops[i].max_cnt = wmops[i].current_cnt; + } + + if ( wmops[i].current_cnt < wmops[i].min_cnt ) + { + wmops[i].min_cnt = wmops[i].current_cnt; + } + + wmops[i].update_cnt++; + } + + wmops[i].current_cnt = 0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].current_call_number = 0; +#endif + } + + current_cnt = ops_cnt - start_cnt; + if ( current_cnt > max_cnt ) + { + max_cnt = current_cnt; + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt_wc[i] = inst_cnt[i]; + } + + fnum_cnt_wc = update_cnt + 1; + } + + if ( current_cnt < min_cnt ) + { + min_cnt = current_cnt; + } + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt[i] = 0.0; + } + + start_cnt = ops_cnt; + + /* increment frame counter */ + update_cnt++; + + return; +} + + +void print_wmops( void ) +{ + int i; + + char *sfmts = "%20s %8s %8s %7s %7s\n"; + char *dfmts = "%20s %8.2f %8.3f %7.3f %7.3f\n"; + char *sfmt = "%20s %8s %8s %7s %7s %7s %7s %7s\n"; + char *dfmt = "%20s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; + +#ifdef WMOPS_WC_FRAME_ANALYSIS + int j, label_len, max_label_len; + char *sfmtt = "%20s %4s %15s\n"; + char *dfmtt = "%20s %4d "; +#endif + + fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); + + fprintf( stdout, "%54s %23s\n", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); + fprintf( stdout, sfmt, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); + fprintf( stdout, sfmt, "---------------", "------", "------", "------", "------", "------", "------", "------" ); + + for ( i = 0; i < num_records; i++ ) + { + fprintf( stdout, dfmt, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, + wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt, + FAC * wmops[i].max_selfcnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, + wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt, + FAC * wmops[i].max_cnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); + } + + fprintf( stdout, sfmts, "---------------", "------", "------", "------", "------" ); + fprintf( stdout, dfmts, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); + fprintf( stdout, "\n" ); + +#ifdef WMOPS_WC_FRAME_ANALYSIS + /* calculate maximum label length for compact prinout */ + max_label_len = 0; + for ( i = 0; i < num_records; i++ ) + { + label_len = strlen( wmops[i].label ); + if ( label_len > max_label_len ) + { + max_label_len = label_len; + } + } + max_label_len += 4; + + fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n", fnum_cnt_wc ); + fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); + fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); + + for ( i = 0; i < num_records; i++ ) + { + fprintf( stdout, "%*s %8d %10.3f %12.3f\n", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt ); + } + + fprintf( stdout, "\nCall Tree:\n\n" ); + fprintf( stdout, sfmtt, " function", "num", "called by: " ); + fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); + + for ( i = 0; i < num_records; i++ ) + { + fprintf( stdout, dfmtt, wmops[i].label, i ); + for ( j = 0; wmops[i].call_tree[j] != -1; j++ ) + { + if ( j != 0 ) + { + fprintf( stdout, ", " ); + } + fprintf( stdout, "%d", wmops[i].call_tree[j] ); + } + fprintf( stdout, "\n" ); + } + + fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); + fprintf( stdout, "\n\n" ); + + fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); /* added -- JPA */ + for ( i = 0; i < NUM_INST; i++ ) + { + switch ( (enum instructions) i ) + { + case _ADD: + fprintf( stdout, "\tAdds: %12.1f\n", inst_cnt_wc[i] ); + break; + case _ABS: + fprintf( stdout, "\tAbsolutes: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MULT: + fprintf( stdout, "\tMultiplies: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MAC: + fprintf( stdout, "\tMACs: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MOVE: + fprintf( stdout, "\tMoves: %12.1f\n", inst_cnt_wc[i] ); + break; + case _STORE: + fprintf( stdout, "\tStores: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOGIC: + fprintf( stdout, "\tLogicals: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SHIFT: + fprintf( stdout, "\tShifts: %12.1f\n", inst_cnt_wc[i] ); + break; + case _BRANCH: + fprintf( stdout, "\tBranches: %12.1f\n", inst_cnt_wc[i] ); + break; + case _DIV: + fprintf( stdout, "\tDivisions: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SQRT: + fprintf( stdout, "\tSquare Root: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TRANS: + fprintf( stdout, "\tTrans: %12.1f\n", inst_cnt_wc[i] ); + break; + case _FUNC: + fprintf( stdout, "\tFunc Call: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOOP: + fprintf( stdout, "\tLoop Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _INDIRECT: + fprintf( stdout, "\tIndirect Addr: %12.1f\n", inst_cnt_wc[i] ); + break; + case _PTR_INIT: + fprintf( stdout, "\tPointer Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TEST: + fprintf( stdout, "\tExtra condit.: %12.1f\n", inst_cnt_wc[i] ); + break; + case _POWER: + fprintf( stdout, "\tExponential: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOG: + fprintf( stdout, "\tLogarithm: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MISC: + fprintf( stdout, "\tAll other op.: %12.1f\n", inst_cnt_wc[i] ); + break; + default: + fprintf( stdout, "\tERROR: Invalid instruction type: %d\n\n", i ); + } + } +#endif + + return; +} + + +/*-------------------------------------------------------------------* + * Memory counting tool measuring RAM usage (stack and heap) + * + * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame. + * + * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function + * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process. + * + * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is + * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process. + * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated + * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame. + * + * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process. + * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words). + * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS' + * is activated, detailed information is printed + * + * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use + * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free(). + *--------------------------------------------------------------------*/ + +#define MAX_RECORDABLE_CALLS 100 +#define MAX_FUNCTION_NAME_LENGTH 35 /* Maximum length that the function string will be truncated to */ +#define MAX_PARAMS_LENGTH 50 /* Maximum length that the parameter string will be truncated to */ +#define MAX_NUM_RECORDS 300 /* Initial maximum number of memory records -> mightb be increased during runtime, if needed */ +#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of memory records, increase the number of records by this number */ + +/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using + a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */ +#ifdef MEM_ALIGN_64BITS +#define BLOCK_ROUNDING 8 /* Align on 64 Bits */ +#else +#define BLOCK_ROUNDING 4 /* Align on 32 Bits */ +#endif + +#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) + +#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */ +#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */ +#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */ +#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */ + +#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) +#define IS_CALLOC( str ) ( str[0] == 'c' ) + +#ifdef MEM_COUNT_DETAILS +const char *csv_filename = "mem_analysis.csv"; +static FILE *fid_csv_filename = NULL; +#endif + +typedef struct +{ + char function_name[MAX_FUNCTION_NAME_LENGTH + 1]; + int16_t *stack_ptr; +} caller_info; + +caller_info stack_callers[2][MAX_RECORDABLE_CALLS]; + +typedef struct +{ + char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ + char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */ + unsigned long hash; + int lineno; + void *block_ptr; + int block_size; + unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */ + unsigned long total_used_size; /* Cumulative sum of the used size in the session */ + int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */ + int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */ + int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */ + int OOB_Flag; + int noccurances; /* Number of times that the memory block has been allocated in a frame */ +} allocator_record; + +allocator_record *allocation_list = NULL; + +static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ +static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */ +static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */ +static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */ +static int32_t wc_ram_size, wc_ram_frame; +static int32_t current_heap_size; +static int current_calls = 0; +static char location_max_stack[256] = "undefined"; +static int Num_Records, Max_Num_Records; +static size_t Stat_Cnt_Size = USE_BYTES; +static const char *Count_Unit[] = { "bytes", "words", "words" }; + +static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap; +static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap; +static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap; + +/* Local Functions */ +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ); +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ); +static void *mem_alloc_block( size_t size, const char *size_str ); + +/*-------------------------------------------------------------------* + * reset_mem() + * + * Initialize/reset memory counting tool (stack and heap) + *--------------------------------------------------------------------*/ + +void reset_mem( Counting_Size cnt_size ) +{ + int16_t something; + size_t tmp_size; + + /* initialize stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + Stat_Cnt_Size = cnt_size; + + /* Check, if sizeof(int32_t) is 4 bytes */ + tmp_size = sizeof( int32_t ); + if ( tmp_size != 4 ) + { + fprintf( stderr, "Error: Expecting 'int32_t' to be a 32 Bits Integer!" ); + exit( -1 ); + } + + /* create allocation list for malloc() memory blocks */ + if ( allocation_list == NULL ) + { + allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) ); + } + + if ( allocation_list == NULL ) + { + fprintf( stderr, "Error: Unable to Create List of Memory Blocks!" ); + exit( -1 ); + } + + Num_Records = 0; + Max_Num_Records = MAX_NUM_RECORDS; + + wc_ram_size = 0; + wc_ram_frame = -1; + current_heap_size = 0; + + /* heap allocation tree */ + heap_allocation_call_tree_max_size = MAX_NUM_RECORDS; + if ( heap_allocation_call_tree == NULL ) + { + heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) ); + memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + heap_allocation_call_tree_size = 0; + + /* wc intra-frame heap */ + max_items_wc_intra_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_intra_frame_heap == NULL ) + { + list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) ); + memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + n_items_wc_intra_frame_heap = 0; + size_wc_intra_frame_heap = 0; + location_wc_intra_frame_heap = -1; + + /* current inter-frame heap */ + max_items_current_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_current_inter_frame_heap == NULL ) + { + list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) ); + memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) ); + } + n_items_current_inter_frame_heap = 0; + size_current_inter_frame_heap = 0; + + /* wc inter-frame heap */ + max_items_wc_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_inter_frame_heap == NULL ) + { + list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) ); + memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + n_items_wc_inter_frame_heap = 0; + size_wc_inter_frame_heap = 0; + location_wc_inter_frame_heap = -1; + +#ifdef MEM_COUNT_DETAILS + /* Check, if the .csv file has already been opened */ + if ( fid_csv_filename == NULL ) + { + fid_csv_filename = fopen( csv_filename, "wb" ); + + if ( fid_csv_filename == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); + exit( -1 ); + } + } + else + { + /* reset file */ + rewind( fid_csv_filename ); + } +#endif + + return; +} + +/*-------------------------------------------------------------------* + * reset_stack() + * + * Reset stack pointer + *--------------------------------------------------------------------*/ + +void reset_stack( void ) +{ + int16_t something; + + /* initialize/reset stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + return; +} + +/*-------------------------------------------------------------------* + * push_stack() + * + * Check the current stack pointer and update the maximum stack pointer, if new maximum found. + *--------------------------------------------------------------------*/ + +int push_stack( const char *filename, const char *fctname ) +{ + int16_t something; + int32_t current_stack_size; + + ptr_current_stack = &something; + + (void) *filename; /* to avoid compilation warning */ + + /* Is there room to save the caller's information? */ + if ( current_calls >= MAX_RECORDABLE_CALLS ) + { /* No */ + fprintf( stderr, "No more room to store call stack info. Please increase MAX_RECORDABLE_CALLS" ); + exit( -1 ); + } + + /* Valid Function Name? */ + if ( fctname[0] == 0 ) + { /* No */ + fprintf( stderr, "Invalid function name for call stack info." ); + exit( -1 ); + } + + /* Save the Name of the Calling Function in the Table */ + strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH ); + stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */ + + /* Save the Stack Pointer */ + stack_callers[0][current_calls].stack_ptr = ptr_current_stack; + + /* Increase Stack Calling Tree Level */ + current_calls++; + + /* Is this the First Time or the Worst Case? */ + if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL ) + { /* Yes */ + /* Save Info about it */ + ptr_max_stack = ptr_current_stack; + + wc_stack_frame = update_cnt; /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */ + strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); + location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; + + /* Save Call Tree */ + memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls ); + + /* Terminate the List (Unless Full) */ + if ( current_calls < MAX_RECORDABLE_CALLS ) + { + stack_callers[1][current_calls].function_name[0] = 0; + } + } + + /* Check, if This is the New Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + + if ( current_stack_size < 0 ) + { + /* prevent negative stack size */ + current_stack_size = 0; + } + + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + return 0 /* for Now */; +} + +/*-------------------------------------------------------------------* + * pop_stack() + * + * Remove stack caller entry from the list + *--------------------------------------------------------------------*/ + +int pop_stack( const char *filename, const char *fctname ) +{ + caller_info *caller_info_ptr; + + (void) *filename; /* to avoid compilation warning */ + + /* Decrease Stack Calling */ + current_calls--; + + /* Get Pointer to Caller Information */ + caller_info_ptr = &stack_callers[0][current_calls]; + + /* Check, if Names Match */ + if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 ) + { + fprintf( stderr, "Invalid usage of pop_stack()" ); + exit( -1 ); + } + + /* Erase Entry */ + caller_info_ptr->function_name[0] = 0; + + /* Retrieve previous stack pointer */ + if ( current_calls == 0 ) + { + ptr_current_stack = ptr_base_stack; + } + else + { + ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr; + } + + return 0 /* for Now */; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * print_stack_call_tree() + * + * Print detailed information about worst-case stack usage + *--------------------------------------------------------------------*/ + +static void print_stack_call_tree( void ) +{ + caller_info *caller_info_ptr; + int call_level; + char fctname[MAX_FUNCTION_NAME_LENGTH + 1]; + + fprintf( stdout, "\nList of functions when maximum stack size is reached:\n\n" ); + + caller_info_ptr = &stack_callers[1][0]; + for ( call_level = 0; call_level < MAX_RECORDABLE_CALLS; call_level++ ) + { + /* Done? */ + if ( caller_info_ptr->function_name[0] == 0 ) + { + break; + } + + /* Print Name */ + strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH ); + strcat( fctname, "()" ); + fprintf( stdout, "%-42s", fctname ); + + /* Print Stack Usage (Based on Difference) */ + if ( call_level != 0 ) + { + fprintf( stdout, "%lu %s\n", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + else + { + fprintf( stdout, "%lu %s\n", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + + /* Advance */ + caller_info_ptr++; + } + + fprintf( stdout, "\n" ); + + return; +} +#endif + + +/*-------------------------------------------------------------------* + * mem_alloc() + * + * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc. + * Finally, it allocates physical memory using malloc() + * The function also updates worst-case heap size and worst-case RAM size + *--------------------------------------------------------------------*/ + +void *mem_alloc( + const char *func_name, + int func_lineno, + size_t size, + char *size_str /* the first char indicates m-alloc or c-alloc */ ) +{ + int index_record; + int32_t current_stack_size; + unsigned long hash; + allocator_record *ptr_record; + + if ( size == 0 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Size of Zero not Supported" ); + exit( -1 ); + } + + /* Search for an existing record (that has been de-allocated before) */ + index_record = 0; + while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL ) + { + if ( ptr_record->frame_allocated == -1 ) + { + break; + } + else + { + index_record++; + } + } + + /* Create new record */ + if ( ptr_record == NULL ) + { + if ( Num_Records >= Max_Num_Records ) + { + /* There is no room for a new record -> reallocate memory */ + Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP; + allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) ); + } + + ptr_record = &( allocation_list[Num_Records] ); + + /* Initialize new record */ + ptr_record->hash = hash; + ptr_record->noccurances = 0; + ptr_record->total_block_size = 0; + ptr_record->total_used_size = 0; + ptr_record->frame_allocated = -1; + ptr_record->OOB_Flag = 0; + ptr_record->wc_heap_size_intra_frame = -1; + ptr_record->wc_heap_size_inter_frame = -1; + + index_record = Num_Records; + Num_Records++; + } + + /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */ + ptr_record->block_ptr = mem_alloc_block( size, size_str ); + + if ( ptr_record->block_ptr == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Cannot Allocate Memory!" ); + exit( -1 ); + } + + /* Save all auxiliary information about the memory block */ + strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH ); + ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */ + ptr_record->params[MAX_PARAMS_LENGTH] = '\0'; + ptr_record->lineno = func_lineno; + ptr_record->block_size = size; + ptr_record->total_block_size += size; + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory allocation record to the .csv file */ + fprintf( fid_csv_filename, "A,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + if ( ptr_record->frame_allocated != -1 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Attempt to Allocate the Same Memory Block with Freeing it First!" ); + exit( -1 ); + } + + ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */ + + /* Update Heap Size in the current frame */ + current_heap_size += ptr_record->block_size; + + /* Check, if this is the new Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */ + heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record; + + return ptr_record->block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_alloc_block() + * + * Physical allocation of memory using malloc(). Appends 'signature' before and after the block, + * pre-fills memory block with magic value + *--------------------------------------------------------------------*/ + +static void *mem_alloc_block( size_t size, const char *size_str ) +{ + size_t rounded_size; + void *block_ptr; + char *tmp_ptr; + size_t n, f; + int32_t fill_value; + int32_t *ptr32; + int32_t mask, temp; + + /* Round Up Block Size */ + rounded_size = ROUND_BLOCK_SIZE( size ); + + /* Allocate memory using the standard malloc() by adding room for Signature Values */ + block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 ); + + if ( block_ptr == NULL ) + { + return NULL; + } + + /* Add Signature Before the Start of the Block */ + ptr32 = (int32_t *) block_ptr; + n = N_32BITS_BLOCKS; + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Fill Memory Block with Magic Value or 0 */ + fill_value = MAGIC_VALUE_USED; + if ( IS_CALLOC( size_str ) ) + { + fill_value = 0x00000000; + } + n = size / sizeof( int32_t ); + while ( n-- ) + { + *ptr32++ = fill_value; + } + + /* Fill the Reminder of the Memory Block - After Rounding */ + n = rounded_size - size; + f = n % sizeof( int32_t ); + if ( f != 0 ) + { + /* when filling with '0' need to adapt the magic value */ + /* shift by [1->24, 2->16, 3->8] */ + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */ + temp = MAGIC_VALUE_OOB & mask; + if ( fill_value != 0x0 ) + { /* for malloc merge fill value */ + temp += ( ~mask ) & MAGIC_VALUE_USED; + } /* for calloc the code in (1) above already introduces zeros */ + *ptr32++ = temp; + } + n /= sizeof( int32_t ); + n += N_32BITS_BLOCKS; + + /* Add Signature After the End of Block */ + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */ + tmp_ptr = (char *) block_ptr; + tmp_ptr += BLOCK_ROUNDING; + block_ptr = (void *) tmp_ptr; + + return block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_set_usage() + * + * Calculates actual usage of memory block by checking the magic value that was used to pre-fill + * each memory block during its allocation + *--------------------------------------------------------------------*/ + +static int mem_set_usage( allocator_record *record_ptr ) +{ + int total_bytes_used; + + size_t n; + int32_t *ptr32; + char *ptr8; + size_t total_bytes; + int32_t fill_value; + + fill_value = MAGIC_VALUE_USED; + if ( ( record_ptr->params[0] ) == 'c' ) + { + fill_value = 0x00000000; + } + + total_bytes = record_ptr->block_size; + + /* Check 4 bytes at a time */ + ptr32 = (int32_t *) record_ptr->block_ptr; + total_bytes_used = 0; + for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr32++ != fill_value ) + { + total_bytes_used += sizeof( int32_t ); + } + } + + /* Check remaining bytes (If Applicable) 1 byte at a time */ + ptr8 = (char *) ptr32; + for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr8++ != (char) fill_value ) + { + total_bytes_used++; + } + + /* Update Value */ + fill_value >>= 8; + } + + return total_bytes_used; +} + +/*-------------------------------------------------------------------* + * mem_check_OOB() + * + * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value + * taht has been added before and after the memory block during its allocation + *--------------------------------------------------------------------*/ + +static unsigned int mem_check_OOB( allocator_record *record_ptr ) +{ + int32_t *ptr32; + unsigned int OOB_Flag = 0x0; + int32_t mask; + size_t i; + int f; + + ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS; + + /* Check the Signature at the Beginning of Memory Block */ + i = N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_START; + } + } while ( --i ); + + /* Advance to End (Snap to lowest 32 Bits) */ + ptr32 += record_ptr->block_size / sizeof( int32_t ); + + /* Calculate Unused Space That has been added to get to the rounded Block Size */ + i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size; + + /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */ + f = i % sizeof( int32_t ); + if ( f != 0 ) + { + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); + if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask ) + { + OOB_Flag |= OOB_END; + } + } + + /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */ + i /= sizeof( int32_t ); + i += N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_END; + } + } while ( --i ); + + return OOB_Flag; +} + +/*-------------------------------------------------------------------* + * malloc_hash() + * + * Calculate hash from function name, line number and malloc size + *--------------------------------------------------------------------*/ + +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ) +{ + unsigned long hash = 5381; + const char *ptr_str; + + ptr_str = func_name; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */ + + ptr_str = size_str; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + return hash; +} + +/*-------------------------------------------------------------------* + * get_mem_record() + * + * Search for memory record in the internal list, return NULL if not found + * Start from index_record + *--------------------------------------------------------------------*/ + +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ) +{ + int i; + + if ( *index_record < 0 || *index_record > Num_Records ) + { + return NULL; + } + + /* calculate hash */ + *hash = malloc_hash( func_name, func_lineno, size_str ); + + for ( i = *index_record; i < Num_Records; i++ ) + { + /* check, if memory block is not allocated at the moment and the hash matches */ + if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash ) + { + *index_record = i; + return &( allocation_list[i] ); + } + } + + /* not found */ + *index_record = -1; + return NULL; +} + + +/*-------------------------------------------------------------------* + * mem_free() + * + * This function de-allocatesd the memory block and frees the mphysical memory with free(). + * It also updates actual and average usage of the memory block. + * + * Note: The record is not removed from the list and may be reused later on in mem_alloc()! + *--------------------------------------------------------------------*/ + +void mem_free( const char *func_name, int func_lineno, void *ptr ) +{ + int i, index_record; + char *tmp_ptr; + allocator_record *ptr_record; + + /* Search for the Block Pointer in the List */ + ptr_record = NULL; + index_record = -1; + for ( i = 0; i < Num_Records; i++ ) + { + if ( ptr == allocation_list[i].block_ptr ) + { /* Yes, Found it */ + ptr_record = &( allocation_list[i] ); + index_record = i; + break; + } + } + + if ( ptr_record == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Unable to Find Record Corresponding to the Allocated Memory Block!" ); + exit( -1 ); + } + + /* Update the Heap Size */ + current_heap_size -= ptr_record->block_size; + + /* Calculate the Actual Usage of the Memory Block (Look for Signature) */ + ptr_record->total_used_size += mem_set_usage( ptr_record ); + + /* Check, if Out-Of-Bounds Access has been Detected */ + ptr_record->OOB_Flag = mem_check_OOB( ptr_record ); + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory de-allocation record to the .csv file */ + fprintf( fid_csv_filename, "D,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + /* De-Allocate Memory Block */ + tmp_ptr = (char *) ptr; + tmp_ptr -= BLOCK_ROUNDING; + ptr = (void *) tmp_ptr; + free( ptr ); + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record; + + /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */ + ptr_record->block_ptr = NULL; + + return; +} + + +/*-------------------------------------------------------------------* + * update_mem() + * + * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory. + *--------------------------------------------------------------------*/ + +void update_mem( void ) +{ + int i, j, flag_alloc = -1, i_record; + int size_current_intra_frame_heap; + int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap; + allocator_record *ptr_record; + + /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */ + n_items_current_intra_frame_heap = 0; + size_current_intra_frame_heap = 0; + for ( i = 0; i < heap_allocation_call_tree_size; i++ ) + { + /* get the record */ + i_record = heap_allocation_call_tree[i]; + + if ( i_record > 0 ) + { + flag_alloc = 1; + } + else if ( i_record < 0 ) + { + flag_alloc = 0; + i_record = -i_record; + } + ptr_record = &( allocation_list[i_record] ); + + if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL ) + { + /* intra-frame heap memory */ + if ( list_current_intra_frame_heap == NULL ) + { + list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) ); + memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) ); + } + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record; + size_current_intra_frame_heap += ptr_record->block_size; + + /* no need to re-size the list -> the initially allocated size should be large enough */ + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) ); + n_items_current_intra_frame_heap--; + size_current_intra_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + else + { + /* inter-frame heap memory */ + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) ); + } + + list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record; + size_current_inter_frame_heap += ptr_record->block_size; + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) ); + n_items_current_inter_frame_heap--; + size_current_inter_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + } + + /* check, if this is the new worst-case for intra-frame heap memory */ + if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) + { + if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) + { + /* resize the list, if needed */ + max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); + n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; + size_wc_intra_frame_heap = size_current_intra_frame_heap; + location_wc_intra_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + i_record = list_wc_intra_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; + } + } + + /* check, if this is the new worst-case for inter-frame heap memory */ + if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) + { + if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); + n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; + size_wc_inter_frame_heap = size_current_inter_frame_heap; + location_wc_inter_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + i_record = list_wc_inter_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; + } + } + + /* reset heap allocation call tree */ + heap_allocation_call_tree_size = 0; + + /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */ + if ( list_current_intra_frame_heap ) + { + free( list_current_intra_frame_heap ); + } + + return; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * subst() + * + * Substitute character in string + *--------------------------------------------------------------------*/ + +static void subst( char *s, char from, char to ) +{ + while ( *s == from ) + { + *s++ = to; + } + + return; +} + + +/*-------------------------------------------------------------------* + * mem_count_summary() + * + * Print detailed (per-item) information about heap memory usage + *--------------------------------------------------------------------*/ + +static void mem_count_summary( void ) +{ + int i, j, index, index_record; + size_t length; + char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10]; + allocator_record *ptr_record, *ptr; + + /* Prepare format string */ + sprintf( format_str, "%%-%ds %%5s %%6s %%-%ds %%20s %%6s ", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH ); + + if ( n_items_wc_intra_frame_heap > 0 ) + { + /* Intra-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum intra-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + + ptr_record = &( allocation_list[index_record] ); + for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ ) + { + index = list_wc_intra_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame ) + { + ptr_record->noccurances++; + list_wc_intra_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Maximum Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + /* Inter-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum inter-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + ptr_record = &( allocation_list[index_record] ); + ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */ + for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ ) + { + index = list_wc_inter_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame ) + { + ptr_record->noccurances++; + list_wc_inter_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Memory Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + return; +} + +#endif + +/*-------------------------------------------------------------------* + * print_mem() + * + * Print information about ROM and RAM memory usage + *--------------------------------------------------------------------*/ + +void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) +{ + int i, nElem; + + fprintf( stdout, "\n\n --- Memory usage --- \n\n" ); + + if ( Const_Data_PROM_Table != NULL ) + { + nElem = 0; + while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, "" ) != 0 ) + nElem++; + + for ( i = 0; i < nElem; i++ ) + { + fprintf( stdout, "Program ROM size (%s): %d instruction words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); + } + + for ( i = 0; i < nElem; i++ ) + { + if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL ) + { + fprintf( stdout, "Error: Cannot retrieve or calculate Table ROM size of (%s)!\n", Const_Data_PROM_Table[i].file_spec ); + } + + fprintf( stdout, "Table ROM (const data) size (%s): %d %s\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + } + else + { + fprintf( stdout, "Program ROM size: not available\n" ); + fprintf( stdout, "Table ROM (const data) size: not available\n" ); + } + + if ( wc_ram_size > 0 ) + { + fprintf( stdout, "Maximum RAM (stack + heap) size: %d %s in frame %d\n", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame ); + } + else + { + fprintf( stdout, "Maximum RAM (stack + heap) size: not available\n" ); + } + + /* check, if the stack is empty */ + if ( ptr_current_stack != ptr_base_stack ) + { + fprintf( stderr, "Warning: Stack is not empty.\n" ); + } + + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + fprintf( stdout, "Maximum stack size: %lu %s in frame %d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], + wc_stack_frame ); + } + else + { + fprintf( stdout, "Maximum stack size: not available\n" ); + } + + /* last update of intra-frame memory and inter-frame memory, if needed */ + if ( heap_allocation_call_tree_size > 0 ) + { + update_mem(); + } + + /* check, if all memory blocks have been deallocated (freed) */ + for ( i = 0; i < Num_Records; i++ ) + { + if ( allocation_list[i].block_ptr != NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", allocation_list[i].name, allocation_list[i].lineno, "Error: Memory Block has not been De-Allocated with free()!" ); + exit( -1 ); + } + } + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Maximum intra-frame heap size: %d %s in frame %d\n", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap ); + } + else + { + fprintf( stdout, "Maximum intra-frame heap size: 0\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + fprintf( stdout, "Maximum inter-frame heap size: %d %s in frame %d\n", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap ); + } + else + { + fprintf( stdout, "Maximum inter-frame heap size: 0\n" ); + } + +#ifdef MEM_COUNT_DETAILS + /* Print detailed information about worst-case stack usage */ + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + print_stack_call_tree(); + } + + /* Print detailed information about worst-case heap usage */ + mem_count_summary(); +#endif + + if ( Stat_Cnt_Size > 0 ) + { + fprintf( stdout, "\nNote: 1 word = %d bits\n", 8 << Stat_Cnt_Size ); + fprintf( stdout, "This is an optimistic estimate of memory consumption assuming that each variable type is stored with sizeof(type) bits\n" ); + } + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Intra-frame heap memory is allocated and de-allocated in the same frame\n" ); + } + + /* De-allocate list of heap memory blocks */ + if ( allocation_list != NULL ) + { + free( allocation_list ); + } + + /* De-allocate heap allocation call tree */ + if ( heap_allocation_call_tree != NULL ) + { + free( heap_allocation_call_tree ); + } + + /* De-allocate intra-frame and inter-frame heap lists */ + if ( list_wc_intra_frame_heap != NULL ) + { + free( list_wc_intra_frame_heap ); + } + + if ( list_current_inter_frame_heap != NULL ) + { + free( list_current_inter_frame_heap ); + } + + if ( list_wc_inter_frame_heap != NULL ) + { + free( list_wc_inter_frame_heap ); + } + +#ifdef MEM_COUNT_DETAILS + if ( fid_csv_filename != NULL ) + { + fclose( fid_csv_filename ); + } +#endif + + return; +} + +#endif /* WMOPS */ + +#ifndef WMOPS +int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ +#endif diff --git a/lib_debug/wmops.h b/lib_debug/wmc_auto.h similarity index 62% rename from lib_debug/wmops.h rename to lib_debug/wmc_auto.h index f18c990ed5ba33a0117a4c20c9686476d5e77094..9e20a4c7c8162126ead7cf45fbc8aab5f506c435 100644 --- a/lib_debug/wmops.h +++ b/lib_debug/wmc_auto.h @@ -1,147 +1,43 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ +/* + * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * + * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, + * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file + * or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". + * + * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor + * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software + * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. + * + * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) + */ #ifndef WMOPS_H #define WMOPS_H -#include -#include "options.h" - - -/*------------------------------------------------------------------------------------------* - * Memory calculation tool - *------------------------------------------------------------------------------------------*/ - -#ifdef WMOPS - -#ifdef _MSC_VER -#pragma warning( disable : 4033 ) -#pragma warning( disable : 4702 ) -#pragma warning( disable : 4709 ) +#ifndef EXIT_FAILURE +#include /* stdlib is needed for exit() */ #endif -extern int Const_Data_Size_rom_enc( void ); -extern int Const_Data_Size_rom_com( void ); -extern int Const_Data_Size_rom_dec( void ); -extern int Const_Data_Size_ivas_rom_enc( void ); -extern int Const_Data_Size_ivas_rom_com( void ); -extern int Const_Data_Size_ivas_rom_dec( void ); -extern int Const_Data_Size_ivas_spar_rom_com( void ); -extern int Const_Data_Size_ivas_rom_binauralRen( void ); -extern int Const_Data_Size_ivas_rom_TdBinauralR( void ); -extern int Const_Data_Size_ivas_rom_binaural_cr( void ); - -int push_stack( const char *filename, const char *fctname ); -int pop_stack( const char *filename, const char *fctname ); -void reset_stack( void ); -void print_stack_call_tree( void ); +#ifndef EOF +#include /* stdio is needed for fprintf() */ +#endif -#else - -#define push_stack( file, fct ) -#define pop_stack( file, fct ) -#define reset_stack() -#define print_mem_enc( x ) -#define print_mem_dec( x ) -#define print_stack_call_tree() +/* To Prevent "warning: '$' in identifier or number" message under GCC */ +#ifdef __GNUC__ +#pragma GCC system_header #endif -/******************************************************************************************/ - /* Real-time relationships */ #define FRAMES_PER_SECOND 50.0 #define MILLION_CYCLES 1e6 +#define WMOPS_BOOST_FAC ( 1.0f ) /* scaling factor for equalizing the difference between automatic and manual instrumentation */ +#define FAC ( FRAMES_PER_SECOND / MILLION_CYCLES * WMOPS_BOOST_FAC ) +#define NUM_INST 20 /* Total number of instruction types (in enum below) */ -#define WMC_AUTO_WEIGHTING_FACT 0.91f /* constant to equalize difference between automatic and manual instrumentation */ -#define WMOPS_BOOST_FAC ( 1.0f / WMC_AUTO_WEIGHTING_FACT ) /* complexity scaling factor for manually instrumented code */ - -#define FAC ( FRAMES_PER_SECOND / MILLION_CYCLES * WMOPS_BOOST_FAC ) - -/******************************************************************************************/ - - -#define FLC_MSU( c ) MAC( c ) /* multiply and subtract is currently seen as MAC operation */ -#define FLC_MAX( c ) MISC( c ) /* max() is seen as MISC like abs() */ -#define FLC_MIN( c ) MISC( c ) /* min() is seen as MISC like abs() */ -#define FLC_NEG( c ) ADD( c ) /* negation is seen as addion: a = 0 - a */ -#define FLC_CAST( c ) /* type conversion is costfree for the moment, but who knows it for the future ? */ -#define FLC_INLINE_FUNC( c ) /* inline function calls are costfree, parameters/retval are currently not counted */ - /* example: FLC_INLINE_FUNC(3); SET_FLOAT(ptr,value,num); */ -#define FLC_ATAN2( c ) \ - DIV( c ); \ - TRANS( c ) /* atan2 is curently seen as division followed by atan */ - -/* inline function for memset in combination with float pointer */ -#define SET_FLOAT( ptr, value, num ) \ - { \ - int i; \ - LOOP( 1 ); \ - MOVE( num ); \ - for ( i = 0; i < num; i++ ) \ - { \ - ptr[i] = value; \ - } \ - } - -/* inline function for memset in combination with integer */ -#define SET_INT( ptr, value, num ) \ - { \ - int i; \ - LOOP( 1 ); \ - MOVE( num ); \ - for ( i = 0; i < num; i++ ) \ - { \ - ptr[i] = value; \ - } \ - } #ifdef WMOPS -#ifndef WMOPS_DETAIL -#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __func__ ) /* Define stack counting function for WMC Tool */ - -#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __func__ ) /* Define stack counting function for WMC Tool */ -#else -#define STACK_DEPTH_FCT_CALL ( push_wmops( __func__ ), push_stack( __FILE__, __func__ ) ) /* Define stack counting function for WMC Tool */ - -#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __func__ ) ) /* Define stack counting function for WMC Tool */ -#endif - -#define ENABLE_WMOPS 1 /* Only for the WMC_Tool */ -#define ENABLE_TREE 0 /* Call tree may be activated by setting this flag to 1 */ -#define NUM_INST 20 /* Total number of instruction types (in enum below) */ - -#define FLC_OPS_COND if ( ops_cnt_activ > 0 ) - enum instructions { _ADD, @@ -165,31 +61,6 @@ enum instructions _LOG, _MISC }; -enum flc_fields -{ - FLC_NOP = 0, - FLC_ADD, - FLC_MULT, - FLC_MAC, - FLC_MOVE, - FLC_STORE, - FLC_LOGIC, - FLC_SHIFT, - FLC_BRANCH, - FLC_DIV, - FLC_SQRT, - FLC_TRANS, - FLC_FUNC, - FLC_LOOP, - FLC_INDIRECT, - FLC_PTR_INIT, - FLC_MISC, - FLC_TEST, - FLC_POWER, - FLC_LOG, - FLC_OPEND -}; - #define _ADD_C 1 #define _ABS_C 1 @@ -235,7 +106,6 @@ enum flc_fields #define ADD( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _ADD_C * ( x ) ); \ inst_cnt[_ADD] += ( x ); \ @@ -251,7 +121,6 @@ enum flc_fields } #define ABS( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _ABS_C * ( x ) ); \ inst_cnt[_ABS] += ( x ); \ @@ -267,7 +136,6 @@ enum flc_fields } #define MULT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _MULT_C * ( x ) ); \ inst_cnt[_MULT] += ( x ); \ @@ -283,7 +151,6 @@ enum flc_fields } #define MAC( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _MAC_C * ( x ) ); \ inst_cnt[_MAC] += ( x ); \ @@ -299,7 +166,6 @@ enum flc_fields } #define MOVE( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _MOVE_C * ( x ) ); \ inst_cnt[_MOVE] += ( x ); \ @@ -315,7 +181,6 @@ enum flc_fields } #define STORE( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _STORE_C * ( x ) ); \ inst_cnt[_STORE] += ( x ); \ @@ -331,7 +196,6 @@ enum flc_fields } #define LOGIC( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _LOGIC_C * ( x ) ); \ inst_cnt[_LOGIC] += ( x ); \ @@ -347,7 +211,6 @@ enum flc_fields } #define SHIFT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _SHIFT_C * ( x ) ); \ inst_cnt[_SHIFT] += ( x ); \ @@ -363,7 +226,6 @@ enum flc_fields } #define BRANCH( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _BRANCH_C * ( x ) ); \ inst_cnt[_BRANCH] += ( x ); \ @@ -379,7 +241,6 @@ enum flc_fields } #define DIV( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _DIV_C * ( x ) ); \ inst_cnt[_DIV] += ( x ); \ @@ -395,7 +256,6 @@ enum flc_fields } #define SQRT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _SQRT_C * ( x ) ); \ inst_cnt[_SQRT] += ( x ); \ @@ -411,7 +271,6 @@ enum flc_fields } #define TRANS( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _TRANS_C * ( x ) ); \ inst_cnt[_TRANS] += ( x ); \ @@ -427,7 +286,6 @@ enum flc_fields } #define LOOP( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _LOOP_C * ( x ) ); \ inst_cnt[_LOOP] += ( x ); \ @@ -443,7 +301,6 @@ enum flc_fields } #define INDIRECT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _INDIRECT_C * ( x ) ); \ inst_cnt[_INDIRECT] += ( x ); \ @@ -459,7 +316,6 @@ enum flc_fields } #define PTR_INIT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _PTR_INIT_C * ( x ) ); \ inst_cnt[_PTR_INIT] += ( x ); \ @@ -475,7 +331,6 @@ enum flc_fields } #define TEST( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _TEST_C * ( x ) ); \ inst_cnt[_TEST] += ( x ); \ @@ -491,7 +346,6 @@ enum flc_fields } #define POWER( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _POWER_C * ( x ) ); \ inst_cnt[_POWER] += ( x ); \ @@ -507,7 +361,6 @@ enum flc_fields } #define LOG( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _LOG_C * ( x ) ); \ inst_cnt[_LOG] += ( x ); \ @@ -523,7 +376,6 @@ enum flc_fields } #define MISC( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _MISC_C * ( x ) ); \ inst_cnt[_MISC] += ( x ); \ @@ -540,7 +392,6 @@ enum flc_fields #define FUNC( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \ inst_cnt[_FUNC]++; \ @@ -558,7 +409,6 @@ enum flc_fields #define DADD( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _ADD_C * ( x ) ); \ inst_cnt[_ADD] += ( x ); \ @@ -574,7 +424,6 @@ enum flc_fields } #define DMULT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _MULT_C * ( x ) ); \ inst_cnt[_MULT] += ( x ); \ @@ -590,7 +439,6 @@ enum flc_fields } #define DMAC( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _MAC_C * ( x ) ); \ inst_cnt[_MAC] += ( x ); \ @@ -606,7 +454,6 @@ enum flc_fields } #define DMOVE( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _MOVE_C * ( x ) ); \ inst_cnt[_MOVE] += ( x ); \ @@ -622,7 +469,6 @@ enum flc_fields } #define DSTORE( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _STORE_C * ( x ) ); \ inst_cnt[_STORE] += ( x ); \ @@ -638,7 +484,6 @@ enum flc_fields } #define DLOGIC( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \ inst_cnt[_LOGIC] += ( x ); \ @@ -654,7 +499,6 @@ enum flc_fields } #define DSHIFT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \ inst_cnt[_SHIFT] += ( x ); \ @@ -670,7 +514,6 @@ enum flc_fields } #define DDIV( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _DIV_C * ( x ) ); \ inst_cnt[_DIV] += ( x ); \ @@ -686,7 +529,6 @@ enum flc_fields } #define DSQRT( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _SQRT_C * ( x ) ); \ inst_cnt[_SQRT] += ( x ); \ @@ -702,7 +544,6 @@ enum flc_fields } #define DTRANS( x ) \ { \ - FLC_OPS_COND \ { \ ops_cnt += ( 2 * _TRANS_C * ( x ) ); \ inst_cnt[_TRANS] += ( x ); \ @@ -725,19 +566,18 @@ extern int ops_cnt_activ; void reset_wmops( void ); void push_wmops( const char *label ); void pop_wmops( void ); -void wmops_sub_start( const char *label ); -void wmops_sub_end( void ); void update_wmops( void ); +void update_mem( void ); void print_wmops( void ); #else /* WMOPS counting disabled */ #define reset_wmops() -#define push_wmops( x ) -#define pop_wmops() -#define wmops_sub_start( x ) -#define wmops_sub_end() -#define update_wmops() +extern int cntr_push_pop; +#define push_wmops( x ) ( cntr_push_pop++ ) +#define pop_wmops() ( cntr_push_pop-- ) +#define update_wmops() ( assert( cntr_push_pop == 0 ) ) +#define update_mem() #define print_wmops() #define ADD( x ) @@ -774,4 +614,426 @@ void print_wmops( void ); #endif +/* mac & msu (Non Instrumented Versions) */ +#ifndef mac +#define mac( a, b, c ) ( ( a ) + ( b ) * ( c ) ) +#endif +#ifndef mac +#define msu( a, b, c ) ( ( a ) - ( b ) * ( c ) ) +#endif + +#ifndef WMOPS +/* DESACTIVATE the Counting Mechanism */ +#define OP_COUNT_( op, n ) + +/* DESACTIVATE Operation Counter Wrappers */ +#define OP_COUNT_WRAPPER1_( op, val ) ( val ) +#define OP_COUNT_WRAPPER2_( expr ) +#define OP_COUNT_WRAPPER3_( op, expr ) expr + +/* DESACTIVATE Logical & Ternary Operators */ +#define __ +#define _ + +#else + +/* '*ops_cnt_ptr' is Used to Avoid: "warning: operation on 'ops_cnt' may be undefined" with Cygwin gcc Compiler */ +static double *ops_cnt_ptr = &ops_cnt; +#define OP_COUNT_( op, x ) ( *ops_cnt_ptr += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) ) + +/******************************************************************/ +/* NOTES: */ +/* The 'wmc_flag_' flag is global to avoid declaration in every */ +/* function and 'static' to avoid clashing with other modules */ +/* that include this header file. */ +/* */ +/* The declarations of 'wmc_flag_' and 'wops_' in this header */ +/* file prevent the addition of a 'C' file to the Project. */ +/******************************************************************/ + +/* General Purpose Global Flag */ +static int wmc_flag_ = 0; + +/* Operation Counter Wrappers */ +#define OP_COUNT_WRAPPER1_( op, val ) ( op, val ) +#define OP_COUNT_WRAPPER2_( expr ) \ + if ( expr, 0 ) \ + ; \ + else +#define OP_COUNT_WRAPPER3_( op, expr ) \ + if ( op, 0 ) \ + ; \ + else \ + expr + +#endif + +/* Define all Macros without '{' & '}' (None of these should be called externally!) */ +#define ABS_( x ) OP_COUNT_( _ABS, ( x ) / WMOPS_BOOST_FAC ) +#define ADD_( x ) OP_COUNT_( _ADD, ( x ) / WMOPS_BOOST_FAC ) +#define MULT_( x ) OP_COUNT_( _MULT, ( x ) / WMOPS_BOOST_FAC ) +#define MAC_( x ) OP_COUNT_( _MAC, ( x ) / WMOPS_BOOST_FAC ) +#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) / WMOPS_BOOST_FAC ) +#define STORE_( x ) OP_COUNT_( _STORE, ( x ) / WMOPS_BOOST_FAC ) +#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) / WMOPS_BOOST_FAC ) +#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) / WMOPS_BOOST_FAC ) +#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) / WMOPS_BOOST_FAC ) +#define DIV_( x ) OP_COUNT_( _DIV, ( x ) / WMOPS_BOOST_FAC ) +#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) / WMOPS_BOOST_FAC ) +#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) / WMOPS_BOOST_FAC ) +#define POWER_( x ) TRANS_( x ) +#define LOG_( x ) TRANS_( x ) +#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) / WMOPS_BOOST_FAC ) +#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) / WMOPS_BOOST_FAC ) +#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) / WMOPS_BOOST_FAC ) +#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) / WMOPS_BOOST_FAC ), OP_COUNT_( _FUNC, 1 ) ) +#define MISC_( x ) ABS_( x ) + +/* Math Operations */ +#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs ) +#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs ) +#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs ) +#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor ) +#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt ) +#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow ) +#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp ) +#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log ) +#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 ) +#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos ) +#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin ) +#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan ) +#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos ) +#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin ) +#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan ) +#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 ) +#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh ) +#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh ) +#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh ) +#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod ) +/* these macros use any local macros already defined */ +/* min/max and their Variants */ +#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) ) +#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) ) +#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) ) +#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) ) +#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) ) +#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) ) +/* Square and its Variants */ +#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) ) +#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) ) +#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) ) +#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) ) +#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) ) +#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) ) +/* Sign and its Variants */ +#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) ) +#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) ) +#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) ) +/* Square Root and its Variants */ +#define sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf( ( x ) ) ) +/* Invert Square Root and its Variants */ +#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) ) +/* Others */ +#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) ) +#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) ) +/* The 'wmc_flag_=wmc_flag_' is Used to Avoid: "warning: left-hand operand of comma expression has no effect" + with Cygwin gcc Compiler */ +#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) ) +#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) ) +#define _squant_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _squant( ( x ) ) ) +/* Set Min/Max */ +#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) ) +#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) ) +/* mac & msu (Instrumented Versions) */ +#define mac_( a, b, c ) OP_COUNT_WRAPPER1_( MAC_( 1 ), mac( a, b, c ) ) +#define msu_( a, b, c ) OP_COUNT_WRAPPER1_( MAC_( 1 ), msu( a, b, c ) ) + +/* Functions */ +#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name ) + +/* Logical Operators */ +#ifndef __ +#define __ ( BRANCH_( 1 ), 1 ) && +#endif + +/* Ternary Operators (? and :) */ +#ifndef _ +#define _ ( BRANCH_( 1 ), 0 ) ? 0: #endif + +/* Flow Control keywords */ +#define if_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + if +#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for +#define while_( c ) \ + while \ + OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra "()" if ',' encountered */ +#define do_ \ + do \ + { +#define _while \ + BRANCH_( 1 ); \ + } \ + while + +#define goto_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + goto +#define break_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + break +#define continue_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + continue +#define return_ \ + OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \ + return + +#define switch_ \ + OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \ + switch +#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 ); + +#ifdef WMOPS + +#define ACC 2 +#define MUL 1 + +/* Counting Function (should not be called externally!) */ +static void wops_( const char *ops ) +{ + char lm = 0; /* lm: Last Operation is Math */ + static char lo = 0; /* Last Operation */ + + void ( *fct )( const char *ops ) = wops_; + +st: + while ( *ops != '\0' ) + { + switch ( *ops++ ) + { + int cnt; + case '-': + for ( cnt = 0; ops[cnt] == '>'; cnt++ ) + ; + if ( cnt & 1 ) + goto ind; + case '+': + lm = 2; + if ( lo & MUL ) + { + MULT_( -1 ); + MAC_( 1 ); + break; + } + lo = ACC << 2; + case 'U': + case 'D': + ADD_( 1 ); + break; + case '*': + lm = 2; + if ( lo & ACC ) + { + ADD_( -1 ); + MAC_( 1 ); + break; + } + lo = MUL << 2; + MULT_( 1 ); + break; + case '/': + case '%': + lm = 2; + DIV_( 1 ); + break; + case '&': + case '|': + case '^': + lm = 2; + case '~': + LOGIC_( 1 ); + break; + case '<': + case '>': + if ( *ops != ops[-1] ) + goto error; + ops++; + case -85: + case -69: + lm = 2; + SHIFT_( 1 ); + break; + case 'L': + case 'G': + if ( *ops == 't' ) + goto comp; + case 'E': + case 'N': + if ( *ops != 'e' ) + goto error; + comp: + ops++; + ADD_( 1 ); + break; + case '!': + MISC_( 2 ); + break; + case 'M': + MOVE_( 1 ); + break; + case 'S': + STORE_( 1 ); + break; + case 'P': + PTR_INIT_( 1 ); + break; + case '[': + case ']': + goto st; + ind: + ops++; + case 'I': + case '.': + INDIRECT_( 1 ); + break; + case '=': + if ( lm ) + goto st; + case '\0': + /* This Shouldn't Happen */ + /* These are Used to Avoid: "warning: 'name' defined but not used" with Cygwin gcc Compiler */ + wmc_flag_ = wmc_flag_; + ops_cnt_ptr = ops_cnt_ptr; + fct( "" ); + error: + default: + fprintf( stderr, "\r wops: Invalid Counting Operation '%s'\n", ops - 1 ); + exit( -1 ); + } + lm >>= 1; + lo >>= 2; + } + + return; +} + +#endif + +/* All Other Operations */ +#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) ) + + +/*-------------------------------------------------------------------* + * Memory counting tool + *-------------------------------------------------------------------*/ + +/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */ +#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) ) + +#ifdef _MSC_VER +/* Disable "warning C4210: nonstandard extension used : function given file scope" with Visual Studio Compiler */ +#pragma warning( disable : 4210 ) +#endif + +/* Const Data Size and PROM Size Wrapper Functions */ +#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void ) +#define Get_Const_Data_Size( file, val_ptr ) \ + { \ + extern int Const_Data_Size_##file( void ); \ + *( val_ptr ) = Const_Data_Size_##file(); \ + } +#define PROM_Size_Func( file ) PROM_Size_##file( void ) +#define Get_PROM_Size( file, val_ptr ) \ + { \ + int PROM_Size_##file( void ); \ + *( val_ptr ) = PROM_Size_##file(); \ + } + +/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */ +/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */ +typedef struct ROM_Size_Lookup_Table +{ + const char file_spec[255]; + int PROM_size; + int ( *Get_Const_Data_Size_Func )( void ); +} ROM_Size_Lookup_Table; + +/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */ +/* and modifies it to print_mem(Const_Data_PROM_Table) */ + +/* #ifdef WMOPS + * ROM_Size_Lookup_Table Const_Data_PROM_Table[] = + * { + * {"../lib_enc/rom_enc.c", 0, NULL}, + * {"../lib_com/*.c", 0, NULL}, + * {"", -1, NULL} + * }; + * #endif + */ + +/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */ +/*#define MEM_COUNT_DETAILS*/ + +typedef enum +{ + USE_BYTES = 0, + USE_16BITS = 1, + USE_32BITS = 2 +} Counting_Size; + +#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) ) +#define __func__ __FUNCTION__ +#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ < 199901L +#if ( __GNUC__ >= 2 ) +#define __func__ __FUNCTION__ +#else +#define __func__ "" +#endif +#elif defined( __GNUC__ ) +#define __func__ __extension__ __FUNCTION__ +#endif + + +#ifdef WMOPS + +void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str ); +void mem_free( const char *func_name, int func_lineno, void *ptr ); + +#define malloc_( size ) mem_alloc( __func__, __LINE__, size, "m:" #size ) +#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), "c:" #n ", " #size ) +#define free_( ptr ) mem_free( __func__, __LINE__, ptr ) + +void reset_mem( Counting_Size cnt_size ); +void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ); + +int push_stack( const char *filename, const char *fctname ); +int pop_stack( const char *filename, const char *fctname ); + +#ifdef WMOPS_DETAIL +#define STACK_DEPTH_FCT_CALL ( push_wmops( __FUNCTION__ ), push_stack( __FILE__, __FUNCTION__ ) ) /* add push_wmops() in all function calls */ +#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __FUNCTION__ ) ) /* add pop_wmops() in all function returns */ +#else +#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __FUNCTION__ ) +#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __FUNCTION__ ) +#endif + +void reset_stack( void ); +#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL; + +#else +#define malloc_( n1 ) malloc( n1 ) +#define calloc_( n1, n2 ) calloc( n1, n2 ) +#define free_( ptr ) free( ptr ) +#define reset_mem( cnt_size ) +#define print_mem( Const_Data_PROM_Table ) + +#define push_stack( file, fct ) +#define pop_stack( file, fct ) +#define reset_stack() +#define func_start_ + +#endif + +#endif /* WMOPS_H */ diff --git a/lib_debug/wmops.c b/lib_debug/wmops.c deleted file mode 100644 index fe75a207ff0d24b73f6a56899f227a88a05900ce..0000000000000000000000000000000000000000 --- a/lib_debug/wmops.c +++ /dev/null @@ -1,503 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include -#include -#include -#include "options.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "wmops.h" - - -/*-------------------------------------------------------------------* - * WMOPS counting tool - *--------------------------------------------------------------------*/ - -#ifdef WMOPS - -#define MAX_RECORDS 1024 -#define MAX_CHAR 64 -#define MAX_STACK 64 -#define DOUBLE_MAX 0x80000000; - -struct wmops_record -{ - char label[MAX_CHAR]; - int32_t call_number; - int32_t update_cnt; - int call_tree[MAX_RECORDS]; - double start_selfcnt; - double current_selfcnt; - double max_selfcnt; - double min_selfcnt; - double tot_selfcnt; - double start_cnt; /* The following take into account the decendants */ - double current_cnt; - double max_cnt; - double min_cnt; - double tot_cnt; -#ifdef WMOPS_WC_FRAME_ANALYSIS - int32_t current_call_number; - double wc_cnt; - double wc_selfcnt; - int32_t wc_call_number; -#endif -}; - -double ops_cnt; -double prom_cnt; -double inst_cnt[NUM_INST]; - -int ops_cnt_activ = 1; - -static struct wmops_record wmops[MAX_RECORDS]; -static int stack[MAX_STACK]; -static int sptr; -static int num_records; -static int current_record; -static int32_t update_cnt; -static double start_cnt; -static double max_cnt; -static double min_cnt; -static double inst_cnt_wc[NUM_INST]; -static int32_t fnum_cnt_wc; - - -void reset_wmops( void ) -{ - int i, j; - - for ( i = 0; i < MAX_RECORDS; i++ ) - { - strcpy( &wmops[i].label[0], "\0" ); - wmops[i].call_number = 0; - wmops[i].update_cnt = 0; - for ( j = 0; j < MAX_RECORDS; j++ ) - { - wmops[i].call_tree[j] = -1; - } - wmops[i].start_selfcnt = 0.0; - wmops[i].current_selfcnt = 0.0; - wmops[i].max_selfcnt = 0.0; - wmops[i].min_selfcnt = DOUBLE_MAX; - wmops[i].tot_selfcnt = 0.0; - wmops[i].start_cnt = 0.0; - wmops[i].current_cnt = 0.0; - wmops[i].max_cnt = 0.0; - wmops[i].min_cnt = DOUBLE_MAX; - wmops[i].tot_cnt = 0.0; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[i].wc_cnt = 0.0; - wmops[i].wc_selfcnt = 0.0; - wmops[i].current_call_number = 0; -#endif - } - - for ( i = 0; i < MAX_STACK; i++ ) - { - stack[i] = -1; - } - sptr = 0; - num_records = 0; - current_record = -1; - update_cnt = 0; - - max_cnt = 0.0; - min_cnt = DOUBLE_MAX; - start_cnt = 0.0; - ops_cnt = 0.0; -} - - -void push_wmops( const char *label ) -{ - int new_flag; - int i, j; - - /* Check if new function record label */ - new_flag = 1; - for ( i = 0; i < num_records; i++ ) - { - if ( strcmp( wmops[i].label, label ) == 0 ) - { - new_flag = 0; - break; - } - } - - /* Configure new record */ - if ( new_flag ) - { - if ( num_records >= MAX_RECORDS ) - { - fprintf( stdout, "push_wmops(): exceeded MAX_RECORDS count.\n\n" ); - exit( -1 ); - } - strcpy( wmops[i].label, label ); - num_records++; - } - - /* Push current context onto stack */ - if ( current_record >= 0 ) - { - if ( sptr >= MAX_STACK ) - { - fprintf( stdout, "\r push_wmops(): stack exceeded, try inreasing MAX_STACK\n" ); - exit( -1 ); - } - stack[sptr++] = current_record; - - /* accumulate op counts */ - wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; - - /* update call tree */ - for ( j = 0; j < MAX_RECORDS; j++ ) - { - if ( wmops[i].call_tree[j] == current_record ) - { - break; - } - else if ( wmops[i].call_tree[j] == -1 ) - { - wmops[i].call_tree[j] = current_record; - break; - } - } - } - - /* init current record */ - current_record = i; - wmops[current_record].start_selfcnt = ops_cnt; - wmops[current_record].start_cnt = ops_cnt; - wmops[current_record].call_number++; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[current_record].current_call_number++; -#endif -} - -void wmops_sub_start( const char *label ) -{ -#ifndef WMOPS_DETAIL - push_wmops( label ); -#endif -} - -void pop_wmops( void ) -{ - - /* Check for underflow */ - if ( current_record < 0 ) - { - fprintf( stdout, "\r pop_wmops(): stack underflow, too many calls to pop_wmops()\n" ); - exit( -1 ); - } - - /* update count of current record */ - wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; - wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; - - /* Get back previous context from stack */ - if ( sptr > 0 ) - { - current_record = stack[--sptr]; - wmops[current_record].start_selfcnt = ops_cnt; - } - else - { - current_record = -1; - } -} - -void wmops_sub_end( void ) -{ -#ifndef WMOPS_DETAIL - pop_wmops(); -#endif -} - -void update_wmops( void ) -{ - int i; - double current_cnt; - - if ( sptr != 0 ) - { - fprintf( stdout, "update_wmops(): Stack must be empty!\n" ); - exit( -1 ); - } - -#ifdef WMOPS_PER_FRAME /* output complexity in WMOPS per frame - note that "frame" number was already incremented before calling this function */ - { - float tmpF = (float) ( FAC * wmops[0].current_cnt ); - dbgwrite( &tmpF, 4, 1, 1, "res/wmops" ); - } -#endif - -#ifdef WMOPS_WC_FRAME_ANALYSIS - if ( ops_cnt - start_cnt > max_cnt ) - { - for ( i = 0; i < num_records; i++ ) - { - wmops[i].wc_cnt = wmops[i].current_cnt; - wmops[i].wc_selfcnt = wmops[i].current_selfcnt; - wmops[i].wc_call_number = wmops[i].current_call_number; - } - } -#endif - - for ( i = 0; i < num_records; i++ ) - { - wmops[i].tot_selfcnt += wmops[i].current_selfcnt; - wmops[i].tot_cnt += wmops[i].current_cnt; - - if ( wmops[i].current_selfcnt > 0 ) - { - if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt ) - { - wmops[i].max_selfcnt = wmops[i].current_selfcnt; - } - - if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt ) - { - wmops[i].min_selfcnt = wmops[i].current_selfcnt; - } - } - - wmops[i].current_selfcnt = 0; - - if ( wmops[i].current_cnt > 0 ) - { - if ( wmops[i].current_cnt > wmops[i].max_cnt ) - { - wmops[i].max_cnt = wmops[i].current_cnt; - } - - if ( wmops[i].current_cnt < wmops[i].min_cnt ) - { - wmops[i].min_cnt = wmops[i].current_cnt; - } - - wmops[i].update_cnt++; - } - - wmops[i].current_cnt = 0; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[i].current_call_number = 0; -#endif - } - - current_cnt = ops_cnt - start_cnt; - if ( current_cnt > max_cnt ) - { - max_cnt = current_cnt; - - for ( i = 0; i < NUM_INST; i++ ) - { - inst_cnt_wc[i] = inst_cnt[i]; - } - - fnum_cnt_wc = update_cnt; - } - - if ( current_cnt < min_cnt ) - { - min_cnt = current_cnt; - } - - for ( i = 0; i < NUM_INST; i++ ) - { - inst_cnt[i] = 0.0; - } - - - start_cnt = ops_cnt; - update_cnt++; -} - - -void print_wmops( void ) -{ - int i, label_len, max_label_len; - - char *sfmts = "%*s %8s %8s %7s %7s\n"; - char *dfmts = "%*s %8.2f %8.3f %7.3f %7.3f\n"; - char *sfmt = "%*s %8s %8s %7s %7s %7s %7s %7s\n"; - char *dfmt = "%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; - -#if ENABLE_TREE - int j; - char *sfmtt = "%20s %4s %15s\n"; - char *dfmtt = "%20s %4d "; -#endif - - /* fprintf( stdout, "\nProgram Memory Analysis: %12.0f words\n", prom_cnt ); */ - /* fprintf (stdout, "\nInstruction Type Analysis (for worst case frame):\n\n"); */ - fprintf( stdout, "\nInstruction Type Analysis (for worst case frame number %d):\n\n", fnum_cnt_wc ); /* added -- JPA */ - for ( i = 0; i < NUM_INST; i++ ) - { - switch ( (enum instructions) i ) - { - case _ADD: - fprintf( stdout, "\tAdds: %12.1f\n", inst_cnt_wc[i] ); - break; - case _ABS: - fprintf( stdout, "\tAbsolutes: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MULT: - fprintf( stdout, "\tMultiplies: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MAC: - fprintf( stdout, "\tMACs: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MOVE: - fprintf( stdout, "\tMoves: %12.1f\n", inst_cnt_wc[i] ); - break; - case _STORE: - fprintf( stdout, "\tStores: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOGIC: - fprintf( stdout, "\tLogicals: %12.1f\n", inst_cnt_wc[i] ); - break; - case _SHIFT: - fprintf( stdout, "\tShifts: %12.1f\n", inst_cnt_wc[i] ); - break; - case _BRANCH: - fprintf( stdout, "\tBranches: %12.1f\n", inst_cnt_wc[i] ); - break; - case _DIV: - fprintf( stdout, "\tDivisions: %12.1f\n", inst_cnt_wc[i] ); - break; - case _SQRT: - fprintf( stdout, "\tSquare Root: %12.1f\n", inst_cnt_wc[i] ); - break; - case _TRANS: - fprintf( stdout, "\tTrans: %12.1f\n", inst_cnt_wc[i] ); - break; - case _FUNC: - fprintf( stdout, "\tFunc Call: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOOP: - fprintf( stdout, "\tLoop Init: %12.1f\n", inst_cnt_wc[i] ); - break; - case _INDIRECT: - fprintf( stdout, "\tIndirect Addr: %12.1f\n", inst_cnt_wc[i] ); - break; - case _PTR_INIT: - fprintf( stdout, "\tPointer Init: %12.1f\n", inst_cnt_wc[i] ); - break; - case _TEST: - fprintf( stdout, "\tExtra condit.: %12.1f\n", inst_cnt_wc[i] ); - break; - case _POWER: - fprintf( stdout, "\tExponential: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOG: - fprintf( stdout, "\tLogarithm: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MISC: - fprintf( stdout, "\tAll other op.: %12.1f\n", inst_cnt_wc[i] ); - break; - default: - fprintf( stdout, "\tERROR: Invalid instruction type: %d\n\n", i ); - } - } - - max_label_len = 0; - for ( i = 0; i < num_records; i++ ) - { - label_len = strlen( wmops[i].label ); - if ( label_len > max_label_len ) - { - max_label_len = label_len; - } - } - max_label_len += 4; - -#ifdef WMOPS_WC_FRAME_ANALYSIS - fprintf( stdout, "\n\nWeighted MOPS Analysis for worst case frame number %d ( WMOPS boost factor %4.2f ):\n", fnum_cnt_wc, WMOPS_BOOST_FAC ); - fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); - fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, "%*s %8d %10.3f %12.3f\n", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt ); - } - -#endif - - fprintf( stdout, "\n\nWeighted MOPS Analysis ( WMOPS boost factor %4.2f ):\n", WMOPS_BOOST_FAC ); - fprintf( stdout, "%*s %34s %23s\n", max_label_len, "", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); - fprintf( stdout, sfmt, max_label_len, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); - fprintf( stdout, sfmt, max_label_len, "---------------", "------", "------", "------", "------", "------", "------", "------" ); - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, dfmt, max_label_len, wmops[i].label, - update_cnt == 0 ? 0.0f : (float) wmops[i].call_number / update_cnt, - wmops[i].update_cnt == 0 ? 0.0f : FAC * wmops[i].min_selfcnt, FAC * wmops[i].max_selfcnt, - wmops[i].update_cnt == 0 ? 0.0f : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, - wmops[i].update_cnt == 0 ? 0.0f : FAC * wmops[i].min_cnt, FAC * wmops[i].max_cnt, - wmops[i].update_cnt == 0 ? 0.0f : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); - } - fprintf( stdout, sfmts, max_label_len, "---------------", "------", "------", "------", "------" ); - fprintf( stdout, dfmts, max_label_len, "total", (float) update_cnt, FAC * min_cnt, FAC * max_cnt, FAC * ops_cnt / update_cnt ); - fprintf( stdout, "\n" ); - -#if ENABLE_TREE - - fprintf( stdout, "\nCall Tree:\n\n" ); - fprintf( stdout, sfmtt, " function", "num", "called by: " ); - fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, dfmtt, wmops[i].label, i ); - for ( j = 0; wmops[i].call_tree[j] != -1; j++ ) - { - if ( j != 0 ) - { - fprintf( stdout, ", " ); - } - fprintf( stdout, "%d", wmops[i].call_tree[j] ); - } - fprintf( stdout, "\n" ); - } - - fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); - fprintf( stdout, "\n\n" ); - -#endif -} - -#endif /* WMOPS */ diff --git a/lib_dec/ACcontextMapping_dec.c b/lib_dec/ACcontextMapping_dec.c index 10fb36974167250244b60cb2f307bec755591a98..5139106d9fe8834d8fed53536ae2a244c34fd936 100644 --- a/lib_dec/ACcontextMapping_dec.c +++ b/lib_dec/ACcontextMapping_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "rom_com.h" #include "ivas_rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /* Range coder header file */ #include diff --git a/lib_dec/FEC.c b/lib_dec/FEC.c index 3267092e7e46cd769a74e26a7f1c2d569e887c47..8118e07748b79eaa83653e8089434b48c34d907d 100644 --- a/lib_dec/FEC.c +++ b/lib_dec/FEC.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "rom_dec.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -522,7 +522,7 @@ static void gain_dec_bfi( } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /*-------------------------------------------------------------------* * pulseRes_preCalc() * @@ -577,4 +577,4 @@ static void pulseRes_preCalc( return; } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP diff --git a/lib_dec/FEC_HQ_core.c b/lib_dec/FEC_HQ_core.c index 53eca7698212331738deee3dc31d6d0cc9628f68..988689b76d63f5af2b859298ad8dacbc110441b5 100644 --- a/lib_dec/FEC_HQ_core.c +++ b/lib_dec/FEC_HQ_core.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_dec.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local prototypes diff --git a/lib_dec/FEC_HQ_phase_ecu.c b/lib_dec/FEC_HQ_phase_ecu.c index fd71f5c41bf9e06ab8d8c26898417c88c484b085..96974b9f8e7d1b96d9a759ecb2c815222193dafc 100644 --- a/lib_dec/FEC_HQ_phase_ecu.c +++ b/lib_dec/FEC_HQ_phase_ecu.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_dec/FEC_adapt_codebook.c b/lib_dec/FEC_adapt_codebook.c index 5ffd9a1fdeba23808f2d4117c2f96bb1916c2745..961dfc6a5d19fa38401eb9c7bb396546b267329d 100644 --- a/lib_dec/FEC_adapt_codebook.c +++ b/lib_dec/FEC_adapt_codebook.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_dec.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- * FEC_synchro_exc() diff --git a/lib_dec/FEC_clas_estim.c b/lib_dec/FEC_clas_estim.c index 7a27532f17abd8981f7d0c170691a33211746ea7..4acd3dab9cef32fa47fafd57184f9edc2e52877a 100644 --- a/lib_dec/FEC_clas_estim.c +++ b/lib_dec/FEC_clas_estim.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "stat_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_dec/FEC_lsf_estim.c b/lib_dec/FEC_lsf_estim.c index f971ec4434de2943cb756fbe8dd9f28c6b8e178d..dce8b8351583c298dcd5ed8f41b0807d7ac32f0c 100644 --- a/lib_dec/FEC_lsf_estim.c +++ b/lib_dec/FEC_lsf_estim.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * FEC_lsf_estim() diff --git a/lib_dec/FEC_pitch_estim.c b/lib_dec/FEC_pitch_estim.c index e2f6491cc30072ce48e16ae042b80fe0b4a2d68e..3076f7bcaaccd78c0e92566c68669bc56eed653e 100644 --- a/lib_dec/FEC_pitch_estim.c +++ b/lib_dec/FEC_pitch_estim.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------* * FEC_pitch_estim() diff --git a/lib_dec/FEC_scale_syn.c b/lib_dec/FEC_scale_syn.c index 66fae0fc053108265fe3efad80bcc738515eb752..7d43ad3a9ae7840dd49894d6a796169878894861 100644 --- a/lib_dec/FEC_scale_syn.c +++ b/lib_dec/FEC_scale_syn.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #define SCLSYN_LAMBDA 0.3f diff --git a/lib_dec/LD_music_post_filter.c b/lib_dec/LD_music_post_filter.c index f19e7375952d6c150fd1e5e3d5c27751716fd188..87984e873a15af6bc744f1e32f4b3af1e409a8ea 100644 --- a/lib_dec/LD_music_post_filter.c +++ b/lib_dec/LD_music_post_filter.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_dec/TonalComponentDetection.c b/lib_dec/TonalComponentDetection.c index 230dfe408625b32ebc099a1bb82576dce3f7c122..fedfe0c2e6be69c18d76ad5576922432a2408f21 100644 --- a/lib_dec/TonalComponentDetection.c +++ b/lib_dec/TonalComponentDetection.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "prot.h" #include "cnst.h" #include "stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" diff --git a/lib_dec/acelp_core_dec.c b/lib_dec/acelp_core_dec.c index 17b5a82aa96627278b0c30d8121fedbe0383ab93..eb53379d6683c5d05f178ae3f0d2b4aef0dac910 100644 --- a/lib_dec/acelp_core_dec.c +++ b/lib_dec/acelp_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -48,7 +48,7 @@ #ifdef LSF_RE_USE_SECONDARY_CHANNEL #include "ivas_rom_com.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * acelp_core_dec() @@ -105,7 +105,7 @@ ivas_error acelp_core_dec( float exc_buffer[DCT_L_POST]; float dct_exc_tmp[L_FRAME16k]; float bpf_error_signal[L_FRAME16k]; - int16_t nb_bits; /* number of bits */ + int16_t nb_bits; /* number of bits */ int16_t indice; /* parameter indices to write */ float gain_buf[NB_SUBFR16k]; float q_env[20]; @@ -125,13 +125,13 @@ ivas_error acelp_core_dec( error = IVAS_ERR_OK; - if ( st->element_mode == IVAS_CPE_MDCT && nchan_out == 1 && st->idchan == 1 && last_element_brate <= IVAS_SID_4k4 ) + if ( st->element_mode == IVAS_CPE_MDCT && nchan_out == 1 && st->idchan == 1 && last_element_brate <= IVAS_SID_5k2 ) { /* In MDCT-Stereo DTX with mono output, we can skip CNG for the second channel, except for the first inactive frame following an active period */ return error; } - wmops_sub_start( "acelp_core_dec" ); + push_wmops( "acelp_core_dec" ); output_frame = (int16_t) ( st->output_Fs / FRAMES_PER_SEC ); @@ -156,11 +156,7 @@ ivas_error acelp_core_dec( st->hFdCngDec->hFdCngCom->sidNoiseEstLp[i] = STEREO_DFT_FD_FILT * st->hFdCngDec->hFdCngCom->sidNoiseEstLp[i] + ( 1 - STEREO_DFT_FD_FILT ) * st->hFdCngDec->hFdCngCom->sidNoiseEst[i]; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ApplyFdCng( NULL, NULL, NULL, NULL, st, 0, 0 ); -#else - ApplyFdCng( NULL, NULL, NULL, st, 0, 0 ); -#endif } else { @@ -183,7 +179,7 @@ ivas_error acelp_core_dec( set_f( synth, 0, output_frame ); /* They are however read in a few places which causes errors in the valgrind tests. Simplest solution from a code perspective was to set them to zero. */ /* CN generation done in DFT domain */ - wmops_sub_end(); + pop_wmops(); return error; } @@ -516,7 +512,7 @@ ivas_error acelp_core_dec( } else { - if ( st->core_brate == SID_2k40 && st->element_mode != IVAS_CPE_MDCT ) + if ( st->core_brate == SID_2k40 && st->element_mode != IVAS_CPE_MDCT && st->read_sid_info ) { FdCng_decodeSID( st ); *sid_bw = 0; @@ -530,11 +526,18 @@ ivas_error acelp_core_dec( { st->hFdCngDec->hFdCngCom->sidNoiseEstLp[i] = STEREO_DFT_FD_FILT * st->hFdCngDec->hFdCngCom->sidNoiseEstLp[i] + ( 1 - STEREO_DFT_FD_FILT ) * st->hFdCngDec->hFdCngCom->sidNoiseEst[i]; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ApplyFdCng( syn, NULL, realBuffer, imagBuffer, st, 0, ( st->coder_type == AUDIO && !st->GSC_noisy_speech ) ); -#else - ApplyFdCng( syn, realBuffer, imagBuffer, st, 0, ( st->coder_type == AUDIO && !st->GSC_noisy_speech ) ); -#endif + } + if ( !st->read_sid_info ) + // if (!st->read_sid_info && st->cng_ism_flag) /* read_sid_info can only be 0 in ParamISM mode */ + { + float noise_lvl_highest; + + noise_lvl_highest = st->hFdCngDec->hFdCngCom->cngNoiseLevel[st->hFdCngDec->hFdCngCom->stopFFTbin - st->hFdCngDec->hFdCngCom->startBand - 1]; + for ( int16_t b = st->hFdCngDec->hFdCngCom->stopFFTbin - st->hFdCngDec->hFdCngCom->startBand; b < st->hFdCngDec->hFdCngCom->stopBand; b++ ) + { + st->hFdCngDec->hFdCngCom->cngNoiseLevel[b] = noise_lvl_highest; + } } generate_comfort_noise_dec( NULL, NULL, st, nchan_out ); @@ -702,6 +705,12 @@ ivas_error acelp_core_dec( residu( Aq, M, old_exc_s, old_exc + L_EXC_MEM_DEC - st->L_frame, st->L_frame ); } + if ( st->last_core != ACELP_CORE && st->element_mode > EVS_MONO ) + { + /* Prepare ACB memory of old_bwe_exc */ + lerp( old_exc, old_bwe_exc, L_EXC_MEM_DEC * HIBND_ACB_L_FAC, L_EXC_MEM_DEC ); + } + /*-----------------------------------------------------------------* * FEC - first good frame after lost frame(s) (possibility to correct the ACB) *-----------------------------------------------------------------*/ @@ -801,7 +810,6 @@ ivas_error acelp_core_dec( return error; } - if ( st->element_mode == IVAS_CPE_TD ) { tmp_noise = st->lp_gainc; @@ -1117,14 +1125,10 @@ ivas_error acelp_core_dec( st->lp_noise = st->hFdCngDec->lp_noise; } - if ( st->element_mode != IVAS_CPE_TD ) + if ( st->element_mode != IVAS_CPE_TD && !st->cng_ism_flag ) { /*Noise estimate*/ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ApplyFdCng( syn, NULL, realBuffer, imagBuffer, st, 0, ( st->coder_type == AUDIO && !st->GSC_noisy_speech ) ); -#else - ApplyFdCng( syn, realBuffer, imagBuffer, st, 0, ( st->coder_type == AUDIO && !st->GSC_noisy_speech ) ); -#endif } if ( !st->cna_dirac_flag ) @@ -1189,11 +1193,7 @@ ivas_error acelp_core_dec( /*Noise estimate*/ if ( st->idchan == 0 && ( nchan_out == 2 || ( st->core_brate != FRAME_NO_DATA && st->core_brate != SID_2k40 ) ) ) { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ApplyFdCng( syn, NULL, realBuffer, imagBuffer, st, 0, ( st->coder_type == AUDIO && !st->GSC_noisy_speech ) ); -#else - ApplyFdCng( syn, realBuffer, imagBuffer, st, 0, ( st->coder_type == AUDIO && !st->GSC_noisy_speech ) ); -#endif } } } @@ -1296,12 +1296,12 @@ ivas_error acelp_core_dec( st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - st->cldfbAna->no_channels; } - if ( !st->cng_dirac_flag || st->element_mode == IVAS_CPE_MDCT ) + if ( !st->cng_sba_flag || st->element_mode == IVAS_CPE_MDCT ) { /*WB/SWB-FD_CNG*/ if ( ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && ( st->cng_type == FD_CNG ) && ( st->hFdCngDec->hFdCngCom->numCoreBands < st->cldfbSyn->no_channels ) ) { - generate_comfort_noise_dec_hf( realBuffer, imagBuffer, st->hFdCngDec->hFdCngCom ); + generate_comfort_noise_dec_hf( realBuffer, imagBuffer, st->hFdCngDec->hFdCngCom, st->cng_ism_flag ); if ( st->hFdCngDec->hFdCngCom->regularStopBand < st->cldfbSyn->no_channels ) { @@ -1443,6 +1443,6 @@ ivas_error acelp_core_dec( st->hTdCngDec->ho_16k_lsp[st->hTdCngDec->ho_circ_ptr] = ( st->L_frame == L_FRAME ? 0 : 1 ); } - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_dec/acelp_core_switch_dec.c b/lib_dec/acelp_core_switch_dec.c index 9daac37b74b1b1fda3fd4b97a0940b025c590610..6953551452220ee793e544469e2d4f379acb1228 100644 --- a/lib_dec/acelp_core_switch_dec.c +++ b/lib_dec/acelp_core_switch_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes @@ -158,8 +158,7 @@ ivas_error acelp_core_switch_dec( * Excitation decoding *----------------------------------------------------------------*/ - config_acelp1( DEC, st->total_brate, cbrate, st->core, -1, -1, st->last_L_frame, -1, &( st->acelp_cfg ), st->next_bit_pos, GENERIC, -1, -1, &decode_bwe /* dummy */, &i, st->element_mode, &i /*dummy*/, 0, 0, st->idchan, 0, 0, 0 /*st->GSC_IVAS_mode*/ - ); + config_acelp1( DEC, st->total_brate, cbrate, st->core, -1, -1, st->last_L_frame, -1, &( st->acelp_cfg ), st->next_bit_pos, GENERIC, -1, -1, &decode_bwe /* dummy */, &i, st->element_mode, &i /*dummy*/, 0, 0, st->idchan, 0, 0, 0 /*st->GSC_IVAS_mode*/ ); decod_gen_voic_core_switch( st, L_frame_for_cs, 0, Aq, exc, cbrate ); @@ -534,7 +533,7 @@ ivas_error acelp_core_switch_dec_bfi( /*-------------------------------------------------------------------* * decod_gen_voic_core_switch() * - * Decode excitation signal in teh first ACELP->HQ switching frame + * Decode excitation signal in the first ACELP->HQ switching frame *-------------------------------------------------------------------*/ static void decod_gen_voic_core_switch( diff --git a/lib_dec/amr_wb_dec.c b/lib_dec/amr_wb_dec.c index c220c8201e42744efb4c0de9041e4c8d9614e23f..5252b265647b1efd2581b816d7b72f2cad8a7f97 100644 --- a/lib_dec/amr_wb_dec.c +++ b/lib_dec/amr_wb_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * amr_wb_dec() @@ -621,11 +621,7 @@ ivas_error amr_wb_dec( /*VAD only for non inactive frame*/ st->VAD = ( st->VAD && ( st->coder_type != INACTIVE ) ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ApplyFdCng( syn, NULL, NULL, NULL, st, 0, 0 ); -#else - ApplyFdCng( syn, NULL, NULL, st, 0, 0 ); -#endif st->hFdCngDec->hFdCngCom->frame_type_previous = st->m_frame_type; diff --git a/lib_dec/ari_dec.c b/lib_dec/ari_dec.c index fe97e69a523f566978b2783e5f3caa4c0704e3e6..31df466f009d2106ae5d5356b9e2351c26af812f 100644 --- a/lib_dec/ari_dec.c +++ b/lib_dec/ari_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "prot.h" #include "stat_com.h" #include "basop_util.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- diff --git a/lib_dec/ari_hm_dec.c b/lib_dec/ari_hm_dec.c index 78f14e4a282b0b3e67a2c59733ba031dfa3fe6a3..3ba6a886fb4468278c9b4809bdcb585c2f50070f 100644 --- a/lib_dec/ari_hm_dec.c +++ b/lib_dec/ari_hm_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "basop_util.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * DecodeIndex() diff --git a/lib_dec/arith_coder_dec.c b/lib_dec/arith_coder_dec.c index 793edcef261e17f57bcea01bfcacc0932c9d1a67..09f1698133aabf410b5ff434b1b5a4cbffb8e4f6 100644 --- a/lib_dec/arith_coder_dec.c +++ b/lib_dec/arith_coder_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "rom_com.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------* * tcx_arith_decode() @@ -170,9 +170,9 @@ void tcx_arith_decode_envelope( gamma_w = 1.0f; gamma_uw = 1.0f / st->gamma; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP tcx_arith_render_envelope( A_ind, L_frame, L_spec, FL2WORD16( hTcxCfg->preemph_fac ), FL2WORD16( gamma_w ), FL2WORD16( 0.5f * gamma_uw ), env ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP if ( use_hm ) { diff --git a/lib_dec/avq_dec.c b/lib_dec/avq_dec.c index 99aabbb04c824fe9f1e796b8d6baae1ac6b137f6..ec74ea53896dbb1cc3939b47c83cfc10f68da315 100644 --- a/lib_dec/avq_dec.c +++ b/lib_dec/avq_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" #include /*-------------------------------------------------------------------* diff --git a/lib_dec/bass_psfilter.c b/lib_dec/bass_psfilter.c index 85c595460c21abd1d82c0bf4c2c6e76d5ad43594..0a0eabd1153824989e9f74fa00d17d5a670cf553 100644 --- a/lib_dec/bass_psfilter.c +++ b/lib_dec/bass_psfilter.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "debug.h" #endif #include -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_dec/cng_dec.c b/lib_dec/cng_dec.c index 415ac27b3a492d5686a52336433dadb1c3a93337..b780db062f4d416a2fbcf2bde7dbb15b79bd18c4 100644 --- a/lib_dec/cng_dec.c +++ b/lib_dec/cng_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_dec/core_dec_init.c b/lib_dec/core_dec_init.c index d2d94799ef04fc4ec848738aa0492f1a02226369..6d6ebeef86800182fbee4d5992066fd405956581 100644 --- a/lib_dec/core_dec_init.c +++ b/lib_dec/core_dec_init.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * open_decoder_LPD() @@ -52,15 +52,13 @@ *-----------------------------------------------------------------------*/ void open_decoder_LPD( - Decoder_State *st, - const int32_t total_brate, - const int32_t last_total_brate, - const int16_t bwidth, - const int16_t is_mct, /* i : MCT mode flag */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t last_element_mode, -#endif - const int16_t is_init /* i : indicate call from init_decoder() to avoid double TC initialization */ + Decoder_State *st, /* i/o: decoder state structure */ + const int32_t total_brate, /* i : total bitrate */ + const int32_t last_total_brate, /* i : last total bitrate */ + const int16_t bwidth, /* i : audio bandwidth */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t last_element_mode, /* i : last element mode */ + const int16_t is_init /* i : indicate call during initialization */ ) { int16_t i; @@ -94,7 +92,7 @@ void open_decoder_LPD( } } - st->tcxonly = getTcxonly( st->element_mode, total_brate, is_mct ); + st->tcxonly = getTcxonly( st->element_mode, total_brate, MCT_flag ); /* the TD TCX PLC in MODE1 still runs with 80ms subframes */ if ( ( st->element_mode == EVS_MONO && st->L_frame == L_FRAME16k && total_brate <= ACELP_32k ) || ( st->element_mode > EVS_MONO && st->L_frame == L_FRAME16k && total_brate <= MAX_ACELP_BRATE ) || ( st->tcxonly && ( st->sr_core == 32000 || st->sr_core == 16000 ) ) ) @@ -192,7 +190,12 @@ void open_decoder_LPD( { if ( !is_init || st->element_mode != IVAS_CPE_MDCT ) { - init_tcx_cfg( st->hTcxCfg, total_brate, st->sr_core, st->output_Fs, st->L_frame, st->bwidth, st->hTcxDec->L_frameTCX, st->fscale, encoderLookahead, encoderLookaheadFB, st->preemph_fac, st->tcxonly, st->rf_flag, st->igf, st->hIGFDec->infoIGFStopFreq, st->element_mode, st->ini_frame, is_mct, st->mct_chan_mode ); + init_tcx_cfg( st->hTcxCfg, total_brate, st->sr_core, st->output_Fs, st->L_frame, st->bwidth, st->hTcxDec->L_frameTCX, st->fscale, encoderLookahead, encoderLookaheadFB, st->preemph_fac, st->tcxonly, st->rf_flag, st->igf, st->hIGFDec->infoIGFStopFreq, st->element_mode, st->ini_frame, MCT_flag +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); } else { @@ -281,7 +284,7 @@ void open_decoder_LPD( st->last_core_bfi = ACELP_CORE; } - if ( st->element_mode != IVAS_CPE_DFT && st->last_codec_mode == MODE1 && st->last_core == ACELP_CORE ) + if ( ( ( st->element_mode != IVAS_CPE_DFT ) || ( st->element_mode == IVAS_CPE_DFT && st->prev_bfi ) ) && st->last_codec_mode == MODE1 && st->last_core == ACELP_CORE ) { /* Switching from Mode 1 ACELP */ st->last_core_bfi = ACELP_CORE; @@ -552,9 +555,7 @@ void open_decoder_LPD( { st->hTcxDec->prev_widow_left_rect = 0; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - /* Todo: should be considered for other stereo modes as well */ - if ( is_init || !( st->element_mode == IVAS_CPE_MDCT && st->element_mode == last_element_mode ) ) + if ( is_init || MCT_flag || !( st->element_mode == IVAS_CPE_MDCT && st->element_mode == last_element_mode ) ) { st->hTcxDec->CngLevelBackgroundTrace_bfi = PLC_MIN_CNG_LEV; st->hTcxDec->NoiseLevelIndex_bfi = PLC_MIN_STAT_BUFF_SIZE - 1; @@ -564,15 +565,6 @@ void open_decoder_LPD( st->hTcxDec->cummulative_damping_tcx = 1.0f; } -#else - st->hTcxDec->CngLevelBackgroundTrace_bfi = PLC_MIN_CNG_LEV; - st->hTcxDec->NoiseLevelIndex_bfi = PLC_MIN_STAT_BUFF_SIZE - 1; - st->hTcxDec->CurrLevelIndex_bfi = 0; - st->hTcxDec->LastFrameLevel_bfi = PLC_MIN_CNG_LEV; - set_f( st->hTcxDec->NoiseLevelMemory_bfi, PLC_MIN_CNG_LEV, PLC_MIN_STAT_BUFF_SIZE ); - - st->hTcxDec->cummulative_damping_tcx = 1.0f; -#endif } st->cummulative_damping = 1.0f; @@ -683,6 +675,20 @@ void open_decoder_LPD( st->last_tns_active = 0; st->second_last_tns_active = 0; st->second_last_core = -1; + + if ( st->hTcxCfg != NULL && +#ifndef ISSUE_24_CLEANUP_MCT_LFE + !MCT_flag && +#endif + st->element_mode != EVS_MONO ) + { + st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( is_init ? total_brate : st->bits_frame_nominal * FRAMES_PER_SEC, st->igf, st->element_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + } if ( hTcxDec != NULL ) { hTcxDec->tcxltp_second_last_pitch = st->old_fpitch; diff --git a/lib_dec/core_dec_reconf.c b/lib_dec/core_dec_reconf.c index 201ccc0cb3ac5c52573f38669013fdf9117c8b75..7734d131773c06eacedaae8cb2be72806e7e73a8 100644 --- a/lib_dec/core_dec_reconf.c +++ b/lib_dec/core_dec_reconf.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * reconfig_decoder_LPD() diff --git a/lib_dec/core_dec_switch.c b/lib_dec/core_dec_switch.c index 637c185f327c71fa57cd543a58bcbb5cdb7fc30c..b02d0a78f5ae2ba639ec634ce3c99d389ec565af 100644 --- a/lib_dec/core_dec_switch.c +++ b/lib_dec/core_dec_switch.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------* * mode_switch_decoder_LPD() @@ -51,16 +51,13 @@ *-------------------------------------------------------------*/ void mode_switch_decoder_LPD( - Decoder_State *st, /* i/o: decoder state structure */ - const int16_t bwidth, /* i : audio bandwidth */ - const int32_t total_brate, /* i : total bitrate */ - const int32_t last_total_brate, /* i : last frame total bitrate */ - const int16_t frame_size_index, /* i : index determining the frame size*/ - const int16_t is_mct /* i : MCT mode flag */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t last_element_mode -#endif + Decoder_State *st, /* i/o: decoder state structure */ + const int16_t bwidth, /* i : audio bandwidth */ + const int32_t total_brate, /* i : total bitrate */ + const int32_t last_total_brate, /* i : last frame total bitrate */ + const int16_t frame_size_index, /* i : index determining the frame size */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ + const int16_t last_element_mode /* i : last element mode */ ) { int16_t fscale, switchWB; @@ -94,7 +91,12 @@ void mode_switch_decoder_LPD( switchWB = 1; /*force init when coming from MODE1*/ } - st->igf = getIgfPresent( st->element_mode, total_brate, bwidth, st->rf_flag, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, total_brate, bwidth, st->rf_flag +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); if ( st->hIGFDec != NULL ) { @@ -109,11 +111,7 @@ void mode_switch_decoder_LPD( if ( fscale != st->fscale || switchWB || bSwitchFromAmrwbIO || st->last_codec_mode == MODE1 || st->force_lpd_reset ) { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - open_decoder_LPD( st, total_brate, last_total_brate, bwidth, is_mct, last_element_mode, 0 ); -#else - open_decoder_LPD( st, total_brate, last_total_brate, bwidth, is_mct, 0 ); -#endif + open_decoder_LPD( st, total_brate, last_total_brate, bwidth, MCT_flag, last_element_mode, 0 ); } else { @@ -147,12 +145,17 @@ void mode_switch_decoder_LPD( if ( st->hTcxCfg != NULL ) { st->hTcxCfg->pCurrentTnsConfig = NULL; - st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( total_brate, st->igf, st->element_mode, st->mct_chan_mode ); + st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( total_brate, st->igf, st->element_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); } if ( st->hTcxCfg->fIsTNSAllowed && st->hIGFDec != NULL && st->hTcxCfg != NULL ) { - InitTnsConfigs( bwidth, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFDec->infoIGFStopFreq, total_brate, st->element_mode, is_mct ); + InitTnsConfigs( bwidth, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFDec->infoIGFStopFreq, total_brate, st->element_mode, MCT_flag ); SetAllowTnsOnWhite( st->hTcxCfg->tnsConfig, st->element_mode == IVAS_CPE_MDCT ); } diff --git a/lib_dec/core_switching_dec.c b/lib_dec/core_switching_dec.c index 61537f76e3ca0527eddc7b64bdc52c65e3860584..fc331a2e9feddf5613d7087db069c065ce0e6b09 100644 --- a/lib_dec/core_switching_dec.c +++ b/lib_dec/core_switching_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,14 +44,14 @@ #include "rom_com.h" #include "prot.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local prototypes *---------------------------------------------------------------------*/ static void core_switch_lb_upsamp( Decoder_State *st, float *output ); -static void smoothTransitionMdctStereoDtx( float synth[], const int16_t output_frame, const int16_t delay_comp ); +static void smoothTransitionDtxToTcx( float synth[], const int16_t output_frame, const int16_t delay_comp ); /*---------------------------------------------------------------------* * core_switching_pre_dec() @@ -70,6 +70,7 @@ ivas_error core_switching_pre_dec( { int16_t i, oldLenClasBuff, newLenClasBuff; ivas_error error; + float tmp; error = IVAS_ERR_OK; @@ -401,7 +402,7 @@ ivas_error core_switching_pre_dec( } } - if ( st->core == HQ_CORE && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) ) + if ( st->core == HQ_CORE && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE || ( ( st->element_mode != EVS_MONO ) && ( st->last_core != HQ_CORE ) ) ) ) { set_f( st->hHQ_core->prev_env, 0, SFM_N_WB ); set_f( st->hHQ_core->prev_normq, 0, SFM_N_WB ); @@ -418,8 +419,34 @@ ivas_error core_switching_pre_dec( set_f( st->hHQ_core->prev_coeff_out, 0, L_HQ_WB_BWE ); } - set_f( st->hHQ_core->old_out, 0, output_frame ); - set_f( st->hHQ_core->old_outLB, 0, L_FRAME16k ); + if ( st->element_mode != EVS_MONO ) + { + /* Estimate mem_env_delta to reinit env_stab */ + tmp = max( 0, ENV_STAB_EST1 + ( ENV_STAB_EST2 * st->stab_fac_smooth_lt ) + ( ENV_STAB_EST3 * st->log_energy_diff_lt ) ); + st->hHQ_core->mem_env_delta = (int16_t) min( MAX16B, (int32_t) ( tmp * ( 1 << 12 ) ) ); /* Convert to Q12 and handle saturation */ + + if ( st->last_core != TCX_20_CORE && st->last_core != TCX_10_CORE ) + { + set_f( st->hHQ_core->old_out, 0, output_frame ); + set_f( st->hHQ_core->old_outLB, 0, L_FRAME16k ); + } + + st->hHQ_core->no_att_hangover = 0; + st->hHQ_core->energy_lt = 300.0f; + + set_s( st->hHQ_core->old_is_transient, 0, 3 ); + set_f( st->hHQ_core->prev_noise_level, 0.0f, 2 ); + st->hHQ_core->prev_R = 0; + set_s( st->hHQ_core->mem_norm + 1, 39, SFM_N_ENV_STAB - 1 ); + st->hHQ_core->prev_hqswb_clas = HQ_NORMAL; + st->hHQ_core->prev_ni_ratio = 0.5f; + set_f( st->hHQ_core->prev_En_sb, 0.0f, NB_SWB_SUBBANDS ); + } + else + { + set_f( st->hHQ_core->old_out, 0, output_frame ); + set_f( st->hHQ_core->old_outLB, 0, L_FRAME16k ); + } } /* handle switching cases where preecho_sb was not called in the last frame (memory not up to date) */ @@ -525,10 +552,13 @@ ivas_error core_switching_pre_dec( *---------------------------------------------------------------------*/ ivas_error core_switching_post_dec( - Decoder_State *st, /* i/o: decoder state structure */ - float *synth, /* i/o: output synthesis */ - float *output, /* i/o: LB synth/upsampled LB synth */ - float output_mem[], /* i : OLA memory from last TCX/HQ frame */ + Decoder_State *st, /* i/o: decoder state structure */ + float *synth, /* i/o: output synthesis */ + float *output, /* i/o: LB synth/upsampled LB synth */ + float output_mem[], /* i : OLA memory from last TCX/HQ frame */ +#ifdef FIX_ISM_DTX_CLICKS + const IVAS_FORMAT ivas_format, /* i : IVAS format */ +#endif const int16_t use_cldfb_for_dft, /* i : flag to use of CLDFB for DFT Stereo */ const int16_t output_frame, /* i : frame length */ const int16_t core_switching_flag, /* i : ACELP->HQ switching flag */ @@ -650,10 +680,14 @@ ivas_error core_switching_post_dec( synth[i + delay_comp] = ( synth[i + delay_comp] * i + ( tmpDelta - i ) * st->previoussynth[i + delay_comp] ) / tmpDelta; } +#ifdef FIX_ISM_DTX_CLICKS + if ( ( st->element_mode == IVAS_CPE_MDCT || ( ivas_format == ISM_FORMAT && st->core == TCX_20_CORE /* <- means TCX in general, TCX10 is forbidden after ACELP */ ) ) && st->last_core_brate <= SID_2k40 && st->core_brate > SID_2k40 ) +#else if ( st->element_mode == IVAS_CPE_MDCT && st->last_core_brate <= SID_2k40 && st->core_brate > SID_2k40 ) +#endif { /* smooth transitions to avoid pops in car noise items */ - smoothTransitionMdctStereoDtx( synth, output_frame, delay_comp ); + smoothTransitionDtxToTcx( synth, output_frame, delay_comp ); } /* Reset memories of CLDFBs */ @@ -1001,7 +1035,7 @@ void bandwidth_switching_detect( { st->bws_cnt1 = 0; } - else if ( st->total_brate > ACELP_9k60 && st->last_core_brate < ACELP_9k60 && st->bwidth == SWB && st->last_bwidth == WB ) + else if ( st->total_brate > ACELP_9k60 && st->last_core_brate < ACELP_9k60 && st->bwidth == SWB && st->last_bwidth == WB && st->last_low_rate_mode == 0 ) { st->bws_cnt1++; } @@ -1048,7 +1082,7 @@ void bw_switching_pre_proc( if ( st->element_mode > EVS_MONO ) { - if ( st->core == ACELP_CORE && !( st->bfi == 1 && st->con_tcx == 1 ) && st->hBWE_FD != NULL && !( st->core_brate <= SID_2k40 && st->element_mode == IVAS_CPE_DFT && nchan_out == 2 ) && !( st->element_mode == IVAS_CPE_MDCT && nchan_out == 1 && st->idchan == 1 && last_element_brate <= IVAS_SID_4k4 ) ) + if ( st->core == ACELP_CORE && !( st->bfi == 1 && st->con_tcx == 1 ) && st->hBWE_FD != NULL && !( st->core_brate <= SID_2k40 && st->element_mode == IVAS_CPE_DFT && nchan_out == 2 ) && !( st->element_mode == IVAS_CPE_MDCT && nchan_out == 1 && st->idchan == 1 && last_element_brate <= IVAS_SID_5k2 ) ) { /* Calculate tilt of the ACELP core synthesis - needed in SWB BWE decoding */ calc_tilt_bwe( old_syn_12k8_16k, &st->tilt_wb, st->L_frame ); @@ -1218,16 +1252,16 @@ static void core_switch_lb_upsamp( } /*---------------------------------------------------------------------* - * smoothTransitionMdctStereoDtx() + * smoothTransitionDtxToTcx() * - * apply smoothing to the transition part for MDCT-Stereo DTX + * apply smoothing to the transition part for inactive to active transitions in DTX *---------------------------------------------------------------------*/ #define TRANSITION_SMOOTHING_LEN_16k 15 #define TRANSITION_SMOOTHING_LEN_32k 31 #define TRANSITION_SMOOTHING_LEN_48k 47 -static void smoothTransitionMdctStereoDtx( +static void smoothTransitionDtxToTcx( float synth[], /* i/o: synthesis */ const int16_t output_frame, /* i : output frame length */ const int16_t delay_comp /* i : delay compensation in samples */ diff --git a/lib_dec/d_gain2p.c b/lib_dec/d_gain2p.c index 7a0cd8ed4f4106dc34cdb71d564775f687308b63..d2fe3e8757f6d0d2ed5443615b6318a80a2f8180 100644 --- a/lib_dec/d_gain2p.c +++ b/lib_dec/d_gain2p.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,11 +40,10 @@ #include "debug.h" #endif #include -#include "typedef.h" #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * Mode2_gain_dec_mless diff --git a/lib_dec/dec2t32.c b/lib_dec/dec2t32.c index 67981738fcb240c393388bd201156e471c2b1084..258e36da41e88431f002ec4ad80f67483ebc5113 100644 --- a/lib_dec/dec2t32.c +++ b/lib_dec/dec2t32.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* * dec_acelp_2t32() diff --git a/lib_dec/dec4t64.c b/lib_dec/dec4t64.c index 3a0a6a7e50f18bd6e376a3ad288c082702db0171..9f2ab5d1c222f7185bc122d32fc115625c6adbca 100644 --- a/lib_dec/dec4t64.c +++ b/lib_dec/dec4t64.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_dec/dec_LPD.c b/lib_dec/dec_LPD.c index 422104ac4380f7df7ea72735711ed598f66cd161..af6a937e11ee56cbe2abbb5ef47ba76ac50cd565 100644 --- a/lib_dec/dec_LPD.c +++ b/lib_dec/dec_LPD.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "cnst.h" #include "basop_proto_func.h" #include "stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -478,11 +478,7 @@ void decoder_LPD( if ( bfi && st->last_core != ACELP_CORE ) { /* PLC: [TCX: TD PLC] */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT con_tcx( st, &synthFB[0], -1.f, NULL, 0, NULL ); -#else - con_tcx( st, &synthFB[0], -1.f, NULL, 0 ); -#endif lerp( synthFB, synth, st->L_frame, st->hTcxDec->L_frameTCX ); st->con_tcx = 1; set_f( &st->mem_pitch_gain[2], st->lp_gainp, st->nb_subfr ); @@ -650,11 +646,7 @@ void decoder_LPD( TonalMDCTConceal_SaveTimeSignal( st->hTonalMDCTConc, synthFB, L_frameTCX ); } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT decoder_tcx_post( st, synth, synthFB, Aq, bfi, 0 ); -#else - decoder_tcx_post( st, synth, synthFB, Aq, bfi ); -#endif if ( st->core == TCX_20_CORE ) { diff --git a/lib_dec/dec_ace.c b/lib_dec/dec_ace.c index 24fbf3149fa49492a50507aedb2954edf750cc63..ee32d67146fdaeaf9719afad027018ca3d766609 100644 --- a/lib_dec/dec_ace.c +++ b/lib_dec/dec_ace.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * decoder_acelp() diff --git a/lib_dec/dec_acelp.c b/lib_dec/dec_acelp.c index 7ccdee8888958871d861e2fd7910ff5eca48cb49..615fa8eae1a0e14a0e2788a2cc61e897b3ca9178 100644 --- a/lib_dec/dec_acelp.c +++ b/lib_dec/dec_acelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,10 +37,9 @@ #include #include #include "options.h" -#include "typedef.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_dec/dec_acelp_tcx_main.c b/lib_dec/dec_acelp_tcx_main.c index b1bfd3e225d87eb29551e5ef57848bd16c7b0f7c..1ab6b5265945b7f5d7c1b51350c7c0844858e56a 100644 --- a/lib_dec/dec_acelp_tcx_main.c +++ b/lib_dec/dec_acelp_tcx_main.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "debug.h" #endif #include "stat_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * decode_frame_type() @@ -198,11 +198,7 @@ static void decode_frame_type( st->rate_switching_init = 1; /* Reconf Core */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT mode_switch_decoder_LPD( st, st->bwidth, st->total_brate, st->last_total_brate, frame_size_index, 0, st->element_mode ); -#else - mode_switch_decoder_LPD( st, st->bwidth, st->total_brate, st->last_total_brate, frame_size_index, 0 ); -#endif /* Reconf. CLDFB: check if the CLDFB works on the right sample rate */ if ( ( st->cldfbAna->no_channels * st->cldfbAna->no_col ) != st->L_frame ) @@ -299,7 +295,7 @@ void dec_acelp_tcx_frame( float old_bwe_exc[( PIT16k_MAX + ( L_FRAME16k + 1 ) + L_SUBFR16k ) * 2]; /* excitation buffer */ float *ptr_bwe_exc; /* pointer to BWE excitation signal in the current frame */ - wmops_sub_start( "dec_acelp_tcx_frame" ); + push_wmops( "dec_acelp_tcx_frame" ); start_bit_pos = st->next_bit_pos; if ( st->rf_flag == 1 ) @@ -483,6 +479,6 @@ void dec_acelp_tcx_frame( st->last_coder_type = INACTIVE; } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_dec/dec_amr_wb.c b/lib_dec/dec_amr_wb.c index 79c9b8d951a19c161d98b342528529ae362ad77f..29fe0a253eb2d65ae1ab650a5efe4730181f7961 100644 --- a/lib_dec/dec_amr_wb.c +++ b/lib_dec/dec_amr_wb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * decod_amr_wb() diff --git a/lib_dec/dec_gen_voic.c b/lib_dec/dec_gen_voic.c index 97fba943dff51de12224b37cedae5aece9e625e7..c8220be8611da8f6014840912da1be0402ad74d5 100644 --- a/lib_dec/dec_gen_voic.c +++ b/lib_dec/dec_gen_voic.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * decod_gen_voic() @@ -64,11 +64,11 @@ ivas_error decod_gen_voic( float *bwe_exc, /* o : excitation for SWB TBE */ int16_t *unbits, /* number of unused bits */ float *gain_buf, /* o : floating pitch gain for each subframe */ - const int16_t tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ - const float tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ + const int16_t tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const float tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ ) { - int16_t T0 = PIT_MIN, T0_frac = 0, T0_min, T0_max; /* integer pitch variables */ + int16_t T0 = PIT_MIN, T0_frac = 0, T0_min, T0_max; /* integer pitch variables */ float gain_pit = 0.0f; /* pitch gain */ float gain_code = 0.0f; /* gain/normalized gain of the algebraic excitation */ float norm_gain_code = 0.0f; /* normalized gain of the algebraic excitation */ @@ -264,7 +264,6 @@ ivas_error decod_gen_voic( return error; } - DTFS_to_fs( st->hWIDec->old_exc2 + shft_prev, (int16_t) rint_new( st->bfi_pitch ), PREVP, (int16_t) st->output_Fs, do_WI ); DTFS_to_fs( exc2 + shft_curr, (int16_t) rint_new( pitch_buf[NB_SUBFR16k - 1] ), CURRP, (int16_t) st->output_Fs, do_WI ); @@ -274,7 +273,6 @@ ivas_error decod_gen_voic( return error; } - mvr2r( out, exc2, st->L_frame ); mvr2r( exc2, exc, st->L_frame ); @@ -287,8 +285,8 @@ ivas_error decod_gen_voic( } } - count_free( PREVP ); - count_free( CURRP ); + free( PREVP ); + free( CURRP ); } } diff --git a/lib_dec/dec_higher_acelp.c b/lib_dec/dec_higher_acelp.c index 32b5b705140898daff04d4f7e6da776cc3395f81..1990de936324fd044c1a0e27d1bb8de532a8560c 100644 --- a/lib_dec/dec_higher_acelp.c +++ b/lib_dec/dec_higher_acelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * transf_cdbk_dec() diff --git a/lib_dec/dec_nelp.c b/lib_dec/dec_nelp.c index 2cdcd126dbe9f6fce3fca8ba0aa92f3d103a9520..8516f4cfd1c7b4589342d13fd1e5395d625db340 100644 --- a/lib_dec/dec_nelp.c +++ b/lib_dec/dec_nelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * decod_nelp() diff --git a/lib_dec/dec_pit_exc.c b/lib_dec/dec_pit_exc.c index 547e321aaf3d420ce214927331f45ab82ece3521..2b67a6042f4a0f06042fa9da9cc21679230f9eb7 100644 --- a/lib_dec/dec_pit_exc.c +++ b/lib_dec/dec_pit_exc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * dec_pit_exc() diff --git a/lib_dec/dec_post.c b/lib_dec/dec_post.c index 9c90fcac62cda90e5df017d9a0d37a25d79489c4..6c5cd0423be8199e2cd6f4f5186fdd96a84046a7 100644 --- a/lib_dec/dec_post.c +++ b/lib_dec/dec_post.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_dec/dec_ppp.c b/lib_dec/dec_ppp.c index c6a274bef4f94fdb556139863e4dcf9fda554a18..b36f9190a1cbb2e2d3dbdb0783f007c08407fc8f 100644 --- a/lib_dec/dec_ppp.c +++ b/lib_dec/dec_ppp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * decod_ppp() diff --git a/lib_dec/dec_prm.c b/lib_dec/dec_prm.c index c6d2b1a439f49b94873da1b02268adbd1060a9df..d2e9aa26efb77b2a557d314e6de50096565940ff 100644 --- a/lib_dec/dec_prm.c +++ b/lib_dec/dec_prm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -53,12 +53,9 @@ *--------------------------------------------------------------------*/ void getTCXMode( - Decoder_State *st, /* i/o: decoder memory state */ - Decoder_State *st0 /* i : bitstream */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t MCT_flag -#endif + Decoder_State *st, /* i/o: decoder memory state */ + Decoder_State *st0, /* i : bitstream */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { uint16_t ind; @@ -94,7 +91,6 @@ void getTCXMode( } st->coder_type = INACTIVE; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) { st->VAD = get_next_indice( st0, 1 ); @@ -103,9 +99,6 @@ void getTCXMode( { st->VAD = 0; } -#else - st->VAD = 0; -#endif } else { @@ -212,13 +205,11 @@ void getTCXMode( *--------------------------------------------------------------------*/ void getTCXWindowing( - const int16_t core, /* i : current core */ - const int16_t last_core, /* i : last frame core */ -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - const int16_t element_mode, -#endif - TCX_CONFIG_HANDLE hTcxCfg, /* i/o: TCX configuration handle */ - Decoder_State *st0 /* i : bitstream */ + const int16_t core, /* i : current core */ + const int16_t last_core, /* i : last frame core */ + const int16_t element_mode, /* i : element mode */ + TCX_CONFIG_HANDLE hTcxCfg, /* i/o: TCX configuration handle */ + Decoder_State *st0 /* i : bitstream */ ) { int16_t overlap_code; @@ -262,7 +253,6 @@ void getTCXWindowing( } } -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 if ( element_mode != EVS_MONO && core == TCX_10_CORE ) { /* also read last overlap */ @@ -275,7 +265,6 @@ void getTCXWindowing( hTcxCfg->tcx_last_overlap_mode = overlap_code; } -#endif return; } @@ -793,15 +782,11 @@ void dec_prm( } /*--------------------------------------------------------------------------------* - * EVS header + * core-coder header *--------------------------------------------------------------------------------*/ /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT getTCXMode( st, st, 0 /* <- MCT_flag */ ); -#else - getTCXMode( st, st ); -#endif core = st->core; /* Decode last_core for error concealment */ @@ -840,11 +825,7 @@ void dec_prm( if ( !st->use_partial_copy ) { -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 getTCXWindowing( st->core, st->last_core, st->element_mode, st->hTcxCfg, st ); -#else - getTCXWindowing( st->core, st->last_core, st->hTcxCfg, st ); -#endif if ( st->enableGplc ) /* SIDE INFO. DECODING */ { diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c index ae5faa4d73a1dd7473a6350b7892f9353f76cc66..fbdd150217ff246abdd3ca4cbe898278b5ef06d2 100644 --- a/lib_dec/dec_tcx.c +++ b/lib_dec/dec_tcx.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include #include "stat_com.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_rom_com.h" #ifdef DEBUG_PLOT #include "deb_out.h" @@ -98,24 +98,20 @@ void decoder_tcx( init_tcx_info( st, L_frame_glob, L_frameTCX_glob, frame_cnt, bfi, &tcx_offset, &tcx_offsetFB, &L_frame, &L_frameTCX, &left_rect, &L_spec ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - decoder_tcx_invQ( st, prm, A, Aind, L_spec, L_frame, L_frameTCX, &x[0], &gainlpc2[0], &xn_buf[0], &fUseTns, &tnsData, &gain_tcx, &prm_sqQ, &nf_seed, bfi, 0, /* <- isMCT */ frame_cnt ); -#else decoder_tcx_invQ( st, prm, A, Aind, L_spec, L_frame, L_frameTCX, &x[0], &gainlpc2[0], &xn_buf[0], &fUseTns, &tnsData, &gain_tcx, &prm_sqQ, &nf_seed, bfi, frame_cnt ); -#endif -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT decoder_tcx_noisefilling( st, NULL, A, L_frameTCX_glob, L_spec, L_frame, L_frameTCX, &x[0], &gainlpc2[0], &tmp_concealment_method, gain_tcx, prm_sqQ, nf_seed, bfi, 0, frame_cnt ); -#else - decoder_tcx_noisefilling( st, A, L_frameTCX_glob, L_spec, L_frame, L_frameTCX, &x[0], &gainlpc2[0], &tmp_concealment_method, gain_tcx, prm_sqQ, nf_seed, bfi, frame_cnt ); -#endif decoder_tcx_noiseshaping_igf( st, L_spec, L_frame, L_frameTCX, left_rect, &x[0], &gainlpc2[0], &tmp_concealment_method, bfi ); decoder_tcx_tns( st, L_frame_glob, L_spec, L_frame, L_frameTCX, &x[0], fUseTns, &tnsData, bfi, frame_cnt, 0 ); decoder_tcx_imdct( st, L_frame_glob, L_frameTCX_glob, L_spec, tcx_offset, tcx_offsetFB, L_frame, L_frameTCX, left_rect, &x[0], &xn_buf[0], MDCT_IV, - fUseTns, &synth[0], &synthFB[0], bfi, frame_cnt, 0, sba_dirac_stereo_flag ); + fUseTns, &synth[0], &synthFB[0], bfi, frame_cnt, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + 0, +#endif + sba_dirac_stereo_flag ); return; } @@ -128,15 +124,12 @@ void decoder_tcx( *-------------------------------------------------------------------*/ void decoder_tcx_post( - Decoder_State *st, - float *synth, - float *synthFB, - float *A, - const int16_t bfi -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t isMCT -#endif + Decoder_State *st, /* i/o: decoder memory state */ + float *synth, /* i/o: synthesis */ + float *synthFB, /* i/o: FB synthesis */ + float *A, /* i : A(z) filter coefficients */ + const int16_t bfi, /* i : Bad frame indicator */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { int16_t i; @@ -163,7 +156,7 @@ void decoder_tcx_post( if ( bfi && !st->use_partial_copy ) { /* run lpc gain compensation not for waveform adjustment */ - if ( !st->enablePlcWaveadjust || st->hPlcInfo->concealment_method == TCX_TONAL ) + if ( !st->enablePlcWaveadjust || ( st->hPlcInfo != NULL && st->hPlcInfo->concealment_method == TCX_TONAL ) ) { float gainHelperFB = hTcxDec->gainHelper; float stepCompensateFB = hTcxDec->stepCompensate * st->L_frame / hTcxDec->L_frameTCX; @@ -188,11 +181,7 @@ void decoder_tcx_post( /* PLC: [TCX: Fade-out] * PLC: update or retrieve the background level */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - if ( bfi == 0 && st->tcxonly && ( st->element_mode != IVAS_CPE_MDCT || isMCT ) && st->clas_dec == UNVOICED_CLAS ) -#else - if ( bfi == 0 && st->tcxonly && st->clas_dec == UNVOICED_CLAS ) -#endif + if ( bfi == 0 && st->tcxonly && ( st->element_mode != IVAS_CPE_MDCT || MCT_flag ) && st->clas_dec == UNVOICED_CLAS ) { minimumStatistics( hTcxDec->NoiseLevelMemory_bfi, &hTcxDec->NoiseLevelIndex_bfi, &hTcxDec->CurrLevelIndex_bfi, &hTcxDec->CngLevelBackgroundTrace_bfi, &hTcxDec->LastFrameLevel_bfi, level_syn, PLC_MIN_CNG_LEV, PLC_MIN_STAT_BUFF_SIZE ); } @@ -206,6 +195,18 @@ void decoder_tcx_post( if ( st->tcxonly ) { gainCNG = hTcxDec->CngLevelBackgroundTrace_bfi / ( level_syn + 0.01f ); + + if ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) + { + if ( st->nbLostCmpt > MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME + MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN ) + { + gainCNG = 0.f; + } + else if ( st->nbLostCmpt > MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) + { + gainCNG *= 1.f - (float) ( st->nbLostCmpt - MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN; + } + } } else { @@ -333,7 +334,17 @@ void IMDCT( /* number of zero for ALDO windows*/ nz = NS2SA( st->output_Fs, N_ZERO_MDCT_NS ) * L_frame / L_frameTCX; - if ( ( L_frameTCX == hTcxDec->L_frameTCX >> 1 || st->mct_chan_mode == MCT_CHAN_MODE_LFE ) && ( st->tcxonly ) ) + if ( st->element_mode != EVS_MONO && frame_cnt == 0 && !bfi && st->prev_bfi && ( st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE ) && !hTcxCfg->last_aldo ) + { + v_multc( old_syn_overl, hTcxDec->conceal_eof_gain * st->last_concealed_gain_syn_deemph, old_syn_overl, overlap ); + } + + if ( ( L_frameTCX == hTcxDec->L_frameTCX >> 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || st->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) && + ( st->tcxonly ) ) { /* Mode decision in PLC @@ -352,7 +363,9 @@ void IMDCT( if ( ( !bfi && hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) || ( bfi && ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) && ( hTcxCfg->tcx_curr_overlap_mode != FULL_OVERLAP ) ) ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE assert( st->mct_chan_mode != MCT_CHAN_MODE_LFE ); +#endif /* minimum or half overlap, two transforms, grouping into one window */ L_win = L_frame >> 1; L_ola = ( hTcxCfg->tcx_last_overlap_mode == MIN_OVERLAP ) ? tcx_mdct_window_min_length : tcx_mdct_window_half_length; @@ -390,7 +403,11 @@ void IMDCT( /* To assure that no garbage values are passed to overlap */ set_zero( xn_buf + L_frame + tcx_offset + ( L_ola >> 1 ), overlap - tcx_offset - ( L_ola >> 1 ) ); } - else if ( !bfi && ( frame_cnt == 0 ) && ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + else if ( !bfi && ( frame_cnt == 0 ) && ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { /* special overlap attempt, two transforms, grouping into one window */ @@ -551,7 +568,13 @@ void IMDCT( /* Window and overlap-add past frame if past frame is TCX */ if ( ( frame_cnt != 0 ) || ( st->last_core_bfi > ACELP_CORE ) ) { - if ( ( ( L_frameTCX == hTcxDec->L_frameTCX >> 1 || st->mct_chan_mode == MCT_CHAN_MODE_LFE ) && ( st->tcxonly ) ) || ( hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ) + if ( ( ( L_frameTCX == hTcxDec->L_frameTCX >> 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || st->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) && + ( st->tcxonly ) ) || + ( hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ) { if ( !bfi && ( frame_cnt > 0 ) && ( index == 0 ) && ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( st->last_core != ACELP_CORE ) ) { @@ -614,7 +637,11 @@ void IMDCT( } } - if ( !aldo && ( ( ( L_frameTCX == hTcxDec->L_frameTCX >> 1 ) && frame_cnt > 0 ) || L_frameTCX != ( hTcxDec->L_frameTCX >> 1 ) ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( !aldo && ( ( ( L_frameTCX == hTcxDec->L_frameTCX >> 1 ) && frame_cnt > 0 ) || L_frameTCX != ( hTcxDec->L_frameTCX >> 1 ) ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { /* Compute windowed synthesis in case of switching to ALDO windows in next frame */ mvr2r( xn_buf + L_frame - nz, old_out, nz + overlap ); @@ -695,10 +722,7 @@ void decoder_tcx_invQ( float *gain_tcx, const int16_t **prm_sqQ1, int16_t *nf_seed, - const int16_t bfi, /* i : Bad frame indicator */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t isMCT, -#endif + const int16_t bfi, /* i : Bad frame indicator */ const int16_t frame_cnt /* i : frame counter in the super frame */ ) { @@ -913,16 +937,7 @@ void decoder_tcx_invQ( hTcxDec->damping = 1; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - else if ( st->element_mode == IVAS_CPE_MDCT && st->nbLostCmpt >= MDCT_ST_PLC_FADEOUT_START_FRAME ) - { - *gain_tcx = hTcxDec->old_gaintcx_bfi; - hTcxDec->damping = Damping_fact( st->coder_type, st->nbLostCmpt - MDCT_ST_PLC_FADEOUT_START_FRAME, st->last_good, st->stab_fac, &( st->lp_gainp ), st->last_core ); - } - else if ( st->element_mode != IVAS_CPE_MDCT || !isMCT ) -#else else -#endif { *gain_tcx = hTcxDec->old_gaintcx_bfi; hTcxDec->damping = Damping_fact( st->coder_type, st->nbLostCmpt, st->last_good, st->stab_fac, &( st->lp_gainp ), st->last_core ); @@ -1079,9 +1094,7 @@ void decoder_tcx_invQ( void decoder_tcx_noisefilling( Decoder_State *st, /* i/o: coder memory state */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT float concealment_noise[L_FRAME48k], -#endif const float A[], /* i : coefficients NxAz[M+1] */ const int16_t L_frameTCX_glob, const int16_t L_spec, @@ -1094,9 +1107,7 @@ void decoder_tcx_noisefilling( const int16_t *prm_sqQ, int16_t nf_seed, const int16_t bfi, /* i : Bad frame indicator */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t isMCT, -#endif + const int16_t MCT_flag, const int16_t frame_cnt /* i : frame counter in the super frame*/ ) { @@ -1120,23 +1131,7 @@ void decoder_tcx_noisefilling( *-----------------------------------------------------------------*/ /* Init lengths */ - if ( st->igf == 0 ) - { - if ( st->narrowBand == 0 ) - { - /* minimum needed for output with sampling rates lower then the - nominal sampling rate */ - infoIGFStartLine = min( L_frameTCX, L_frame ); - } - else - { - infoIGFStartLine = L_frameTCX; - } - } - else - { - infoIGFStartLine = min( st->hIGFDec->infoIGFStartLine, L_frameTCX ); - } + infoIGFStartLine = get_igf_startline( st, L_frame, L_frameTCX ); noiseFillingSize = L_spec; if ( st->igf ) @@ -1246,13 +1241,8 @@ void decoder_tcx_noisefilling( if ( st->hTonalMDCTConc != NULL ) { if ( !bfi && st->element_mode != IVAS_CPE_MDCT ) - { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x, L_frameTCX, L_frame, gainlpc2, infoIGFStartLine ); -#else - TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x, L_frameTCX, L_frame, gainlpc2 ); -#endif } else if ( bfi ) { @@ -1261,11 +1251,7 @@ void decoder_tcx_noisefilling( { /* set f to 1 to not fade out */ /* set f to 0 to immediately switch to white noise */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - if ( st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) -#else - if ( st->tcxonly ) -#endif + if ( st->tcxonly && ( st->element_mode != IVAS_CPE_MDCT || MCT_flag ) ) { f = 1.0f; } @@ -1304,18 +1290,14 @@ void decoder_tcx_noisefilling( noiseTiltFactor = 1.0f; tcxGetNoiseFillingTilt( A, L_frame, ( total_brate >= ACELP_13k20 && !st->rf_flag ), &noiseTiltFactor ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - if ( st->element_mode == IVAS_CPE_MDCT && !isMCT ) + if ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) { - TonalMDCTConceal_InsertNoise( st->hTonalMDCTConc, x, st->tonal_mdct_plc_active, &st->seed_tcx_plc, noiseTiltFactor, f, concealment_noise, infoIGFStartLine ); + TonalMDCTConceal_InsertNoise( st->hTonalMDCTConc, x, st->tonal_mdct_plc_active, &st->seed_tcx_plc, noiseTiltFactor, f, concealment_noise, hTcxDec->CngLevelBackgroundTrace_bfi, infoIGFStartLine ); } else { - TonalMDCTConceal_InsertNoise( st->hTonalMDCTConc, x, st->tonal_mdct_plc_active, &st->seed_tcx_plc, noiseTiltFactor, f, NULL, infoIGFStartLine ); + TonalMDCTConceal_InsertNoise( st->hTonalMDCTConc, x, st->tonal_mdct_plc_active, &st->seed_tcx_plc, noiseTiltFactor, f, NULL, hTcxDec->CngLevelBackgroundTrace_bfi, infoIGFStartLine ); } -#else - TonalMDCTConceal_InsertNoise( st->hTonalMDCTConc, x, st->tonal_mdct_plc_active, &st->seed_tcx_plc, noiseTiltFactor, f, infoIGFStartLine ); -#endif } } } @@ -1353,18 +1335,23 @@ void decoder_tcx_noisefilling( IGFDecReplicateTCX10State( st->hIGFDec ); } - if ( st->igf ) + if ( st->element_mode != EVS_MONO ) { - if ( bfi && st->element_mode != EVS_MONO ) + if ( bfi ) { - *st->hIGFDec->igfData.igfInfo.nfSeed = (int16_t) ( st->seed_tcx_plc * 31821L + 13849L ); + nf_seed = st->seed_tcx_plc; } - else + else if ( nf_seed == 0 ) { - *st->hIGFDec->igfData.igfInfo.nfSeed = (int16_t) ( nf_seed * 31821L + 13849L ); + nf_seed = *st->hIGFDec->igfData.igfInfo.nfSeed; } } + if ( st->igf ) + { + *st->hIGFDec->igfData.igfInfo.nfSeed = (int16_t) ( nf_seed * 31821L + 13849L ); + } + return; } @@ -1393,11 +1380,7 @@ void decoder_tcx_noiseshaping_igf( * Noise shaping in frequency domain (1/Wz) * *-----------------------------------------------------------*/ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( st->igf && ( !bfi || ( st->element_mode == IVAS_CPE_MDCT && st->prev_bfi ) ) ) -#else - if ( st->igf && !bfi ) -#endif { if ( ( L_frame == st->L_frame >> 1 ) && ( st->tcxonly ) ) { @@ -1517,11 +1500,6 @@ void decoder_tcx_tns( isTCX5 = 1; tcx5SpectrumDeinterleaving( L >> 1, x ); - - if ( hTcxCfg->fIsTNSAllowed && fUseTns != 0 && bfi != 1 && tnsData->tnsOnWhitenedSpectra == whitenedDomain ) - { - tcx5TnsGrouping( L >> 1, hTcxCfg->tnsConfig[0][0].iFilterBorders[0] >> 1, x ); - } } } @@ -1539,6 +1517,11 @@ void decoder_tcx_tns( /* Apply TNS to get the reconstructed signal */ SetTnsConfig( hTcxCfg, L_frame_glob == st->L_frame, ( st->last_core == ACELP_CORE ) && ( frame_cnt == 0 ) ); + if ( ( L_frame == st->L_frame >> 1 ) && st->tcxonly && isTCX5 ) + { + tcx5TnsGrouping( L >> 1, hTcxCfg->tnsConfig[0][0].iFilterBorders[0] >> 1, x ); + } + ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, tnsData, x, 0 ); #ifdef DEBUG_PLOT sendDebout( "tnsSpec2", L_frameTCX, 1, "aftTNS", MTV_FLOAT, x ); @@ -1546,7 +1529,14 @@ void decoder_tcx_tns( if ( ( L_frame == st->L_frame >> 1 ) && st->tcxonly && isTCX5 ) { - tcx5TnsUngrouping( L_frameTCX >> 1, hTcxCfg->tnsConfig[0][0].iFilterBorders[0] >> 1, x, DEC ); + if ( st->element_mode == EVS_MONO || L_spec < L_frameTCX ) /* TBC: this is temporary to maintain EVS BE, this is a bug and should be fixed also for EVS (see issue 13) */ + { + tcx5TnsUngrouping( L_frameTCX >> 1, hTcxCfg->tnsConfig[0][0].iFilterBorders[0] >> 1, x, DEC ); + } + else + { + tcx5TnsUngrouping( L >> 1, hTcxCfg->tnsConfig[0][0].iFilterBorders[0] >> 1, x, DEC ); + } } } @@ -1592,9 +1582,11 @@ void decoder_tcx_imdct( const int16_t fUseTns, /* i : flag that is set if TNS data is present */ float synth[], /* i/o: synth[-M..L_frame] */ float synthFB[], - const int16_t bfi, /* i : Bad frame indicator */ - const int16_t frame_cnt, /* i : frame counter in the super frame */ - const int16_t isLFE, /* i : is LFE */ + const int16_t bfi, /* i : Bad frame indicator */ + const int16_t frame_cnt, /* i : frame counter in the super frame */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t isLFE, /* i : is LFE */ +#endif const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ ) { @@ -1626,7 +1618,11 @@ void decoder_tcx_imdct( hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode; } - if ( !isLFE && st->igf ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + !isLFE && +#endif + st->igf ) { proc = st->hIGFDec->flatteningTrigger; @@ -1724,7 +1720,18 @@ void decoder_tcx_imdct( if ( st->element_mode != IVAS_CPE_DFT && !sba_dirac_stereo_flag ) { - IMDCT( xn_bufFB, hTcxDec->syn_Overl, hTcxDec->syn_Overl_TDAC, xn_buf, st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_window : hTcxCfg->tcx_aldo_window_1_trunc, st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_window : hTcxCfg->tcx_aldo_window_2, hTcxCfg->tcx_mdct_window_half, hTcxCfg->tcx_mdct_window_minimum, hTcxCfg->tcx_mdct_window_trans, hTcxCfg->tcx_mdct_window_half_length, hTcxCfg->tcx_mdct_window_min_length, index, + IMDCT( xn_bufFB, hTcxDec->syn_Overl, hTcxDec->syn_Overl_TDAC, xn_buf, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_window : hTcxCfg->tcx_aldo_window_1_trunc, +#else + hTcxCfg->tcx_aldo_window_1_trunc, +#endif +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_window : hTcxCfg->tcx_aldo_window_2, +#else + hTcxCfg->tcx_aldo_window_2, +#endif + hTcxCfg->tcx_mdct_window_half, hTcxCfg->tcx_mdct_window_minimum, hTcxCfg->tcx_mdct_window_trans, hTcxCfg->tcx_mdct_window_half_length, hTcxCfg->tcx_mdct_window_min_length, index, kernelType, left_rect, tcx_offset, overlap, L_frame, L_frameTCX, max( L_frameTCX, L_spec ) >> 1, L_frame_glob, frame_cnt, bfi, st->hHQ_core->old_outLB, 0, st, 0, acelp_zir ); } @@ -1744,7 +1751,13 @@ void decoder_tcx_imdct( if ( st->element_mode != EVS_MONO ) { - IMDCT( x_tmp, hTcxDec->syn_OverlFB, hTcxDec->syn_Overl_TDACFB, xn_bufFB, st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_windowFB : hTcxCfg->tcx_aldo_window_1_FB_trunc, st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_windowFB : hTcxCfg->tcx_aldo_window_2_FB, hTcxCfg->tcx_mdct_window_halfFB, hTcxCfg->tcx_mdct_window_minimumFB, hTcxCfg->tcx_mdct_window_transFB, hTcxCfg->tcx_mdct_window_half_lengthFB, hTcxCfg->tcx_mdct_window_min_lengthFB, index, + IMDCT( x_tmp, hTcxDec->syn_OverlFB, hTcxDec->syn_Overl_TDACFB, xn_bufFB, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_windowFB : hTcxCfg->tcx_aldo_window_1_FB_trunc, st->mct_chan_mode == MCT_CHAN_MODE_LFE ? hTcxCfg->tcx_mdct_windowFB : hTcxCfg->tcx_aldo_window_2_FB, +#else + hTcxCfg->tcx_aldo_window_1_FB_trunc, hTcxCfg->tcx_aldo_window_2_FB, +#endif + hTcxCfg->tcx_mdct_window_halfFB, hTcxCfg->tcx_mdct_window_minimumFB, hTcxCfg->tcx_mdct_window_transFB, hTcxCfg->tcx_mdct_window_half_lengthFB, hTcxCfg->tcx_mdct_window_min_lengthFB, index, kernelType, left_rect, tcx_offsetFB, overlapFB, L_frameTCX, L_frameTCX, max( L_frameTCX, L_spec ) >> 1, L_frameTCX_glob, frame_cnt, bfi, st->hHQ_core->old_out, 1, st, FSCALE_DENOM * L_frameTCX_glob / L_frame_glob, acelp_zir ); } else @@ -1936,14 +1949,15 @@ void decoder_tcx_IGF_mono( *-------------------------------------------------------------------*/ void decoder_tcx_IGF_stereo( - Decoder_State **sts, /* i/o: coder memory states */ - STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo structure */ - int16_t ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ - float *x[CPE_CHANNELS][NB_DIV], /* o : de-quatized coefficients */ - const int16_t L_frame, /* i : frame length */ - const int16_t left_rect, /* i : left part is rectangular */ - const int16_t k, /* i : Subframe index */ - const int16_t bfi /* i : bad frame indicator */ + Decoder_State **sts, /* i/o: coder memory states */ + STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo structure */ + int16_t ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ + float *x[CPE_CHANNELS][NB_DIV], /* o : de-quatized coefficients */ + const int16_t L_frame, /* i : frame length */ + const int16_t left_rect, /* i : left part is rectangular */ + const int16_t k, /* i : Subframe index */ + const int16_t bfi, /* i : bad frame indicator */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { int16_t coreMsMask[N_MAX]; @@ -1996,7 +2010,7 @@ void decoder_tcx_IGF_stereo( igfGridIdx = ( sts[0]->last_core == ACELP_CORE || ( left_rect && bfi ) ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM; } - IGFDecApplyStereo( sts[0]->hIGFDec, sts[1]->hIGFDec, x[0][k], x[1][k], igfGridIdx, coreMsMask, hStereoMdct->IGFStereoMode[k] == SMDCT_BW_MS, bfi ); + IGFDecApplyStereo( sts[0]->hIGFDec, sts[1]->hIGFDec, x[0][k], x[1][k], igfGridIdx, coreMsMask, hStereoMdct->IGFStereoMode[k] == SMDCT_BW_MS, bfi, MCT_flag ); } return; diff --git a/lib_dec/dec_tran.c b/lib_dec/dec_tran.c index 7120211fb61a767b6937e68c833b873f3b7078ee..875ce5eabf3449bcd087dffd7b81e08556d4270b 100644 --- a/lib_dec/dec_tran.c +++ b/lib_dec/dec_tran.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * decod_tran() diff --git a/lib_dec/dec_uv.c b/lib_dec/dec_uv.c index 28395210910cc7cf83a9494d4c7edf0cac532fce..63c4b1d3bdcffbb529c280865e84b629e68a5399 100644 --- a/lib_dec/dec_uv.c +++ b/lib_dec/dec_uv.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * decod_unvoiced() diff --git a/lib_dec/decision_matrix_dec.c b/lib_dec/decision_matrix_dec.c index 348e57a3e486b7f0ed687ce6bc9ea4f305de7f9a..84e6e9573e20eb5f2df4788a644e6e4bc1903a45 100644 --- a/lib_dec/decision_matrix_dec.c +++ b/lib_dec/decision_matrix_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,13 +42,13 @@ #include "stat_dec.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * decision_matrix_dec() * * ACELP/HQ core selection - * Read ACELP signalling bits from the bitstream + * Read ACELP signaling bits from the bitstream * Set extension layers *-----------------------------------------------------------------*/ @@ -208,12 +208,12 @@ void decision_matrix_dec( } /*-----------------------------------------------------------------* - * Read ACELP signalling bits from the bitstream + * Read ACELP signaling bits from the bitstream *-----------------------------------------------------------------*/ if ( st->core == ACELP_CORE ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ start_idx = 0; while ( acelp_sig_tbl[start_idx] != st->total_brate ) { @@ -240,10 +240,10 @@ void decision_matrix_dec( } else { - /* retrieve the signalling indice */ + /* retrieve the signaling indice */ ind = acelp_sig_tbl[start_idx]; - /* convert signalling indice into signalling information */ + /* convert signaling indice into signaling information */ st->coder_type = ind & 0x7; if ( st->coder_type == LR_MDCT ) { @@ -257,7 +257,7 @@ void decision_matrix_dec( } } - /* detect corrupted signalling (due to bit errors) */ + /* detect corrupted signaling (due to bit errors) */ if ( ( st->BER_detect ) || ( ind >= 1 << 7 ) || ( st->total_brate <= ACELP_13k20 && st->bwidth == FB ) || @@ -408,7 +408,7 @@ void decision_matrix_dec( /*-----------------------------------------------------------------* - * Read HQ signalling bits from the bitstream + * Read HQ signaling bits from the bitstream * Set HQ core type *-----------------------------------------------------------------*/ @@ -464,7 +464,7 @@ void decision_matrix_dec( } } - /* detect bit errors in signalling */ + /* detect bit errors in signaling */ if ( ( ( st->total_brate >= ACELP_24k40 && st->bwidth == NB ) || ( st->core == HQ_CORE && st->total_brate <= LRMDCT_CROSSOVER_POINT && st->bwidth == FB ) ) ) { diff --git a/lib_dec/dlpc_avq.c b/lib_dec/dlpc_avq.c index 83a0029fb3e08dc91b39ab0a6a319128d8cc0c1d..b4a95fd74d5369d449c1386a2fa889a9cf95d3a9 100644 --- a/lib_dec/dlpc_avq.c +++ b/lib_dec/dlpc_avq.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * dlpc_avq() @@ -57,7 +57,6 @@ int16_t dlpc_avq( int16_t *p_index, q_type; /* Last LPC index */ - if ( numlpc == 1 ) { last = 0; diff --git a/lib_dec/dlpc_stoch.c b/lib_dec/dlpc_stoch.c index 59ec142c0a54214e844a734a06030945e59bacc6..1bbba46b1b2c9c18fcddd5a3eaf0123d95318d18 100644 --- a/lib_dec/dlpc_stoch.c +++ b/lib_dec/dlpc_stoch.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_com.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * lpc_unquantize() @@ -71,6 +71,7 @@ void lpc_unquantize( if ( st->lpcQuantization == 0 ) { nb_indices = dlpc_avq( param_lpc, &lsf[M], st->numlpc, st->sr_core ); + for ( k = 0; k < st->numlpc; k++ ) { lsf2lsp( &lsf[( k + 1 ) * M], &lsp[( k + 1 ) * M], M, st->sr_core ); diff --git a/lib_dec/er_dec_acelp.c b/lib_dec/er_dec_acelp.c index 4e0d5c9b482257ad4c6681a921320ad3b9301fb6..7024cfb3f848a0557fb1f826062091ec7ac7b805 100644 --- a/lib_dec/er_dec_acelp.c +++ b/lib_dec/er_dec_acelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #endif #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * con_acelp() diff --git a/lib_dec/er_dec_tcx.c b/lib_dec/er_dec_tcx.c index 2fb4a8979ab4934901e31a1150107f335c8062a9..1ce3bf2035f97aee410f014857fefa7da3b749d1 100644 --- a/lib_dec/er_dec_tcx.c +++ b/lib_dec/er_dec_tcx.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,6 +34,8 @@ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ +#include "cnst.h" +#include "ivas_cnst.h" #include #include #include "options.h" @@ -43,7 +45,7 @@ #include #include "prot.h" #include "rom_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * con_tcx() @@ -52,16 +54,12 @@ *-----------------------------------------------------------------*/ void con_tcx( - Decoder_State *st, /* i/o: coder memory state */ - float synth[] /* i/o: synth[] */ - , - const float coh, /* i : coherence of stereo signal */ - int16_t *noise_seed, /* i/o: noise seed for stereo */ - const int16_t only_left /* i : TD-PLC only in left channel */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const float *A_cng -#endif + Decoder_State *st, /* i/o: coder memory state */ + float synth[], /* i/o: synth[] */ + const float coh, /* i : coherence of stereo signal */ + int16_t *noise_seed, /* i/o: noise seed for stereo */ + const int16_t only_left, /* i : TD-PLC only in left channel */ + const float A_cng[] /* i : CNG LP filter coefficients */ ) { int16_t i, n, L_frame, L_subfr, fLowPassFilter, T0; @@ -280,19 +278,7 @@ void con_tcx( st->bpf_gain_param = 0; /* PLC: calculate damping factor */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - alpha = 1.0f; - if ( st->element_mode == IVAS_CPE_MDCT && st->nbLostCmpt >= MDCT_ST_PLC_FADEOUT_START_FRAME ) - { - alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt - MDCT_ST_PLC_FADEOUT_START_FRAME, st->last_good, st->stab_fac, &( st->lp_gainp ), 0 ); - } - else if ( st->element_mode != IVAS_CPE_MDCT ) - { - alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &( st->lp_gainp ), 0 ); - } -#else - alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &( st->lp_gainp ), 0 ); -#endif + alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &( st->lp_gainp ), ACELP_CORE ); if ( st->nbLostCmpt == 1 ) { @@ -351,19 +337,7 @@ void con_tcx( set_f( pitch_buf, (float) L_SUBFR, st->nb_subfr ); /* PLC: calculate damping factor */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - alpha = 1.0f; - if ( st->element_mode == IVAS_CPE_MDCT && st->nbLostCmpt >= MDCT_ST_PLC_FADEOUT_START_FRAME ) - { - alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt - MDCT_ST_PLC_FADEOUT_START_FRAME, st->last_good, st->stab_fac, &( st->lp_gainp ), 0 ); - } - else if ( st->element_mode != IVAS_CPE_MDCT ) - { - alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &( st->lp_gainp ), 0 ); - } -#else - alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &( st->lp_gainp ), 0 ); -#endif + alpha = Damping_fact( st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &( st->lp_gainp ), ACELP_CORE ); } /*-----------------------------------------------------------------* @@ -460,7 +434,6 @@ void con_tcx( /* PLC: [TCX: Fade-out] retrieve background level */ tmp = 1.0f; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( A_cng != NULL ) { gainSynthDeemph = getLevelSynDeemph( &( tmp ), A_cng, L_frame / 4, st->preemph_fac, 1 ) / 4.f; @@ -469,12 +442,21 @@ void con_tcx( { gainSynthDeemph = getLevelSynDeemph( &( tmp ), A_local, L_frame / 4, st->preemph_fac, 1 ); } -#else - gainSynthDeemph = getLevelSynDeemph( &( tmp ), A_local, L_frame / 4, st->preemph_fac, 1 ); -#endif if ( st->tcxonly ) { gainCNG = hTcxDec->CngLevelBackgroundTrace_bfi / gainSynthDeemph; + + if ( st->element_mode == IVAS_CPE_MDCT && A_cng != NULL ) + { + if ( st->nbLostCmpt > MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME + MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN ) + { + gainCNG = 0.f; + } + else if ( st->nbLostCmpt > MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) + { + gainCNG *= 1.f - (float) ( st->nbLostCmpt - MDCT_ST_PLC_FADEOUT_MAX_CONC_FRAME ) / MDCT_ST_PLC_FADEOUT_TO_ZERO_LEN; + } + } } else { @@ -570,26 +552,12 @@ void con_tcx( mvr2r( buf, mem_syn, M ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( A_cng != NULL ) { - if ( ( st->nbLostCmpt == 1 && st->idchan == 0 ) || ( st->nbLostCmpt == 2 && st->idchan == 1 ) ) + if ( st->plcBackgroundNoiseUpdated && alpha != 1.0f ) { - float lsp_cng[M]; + float lsp_local[M], lsp_fade[M], alpha_inv; - lpc_from_spectrum( st->hFdCngDec->hFdCngCom, st->hFdCngDec->hFdCngCom->startBand, st->hFdCngDec->hFdCngCom->stopFFTbin, 0.f ); - - a2lsp_stab( st->hFdCngDec->hFdCngCom->A_cng, lsp_cng, st->lspold_cng ); - mvr2r( lsp_cng, st->lspold_cng, M ); - } - - if ( alpha != 1.0f ) - { - float lsp_local[M]; - float lsp_fade[M]; - float alpha_inv; - - wmops_sub_start( "Fade LSPs" ); alpha_inv = 1.0f - alpha; a2lsp_stab( A_local, lsp_local, lsp_local ); @@ -600,10 +568,8 @@ void con_tcx( } lsp2a_stab( lsp_fade, A_local, M ); - wmops_sub_end(); } } -#endif syn_filt( A_local, M, &exc[0], &syn[0], L_frame + ( L_frame / 2 ), mem_syn, 1 ); diff --git a/lib_dec/er_scale_syn.c b/lib_dec/er_scale_syn.c index 1ae7f57104f8055bee742b70f74caaeb89410a51..d6d048b234a115a4ddf10b64725d5e6bd44ce045 100644 --- a/lib_dec/er_scale_syn.c +++ b/lib_dec/er_scale_syn.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* diff --git a/lib_dec/er_sync_exc.c b/lib_dec/er_sync_exc.c index 3a66e8312992d048d707246b44133989c7d9726e..b28a172715875c93696b27547bbf4e2efd86bd6a 100644 --- a/lib_dec/er_sync_exc.c +++ b/lib_dec/er_sync_exc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_dec/er_util.c b/lib_dec/er_util.c index f907781c2906a66d3d754ea0871e38d76d23601e..75f553f1e83602560ac49cbedfb048e4710b23d9 100644 --- a/lib_dec/er_util.c +++ b/lib_dec/er_util.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "cnst.h" #include "stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* @@ -318,8 +318,12 @@ int16_t GetPLCModeDecision( { TonalMDCTConceal_Detect( st->hTonalMDCTConc, ( hTcxDec->tcxltp_last_gain_unmodified > 0 ) ? st->old_fpitch : 0, &numIndices, - ( st->element_mode == IVAS_CPE_MDCT ? &( st->hTcxCfg->psychParamsTCX20 ) : st->hTcxCfg->psychParamsCurrent ), - st->mct_chan_mode == MCT_CHAN_MODE_LFE ); + ( st->element_mode == IVAS_CPE_MDCT ? &( st->hTcxCfg->psychParamsTCX20 ) : st->hTcxCfg->psychParamsCurrent ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ); if ( ( numIndices > 10 ) || ( ( numIndices > 5 ) && ( fabs( hTcxDec->tcxltp_third_last_pitch - hTcxDec->tcxltp_second_last_pitch ) < 0.5f ) ) || ( ( numIndices > 0 ) && ( ( st->last_good <= UNVOICED_TRANSITION ) || ( hTcxDec->tcxltp_last_gain_unmodified <= 0.4f ) ) && ( fabs( hTcxDec->tcxltp_third_last_pitch - hTcxDec->tcxltp_second_last_pitch ) < 0.5f ) ) ) { diff --git a/lib_dec/evs_dec.c b/lib_dec/evs_dec.c index 9943ca9b980953a6857a3e4a102edacf2c6b3bf5..0dbc0feafc07ebb98963d8314b762d5e20de0e76 100644 --- a/lib_dec/evs_dec.c +++ b/lib_dec/evs_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif @@ -86,7 +86,7 @@ ivas_error evs_dec( error = IVAS_ERR_OK; - wmops_sub_start( "evs_dec" ); + push_wmops( "evs_dec" ); /*------------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ @@ -276,7 +276,11 @@ ivas_error evs_dec( * Postprocessing for ACELP/MDCT core switching *---------------------------------------------------------------------*/ +#ifdef FIX_ISM_DTX_CLICKS + if ( ( error = core_switching_post_dec( st, synth, NULL, NULL, 0, MONO_FORMAT, output_frame, core_switching_flag, 0, -1, EVS_MONO ) ) != IVAS_ERR_OK ) +#else if ( ( error = core_switching_post_dec( st, synth, NULL, NULL, 0, output_frame, core_switching_flag, 0, -1, EVS_MONO ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -285,7 +289,7 @@ ivas_error evs_dec( /*---------------------------------------------------------------------* * Pre-processing for bandwidth switching *---------------------------------------------------------------------*/ - wmops_sub_start( "BWE_decoding" ); + push_wmops( "BWE_decoding" ); bw_switching_pre_proc( st, old_syn_12k8_16k, -1, 1 ); @@ -319,7 +323,7 @@ ivas_error evs_dec( /* FB TBE decoder */ if ( output_frame == L_FRAME48k && st->extl == FB_TBE ) { - fb_tbe_dec( st, fb_exc, hb_synth, NULL ); + fb_tbe_dec( st, fb_exc, hb_synth, NULL, L_FRAME48k ); } } else if ( st->extl == SWB_BWE || st->extl == FB_BWE || ( st->output_Fs >= 32000 && st->core == ACELP_CORE && st->bwidth > NB && st->bws_cnt > 0 && !st->ppp_mode_dec && !( st->nelp_mode_dec == 1 && st->bfi == 1 ) ) ) @@ -356,7 +360,7 @@ ivas_error evs_dec( swb_CNG_dec( st, synth, hb_synth, sid_bw ); } - wmops_sub_end(); + pop_wmops(); /*----------------------------------------------------------------* * Delay ACELP core synthesis to be synchronized with the components of bandwidth extension layers @@ -600,7 +604,7 @@ ivas_error evs_dec( if ( st->extl == FB_TBE && output_frame == L_FRAME48k ) { - fb_tbe_dec( st, fb_exc, hb_synth, NULL ); + fb_tbe_dec( st, fb_exc, hb_synth, NULL, L_FRAME48k ); } } mvr2r( hb_synth, st->hBWE_TD->old_hb_synth, output_frame ); @@ -676,11 +680,7 @@ ivas_error evs_dec( st->lp_noise = st->hFdCngDec->lp_noise; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ApplyFdCng( output, NULL, realBuffer, imagBuffer, st, concealWholeFrame, 0 ); -#else - ApplyFdCng( output, realBuffer, imagBuffer, st, concealWholeFrame, 0 ); -#endif /* Generate additional comfort noise to mask potential coding artefacts */ if ( st->m_frame_type == ACTIVE_FRAME && st->flag_cna ) @@ -979,6 +979,6 @@ ivas_error evs_dec( } #endif - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_dec/fd_cng_dec.c b/lib_dec/fd_cng_dec.c index 8fd77a836dbcc658e662b3e6d337e96ddc7cffa1..ab9465a93a246c2251e998f544b2b28f501cc084 100644 --- a/lib_dec/fd_cng_dec.c +++ b/lib_dec/fd_cng_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,6 @@ ====================================================================================*/ #include -#include "typedef.h" #include #include "options.h" #ifdef DEBUGGING @@ -45,7 +44,7 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" #include "ivas_rom_dec.h" @@ -59,6 +58,14 @@ #define CNA_ACT_DN_FACT 0.7 /* downward updating factor for CNA during active frames */ #define FIRST_CNA_NOISE_UPD_FRAMES 5 /* minimum number of CN initialization frames */ + +/*------------------------------------------------------------------- + * Local fucntions declarations + *-------------------------------------------------------------------*/ + +static void perform_noise_estimation_dec( const float *timeDomainInput, float *power_spectrum, HANDLE_FD_CNG_DEC hFdCngDec, const int16_t element_mode, const int16_t bwidth, const int16_t L_frame, const int16_t last_L_frame, const int32_t last_core_brate, const int16_t VAD ); + + /*------------------------------------------------------------------- * createFdCngDec() * @@ -76,8 +83,7 @@ ivas_error createFdCngDec( *hFdCngDec = NULL; /* Allocate memory */ - hs = (HANDLE_FD_CNG_DEC) count_malloc( sizeof( FD_CNG_DEC ) ); - if ( hs == NULL ) + if ( ( hs = (HANDLE_FD_CNG_DEC) malloc( sizeof( FD_CNG_DEC ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FD CNG DEC structure" ); } @@ -352,7 +358,7 @@ void deleteFdCngDec( if ( hsDec != NULL ) { deleteFdCngCom( &( hsDec->hFdCngCom ) ); - count_free( hsDec ); + free( hsDec ); *hFdCngDec = NULL; } @@ -368,9 +374,7 @@ void deleteFdCngDec( void ApplyFdCng( float *timeDomainInput, -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT float *powerSpectrum, -#endif float **realBuffer, /* i/o: Real part of the buffer */ float **imagBuffer, /* i/o: Imaginary part of the buffer */ Decoder_State *st, @@ -384,17 +388,15 @@ void ApplyFdCng( int16_t j, k; float factor; float lsp_cng[M]; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT int16_t L_frame, last_L_frame; int32_t sr_core; - wmops_sub_start( "ApplyFdCng" ); + push_wmops( "ApplyFdCng" ); - /* limit L_frame and core fs values for MDCT-Stereo modes which can have higher core sampling than 16kHz, but use a downsampled buffer */ + /* limit L_frame and core Fs values for MDCT-Stereo modes which can have higher core sampling than 16kHz, but use a downsampled buffer */ L_frame = min( st->L_frame, L_FRAME16k ); last_L_frame = min( st->last_L_frame, L_FRAME16k ); sr_core = min( st->sr_core, INT_FS_16k ); -#endif if ( hFdCngCom->frame_type_previous == ACTIVE_FRAME ) { @@ -418,28 +420,30 @@ void ApplyFdCng( hFdCngCom->sid_frame_counter = 0; /* set noise estimation inactive during concealment, as no update with noise generated by concealment should be performed. */ /* set noise estimation inactive when we have bit errors, as no update with noise generated by corrupt frame (biterror) should be performed. */ +#ifndef DISCRETE_ISM_DTX_CNG if ( concealWholeFrame == 0 && -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ( timeDomainInput == NULL || ( *timeDomainInput( -FLT_MAX ) && *( timeDomainInput + hFdCngCom->frameSize - 1 ) < FLT_MAX && *( timeDomainInput + hFdCngCom->frameSize - 1 ) > ( -FLT_MAX ) ) ) && -#else - *timeDomainInput( -FLT_MAX ) && - *( timeDomainInput + hFdCngCom->frameSize - 1 ) < FLT_MAX && - *( timeDomainInput + hFdCngCom->frameSize - 1 ) > ( -FLT_MAX ) && -#endif ( ( ( ( st->element_mode != IVAS_CPE_TD && st->element_mode != IVAS_CPE_DFT && hFdCngDec->flag_dtx_mode ) || !st->VAD ) && !( st->cng_type == LP_CNG && hFdCngDec->flag_dtx_mode ) && ( is_music == 0 ) ) || ( st->element_mode == IVAS_CPE_TD ) ) && ( !st->BER_detect ) ) +#else + if ( concealWholeFrame == 0 && + ( timeDomainInput == NULL || + ( *timeDomainInput( -FLT_MAX ) && + *( timeDomainInput + hFdCngCom->frameSize - 1 ) < FLT_MAX && + *( timeDomainInput + hFdCngCom->frameSize - 1 ) > ( -FLT_MAX ) ) ) && + ( ( ( ( st->element_mode != IVAS_CPE_TD && st->element_mode != IVAS_CPE_DFT && hFdCngDec->flag_dtx_mode ) || !st->VAD || ( st->ini_frame < 100 && st->is_ism_format ) ) && + !( st->cng_type == LP_CNG && hFdCngDec->flag_dtx_mode ) && ( is_music == 0 ) ) || + ( st->element_mode == IVAS_CPE_TD ) ) && + ( !st->BER_detect ) ) +#endif { /* Perform noise estimation at the decoder */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT perform_noise_estimation_dec( timeDomainInput, powerSpectrum, hFdCngDec, st->element_mode, st->bwidth, L_frame, last_L_frame, st->last_core_brate, st->VAD ); -#else - perform_noise_estimation_dec( timeDomainInput, hFdCngDec, st->element_mode, st->bwidth, st->L_frame, st->last_L_frame, st->last_core_brate, st->VAD ); -#endif if ( st->element_mode != IVAS_CPE_TD && st->element_mode != IVAS_CPE_DFT ) { @@ -471,7 +475,6 @@ void ApplyFdCng( } } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( st->element_mode == IVAS_CPE_MDCT && timeDomainInput == NULL ) { st->hTcxDec->CngLevelBackgroundTrace_bfi = sqrtf( sum_f( cngNoiseLevel, hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / NORM_MDCT_FACTOR ); @@ -480,7 +483,6 @@ void ApplyFdCng( { st->hTcxDec->CngLevelBackgroundTrace_bfi = (float) sqrt( ( sum_f( cngNoiseLevel, hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 * hFdCngCom->fftlen ) / L_frame ); } -#endif st->cngTDLevel = (float) sqrt( ( sum_f( cngNoiseLevel, hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 * hFdCngCom->fftlen ) / st->L_frame ); } else if ( st->element_mode == IVAS_CPE_TD || st->element_mode == IVAS_CPE_DFT ) @@ -488,73 +490,36 @@ void ApplyFdCng( if ( hFdCngCom->active_frame_counter > 0 ) { /* Perform noise estimation in active frames in the decoder for downward updates */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT perform_noise_estimation_dec( timeDomainInput, powerSpectrum, hFdCngDec, st->element_mode, st->bwidth, L_frame, last_L_frame, st->last_core_brate, st->VAD ); -#else - perform_noise_estimation_dec( timeDomainInput, hFdCngDec, st->element_mode, st->bwidth, st->L_frame, st->last_L_frame, st->last_core_brate, st->VAD ); -#endif } } - if ( ( concealWholeFrame == 1 ) && ( st->nbLostCmpt == 1 ) && sum_f( cngNoiseLevel + hFdCngCom->startBand, hFdCngCom->stopFFTbin - hFdCngCom->startBand ) > 0.01f ) + if ( ( concealWholeFrame == 1 ) && ( st->nbLostCmpt == 1 ) ) { -#ifndef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT /* update lsf cng estimate for concealment. Do that during concealment, in order to avoid addition clean channel complexity*/ - lpc_from_spectrum( hFdCngCom, hFdCngCom->startBand, hFdCngCom->stopFFTbin, 0 ); -#else - if ( st->element_mode == IVAS_CPE_MDCT && st->core != ACELP_CORE ) - { - float scf[SNS_NPTS]; - float scf_int[FDNS_NPTS]; - float whitenend_noise_shape[L_FRAME16k]; - int16_t inc, start_idx, stop_idx; - float *noiseLevelPtr; - - wmops_sub_start( "get scfs for bg" ); - inc = ( st->core > TCX_20 ) ? 2 : 1; - start_idx = hFdCngCom->startBand / inc; - stop_idx = L_frame / inc; - noiseLevelPtr = cngNoiseLevel; + /* always set psychParameters for MDCT-Stereo ... */ + if ( st->element_mode == IVAS_CPE_MDCT && st->hTonalMDCTConc != NULL ) + { + st->hTonalMDCTConc->psychParams = ( st->core == TCX_20_CORE ) ? &st->hTonalMDCTConc->psychParamsTCX20 : &st->hTonalMDCTConc->psychParamsTCX10; + } - set_zero( whitenend_noise_shape, start_idx ); - for ( j = start_idx; j < stop_idx; j++, noiseLevelPtr += inc ) - { - whitenend_noise_shape[j] = *noiseLevelPtr; - } - if ( st->core == TCX_20_CORE ) + /* ... but do actual computations only if sufficient energy in noise shape */ + if ( sum_f( cngNoiseLevel + hFdCngCom->startBand, hFdCngCom->stopFFTbin - hFdCngCom->startBand ) > 0.01f ) + { + if ( st->element_mode == IVAS_CPE_MDCT && st->core != ACELP_CORE ) { - st->hTonalMDCTConc->psychParams = &st->hTonalMDCTConc->psychParamsTCX20; + TonalMdctConceal_whiten_noise_shape( st, L_frame, ON_FIRST_LOST_FRAME ); } - else + else if ( st->element_mode != IVAS_CPE_MDCT || st->core == ACELP_CORE ) { - st->hTonalMDCTConc->psychParams = &st->hTonalMDCTConc->psychParamsTCX10; + lpc_from_spectrum( hFdCngCom, hFdCngCom->startBand, hFdCngCom->stopFFTbin, 0.f ); + a2lsp_stab( hFdCngCom->A_cng, lsp_cng, st->lspold_cng ); + mvr2r( lsp_cng, st->lspold_cng, M ); + lsp2lsf( lsp_cng, st->lsf_cng, M, sr_core ); } - - sns_compute_scf( whitenend_noise_shape, st->hTonalMDCTConc->psychParams, L_frame, scf ); - sns_interpolate_scalefactors( scf_int, scf, ENC ); - sns_interpolate_scalefactors( st->hTonalMDCTConc->scaleFactorsBackground, scf, DEC ); - sns_shape_spectrum( whitenend_noise_shape, st->hTonalMDCTConc->psychParams, scf_int, L_frame ); - - mvr2r( whitenend_noise_shape + start_idx, cngNoiseLevel, stop_idx - start_idx ); - wmops_sub_end(); - } - else if ( st->element_mode != IVAS_CPE_MDCT ) - { - lpc_from_spectrum( hFdCngCom, hFdCngCom->startBand, hFdCngCom->stopFFTbin, 0.f ); - a2lsp_stab( hFdCngCom->A_cng, lsp_cng, st->lspold_cng ); - mvr2r( lsp_cng, st->lspold_cng, M ); - lsp2lsf( lsp_cng, st->lsf_cng, M, sr_core ); + st->plcBackgroundNoiseUpdated = 1; } -#endif - -#ifndef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - a2lsp_stab( hFdCngCom->A_cng, lsp_cng, st->lspold_cng ); - mvr2r( lsp_cng, st->lspold_cng, M ); - - lsp2lsf( lsp_cng, st->lsf_cng, M, st->sr_core ); -#endif - st->plcBackgroundNoiseUpdated = 1; } break; @@ -567,11 +532,7 @@ void ApplyFdCng( if ( st != NULL && st->cng_type == LP_CNG ) { /* Perform noise estimation on inactive phase at the decoder */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT perform_noise_estimation_dec( timeDomainInput, powerSpectrum, hFdCngDec, st->element_mode, st->bwidth, L_frame, last_L_frame, st->last_core_brate, st->VAD ); -#else - perform_noise_estimation_dec( timeDomainInput, hFdCngDec, st->element_mode, st->bwidth, st->L_frame, st->last_L_frame, st->last_core_brate, st->VAD ); -#endif if ( st->element_mode != IVAS_CPE_TD && st->element_mode != IVAS_CPE_DFT ) { @@ -582,11 +543,7 @@ void ApplyFdCng( /* This sets the new CNG levels until a SID update overwrites it */ mvr2r( hFdCngDec->bandNoiseShape, cngNoiseLevel, hFdCngCom->stopFFTbin - hFdCngCom->startBand ); /* This sets the new CNG levels until a SID update overwrites it */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT st->cngTDLevel = (float) sqrt( ( sum_f( cngNoiseLevel, hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 * hFdCngCom->fftlen ) / L_frame ); -#else - st->cngTDLevel = (float) sqrt( ( sum_f( cngNoiseLevel, hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 * hFdCngCom->fftlen ) / st->L_frame ); -#endif break; } @@ -668,10 +625,8 @@ void ApplyFdCng( default: break; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - wmops_sub_end(); -#endif + pop_wmops(); return; } @@ -683,11 +638,9 @@ void ApplyFdCng( * Perform noise estimation at the decoder *-------------------------------------------------------------------*/ -void perform_noise_estimation_dec( +static void perform_noise_estimation_dec( const float *timeDomainInput, -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT float *power_spectrum, -#endif HANDLE_FD_CNG_DEC hFdCngDec, /* i/o: FD_CNG structure containing all buffers and variables */ const int16_t element_mode, /* i : element mode */ const int16_t bwidth, /* i : audio bandwidth */ @@ -720,16 +673,11 @@ void perform_noise_estimation_dec( float temp, ftemp, delta; float wght; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( !( element_mode == IVAS_CPE_MDCT && power_spectrum != NULL ) ) { /* Perform STFT analysis */ AnalysisSTFT( timeDomainInput, fftBuffer, hFdCngDec->hFdCngCom ); } -#else - /* Perform STFT analysis */ - AnalysisSTFT( timeDomainInput, fftBuffer, hFdCngDec->hFdCngCom ); -#endif if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_CPE_DFT ) { @@ -962,7 +910,6 @@ void perform_noise_estimation_dec( } else { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( element_mode == IVAS_CPE_MDCT && power_spectrum != NULL ) { /* use power spectrum calculated in the MDCT-domain instead of calculating new power spectrum */ @@ -995,32 +942,6 @@ void perform_noise_estimation_dec( /* Rescale to get energy/sample: it should be 2*(1/N)*(2/N), parseval relation with 1/N,*2 for nrg computed till Nyquist only, 2/N as windowed samples correspond to half a frame*/ v_multc( periodog, 4.f / (float) ( hFdCngDec->hFdCngCom->fftlen * hFdCngDec->hFdCngCom->fftlen ), periodog, stopFFTbin - startBand ); } -#else - /* Compute the squared magnitude in each FFT bin */ - if ( startBand == 0 ) - { - ( *ptr_per ) = fftBuffer[0] * fftBuffer[0]; /* DC component */ - ptr_per++; - ptr_r = fftBuffer + 2; - } - else - { - ptr_r = fftBuffer + 2 * startBand; - } - - ptr_i = ptr_r + 1; - - for ( ; ptr_per < periodog + stopFFTbin - startBand; ptr_per++ ) - { - ( *ptr_per ) = ( *ptr_r ) * ( *ptr_r ) + ( *ptr_i ) * ( *ptr_i ); - ptr_r += 2; - ptr_i += 2; - } - /* Nyquist frequency is discarded */ - - /* Rescale to get energy/sample: it should be 2*(1/N)*(2/N), parseval relation with 1/N,*2 for nrg computed till Nyquist only, 2/N as windowed samples correspond to half a frame*/ - v_multc( periodog, 4.f / (float) ( hFdCngDec->hFdCngCom->fftlen * hFdCngDec->hFdCngCom->fftlen ), periodog, stopFFTbin - startBand ); -#endif /* Adjust to the desired frequency resolution by averaging over spectral partitions for SID transmission */ bandcombinepow( periodog, stopFFTbin - startBand, part, npart, psize_inv, msPeriodog ); @@ -1182,7 +1103,7 @@ void generate_comfort_noise_dec( c2 = (float) sqrt( 1 - hFdCngCom->coherence ); seed2 = &( hFdCngCom->seed2 ); - if ( st->element_mode == IVAS_CPE_MDCT && st->idchan == 1 ) + if ( ( st->element_mode == IVAS_CPE_MDCT && st->idchan == 1 ) || ( st->element_mode == IVAS_SCE && st->cng_ism_flag ) ) { seed2 = &( hFdCngCom->seed3 ); } @@ -1192,7 +1113,7 @@ void generate_comfort_noise_dec( if ( hFdCngCom->startBand == 0 ) { - if ( st->element_mode == IVAS_CPE_MDCT ) + if ( st->element_mode == IVAS_CPE_MDCT || ( st->element_mode == IVAS_SCE && st->cng_ism_flag ) ) { rand_gauss( &tmp1, seed ); rand_gauss( &tmp2, seed2 ); @@ -1217,7 +1138,7 @@ void generate_comfort_noise_dec( for ( ; ptr_level < cngNoiseLevel + hFdCngCom->stopFFTbin - hFdCngCom->startBand; ptr_level++ ) { /* Real part in FFT bins */ - if ( st->element_mode == IVAS_CPE_MDCT ) + if ( st->element_mode == IVAS_CPE_MDCT || ( st->element_mode == IVAS_SCE && st->cng_ism_flag ) ) { rand_gauss( &tmp1, seed ); rand_gauss( &tmp2, seed2 ); @@ -1231,7 +1152,7 @@ void generate_comfort_noise_dec( ptr_r += 2; /* Imaginary part in FFT bins */ - if ( st->element_mode == IVAS_CPE_MDCT ) + if ( st->element_mode == IVAS_CPE_MDCT || ( st->element_mode == IVAS_SCE && st->cng_ism_flag ) ) { rand_gauss( &tmp1, seed ); rand_gauss( &tmp2, seed2 ); @@ -1309,7 +1230,7 @@ void generate_comfort_noise_dec( for ( i = 0; i < hFdCngCom->numSlots; i++ ) { /* Real part in CLDFB band */ - if ( st->element_mode == IVAS_CPE_MDCT ) + if ( st->element_mode == IVAS_CPE_MDCT || ( st->element_mode == IVAS_SCE && st->cng_ism_flag ) ) { rand_gauss( &tmp1, seed ); rand_gauss( &tmp2, seed2 ); @@ -1322,7 +1243,7 @@ void generate_comfort_noise_dec( bufferReal[i][j] *= (float) sqrt( ( scaleCldfb * *ptr_level ) * 0.5f ); /* Imaginary part in CLDFB band */ - if ( st->element_mode == IVAS_CPE_MDCT ) + if ( st->element_mode == IVAS_CPE_MDCT || ( st->element_mode == IVAS_SCE && st->cng_ism_flag ) ) { rand_gauss( &tmp1, seed ); rand_gauss( &tmp2, seed2 ); @@ -1419,16 +1340,29 @@ void generate_comfort_noise_dec( *-------------------------------------------------------------------*/ void generate_comfort_noise_dec_hf( - float **bufferReal, /* o : Real part of input bands */ - float **bufferImag, /* o : Imaginary part of input bands */ - HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */ + float **bufferReal, /* o : Real part of input bands */ + float **bufferImag, /* o : Imaginary part of input bands */ + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + const int16_t cng_coh_flag /* i : CNG Flag for coherence handling */ ) { int16_t i, j; float *ptr_level; + int16_t *seed = &( hFdCngCom->seed ); float scale = CLDFB_SCALING / hFdCngCom->scalingFactor; + int16_t *seed2 = &( hFdCngCom->seed ); + float tmp1, tmp2, c1 = 0.f, c2 = 0.f; + + if ( cng_coh_flag ) + { + seed2 = &( hFdCngCom->seed3 ); + + c1 = (float) sqrt( hFdCngCom->coherence ); // VE!!!!! all occurences of "(float) sqrt()" should be replaced by "sqrtf()" + c2 = (float) sqrt( 1 - hFdCngCom->coherence ); + } + ptr_level = hFdCngCom->cngNoiseLevel + hFdCngCom->stopFFTbin - hFdCngCom->startBand; /* Generate Gaussian random noise in real and imaginary parts of the CLDFB bands @@ -1440,12 +1374,29 @@ void generate_comfort_noise_dec_hf( { for ( i = 0; i < hFdCngCom->numSlots; i++ ) { - /* Real part in CLDFB band */ - rand_gauss( &bufferReal[i][j], seed ); - bufferReal[i][j] *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); - /* Imaginary part in CLDFB band */ - rand_gauss( &bufferImag[i][j], seed ); - bufferImag[i][j] *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); + if ( cng_coh_flag ) + { + /* Real part in CLDFB band */ + rand_gauss( &tmp1, seed ); + rand_gauss( &tmp2, seed2 ); + bufferReal[i][j] = tmp1 * c1 + tmp2 * c2; + bufferReal[i][j] *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); + + /* Imaginary part in CLDFB band */ + rand_gauss( &tmp1, seed ); + rand_gauss( &tmp2, seed2 ); + bufferImag[i][j] = tmp1 * c1 + tmp2 * c2; + bufferImag[i][j] *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); + } + else + { + /* Real part in CLDFB band */ + rand_gauss( &bufferReal[i][j], seed ); + bufferReal[i][j] *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); + /* Imaginary part in CLDFB band */ + rand_gauss( &bufferImag[i][j], seed ); + bufferImag[i][j] *= (float) sqrt( ( scale * *ptr_level ) * 0.5f ); + } } ptr_level++; } @@ -1868,7 +1819,7 @@ void generate_masking_noise_dirac( int16_t *seed = &( hFdCngCom->seed ); float scale; - wmops_sub_start( "fd_cng_dirac" ); + push_wmops( "fd_cng_dirac" ); /* Init */ scale = 0.f; @@ -2027,7 +1978,7 @@ void generate_masking_noise_dirac( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -2055,7 +2006,7 @@ void FdCngDecodeMDCTStereoSID( int16_t is_out_ms; is_out_ms = 0; - if ( hCPE->hCoreCoder[0]->cng_spar_flag == 1 ) + if ( hCPE->hCoreCoder[0]->cng_sba_flag ) { is_out_ms = 1; } @@ -2099,6 +2050,8 @@ void FdCngDecodeMDCTStereoSID( msvq_dec( cdk_37bits_ivas, NULL, NULL, stages, N, FD_CNG_maxN_37bits, indices, ms_ptr[ch], NULL ); } + dtx_read_padding_bits( sts[1], ( IVAS_SID_5k2 - 4400 ) / FRAMES_PER_SEC ); + if ( sts[0]->hFdCngDec->hFdCngCom->no_side_flag ) { set_zero( ms_ptr[1], NPART ); @@ -2122,7 +2075,7 @@ void FdCngDecodeMDCTStereoSID( lpc_from_spectrum( hFdCngCom, hFdCngCom->startBand, hFdCngCom->stopFFTbin, sts[ch]->preemph_fac ); } - if ( hCPE->nchan_out == 1 && hCPE->last_element_brate <= IVAS_SID_4k4 ) + if ( hCPE->nchan_out == 1 && hCPE->last_element_brate <= IVAS_SID_5k2 ) { /* create proper M noise shape in channel zero after gains have been applied */ for ( p = 0; p < N; p++ ) @@ -2212,8 +2165,6 @@ void FdCngDecodeDiracMDCTStereoSID( { sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst[p] = 0.5f * ( sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst[p] + sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst[p] ); } - sts[0]->hFdCngDec->hFdCngCom->coherence = 0.0f; - sts[1]->hFdCngDec->hFdCngCom->coherence = 0.0f; } return; diff --git a/lib_dec/gain_dec.c b/lib_dec/gain_dec.c index dd8a58637cee9e121e574d6eacd2b1abadba7c7d..99eecba56a4919f1790c0f3a022761b1328c65c3 100644 --- a/lib_dec/gain_dec.c +++ b/lib_dec/gain_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Es_pred_dec() diff --git a/lib_dec/gaus_dec.c b/lib_dec/gaus_dec.c index fed8ab60ac8c4cf6146308f3c8854ce399be7cde..a053597722528bb13536f2380e84c90c3d55f63d 100644 --- a/lib_dec/gaus_dec.c +++ b/lib_dec/gaus_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_dec/gs_dec.c b/lib_dec/gs_dec.c index f1b4e997afeddd653701267d402df2b6c5cfafc1..e8112c6c4da76ee0a2eb5e970a749427acd9a494 100644 --- a/lib_dec/gs_dec.c +++ b/lib_dec/gs_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * decod_audio() diff --git a/lib_dec/gs_dec_amr_wb.c b/lib_dec/gs_dec_amr_wb.c index 956e065031ebb1fadb0763a50547789292336133..1d41f367f4ff2497d0b56e8ad624f681141a797f 100644 --- a/lib_dec/gs_dec_amr_wb.c +++ b/lib_dec/gs_dec_amr_wb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_dec/hdecnrm.c b/lib_dec/hdecnrm.c index f1a119a8678040c16e02a1775806fbb99a6b0542..1f247ef1f0e1a1e9e87a6d0a24d171d0e9ba54b4 100644 --- a/lib_dec/hdecnrm.c +++ b/lib_dec/hdecnrm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------*/ diff --git a/lib_dec/hf_synth.c b/lib_dec/hf_synth.c index 9c0f2c8463b3299fc3cc7f91d9b97b87cdc67213..a4d75b4e9af5118eef7c49a1cc5fecc4450b0e9e 100644 --- a/lib_dec/hf_synth.c +++ b/lib_dec/hf_synth.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_dec/hq_classifier_dec.c b/lib_dec/hq_classifier_dec.c index 38a02300795dbc63606888a770654dace266e17c..10a1a783fcddeac2b0bf93a14e6306c98e24ca33 100644 --- a/lib_dec/hq_classifier_dec.c +++ b/lib_dec/hq_classifier_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hq_classifier_dec() diff --git a/lib_dec/hq_conf_fec.c b/lib_dec/hq_conf_fec.c index 5e0e6426f24d850467bab892482c518360bc1225..7d3c79fcf2367dc699d50eadd5faef31a689d998 100644 --- a/lib_dec/hq_conf_fec.c +++ b/lib_dec/hq_conf_fec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hq_configure_bfi() diff --git a/lib_dec/hq_core_dec.c b/lib_dec/hq_core_dec.c index 507d80596e16d17f5730c268d3e80bcbabc43fd9..cdb9601679549187e6e5dae354e0e8e2314e6f71 100644 --- a/lib_dec/hq_core_dec.c +++ b/lib_dec/hq_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" @@ -87,7 +87,7 @@ void hq_core_dec( int16_t mdctWindowLength; int16_t mdctWindowLengthFB; - wmops_sub_start( "hq_core_dec" ); + push_wmops( "hq_core_dec" ); /*-------------------------------------------------------------------------- * Initializations *--------------------------------------------------------------------------*/ @@ -153,7 +153,7 @@ void hq_core_dec( acelp_plc_mdct_transition( st ); } - /* subtract signalling bits */ + /* subtract signaling bits */ num_bits -= st->next_bit_pos; /* set FEC parameters */ @@ -249,7 +249,7 @@ void hq_core_dec( else { /* HQ high rate decoder */ - hq_hr_dec( st, t_audio_q, L_spec, num_bits, ynrm, &is_transient, &hqswb_clas, SWB_fenv ); + hq_hr_dec( st, t_audio_q, L_spec, num_bits, ynrm, &is_transient, &hqswb_clas, SWB_fenv, core_switching_flag ); } if ( st->element_mode == EVS_MONO || ( !core_switching_flag && !hq_recovery_flag ) ) @@ -495,7 +495,7 @@ void hq_core_dec( mvr2r( output, st->old_exc + L_EXC_MEM_DEC - st->L_frame, st->L_frame ); } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_dec/hq_env_dec.c b/lib_dec/hq_env_dec.c index d4abecfc5d52410a91752a0412aea484500b9cf1..e584bfa8276c44c19fe394a3ad35557a9d83d5d9 100644 --- a/lib_dec/hq_env_dec.c +++ b/lib_dec/hq_env_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------* * decode_envelope_indices() diff --git a/lib_dec/hq_hr_dec.c b/lib_dec/hq_hr_dec.c index 3eb1108b24e1966d17934ffab447ede40e503eab..5153af07ead81341863f7c98377ac69a65d53609 100644 --- a/lib_dec/hq_hr_dec.c +++ b/lib_dec/hq_hr_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hq_pred_hb_bws() @@ -100,14 +100,15 @@ static void hq_pred_hb_bws( *--------------------------------------------------------------------------*/ void hq_hr_dec( - Decoder_State *st, /* i/o: decoder state structure */ - float *t_audio_q, /* o : transform-domain coefficients */ - const int16_t length, /* i : frame length */ - const int16_t num_bits, /* i : number of available bits */ - int16_t *ynrm, /* o : norm quantization index vector */ - int16_t *is_transient, /* o : transient flag */ - int16_t *hqswb_clas, /* o : HQ SWB class */ - float *SWB_fenv /* o : SWB frequency envelopes */ + Decoder_State *st, /* i/o: decoder state structure */ + float *t_audio_q, /* o : transform-domain coefficients */ + const int16_t length, /* i : frame length */ + const int16_t num_bits, /* i : number of available bits */ + int16_t *ynrm, /* o : norm quantization index vector */ + int16_t *is_transient, /* o : transient flag */ + int16_t *hqswb_clas, /* o : HQ SWB class */ + float *SWB_fenv, /* o : SWB frequency envelopes */ + const int16_t core_switching_flag /* i : Core switching flag */ ) { int16_t nb_sfm; @@ -193,9 +194,9 @@ void hq_hr_dec( { hHQ_core->mem_env_delta = 0; } - else if ( length == L_FRAME32k ) + else if ( length == L_FRAME32k || ( core_switching_flag && ( st->element_mode != EVS_MONO ) && length == L_SPEC32k_EXT ) ) { - env_stab = env_stability( ynrm, SFM_N_ENV_STAB, hHQ_core->mem_norm, &hHQ_core->mem_env_delta ); + env_stab = env_stability( ynrm, SFM_N_ENV_STAB, hHQ_core->mem_norm, &hHQ_core->mem_env_delta, core_switching_flag && ( st->element_mode != EVS_MONO ) ); } else { @@ -209,13 +210,13 @@ void hq_hr_dec( } else { - if ( length == L_FRAME32k ) + if ( length == L_FRAME32k || ( core_switching_flag && ( st->element_mode != EVS_MONO ) && length == L_SPEC32k_EXT ) ) { hHQ_core->env_stab = env_stab; /* calculated stability */ } else { - hHQ_core->env_stab = env_stability( ynrm, SFM_N_ENV_STAB_WB, hHQ_core->mem_norm_hqfec, &hHQ_core->mem_env_delta_hqfec ); + hHQ_core->env_stab = env_stability( ynrm, SFM_N_ENV_STAB_WB, hHQ_core->mem_norm_hqfec, &hHQ_core->mem_env_delta_hqfec, core_switching_flag && ( st->element_mode != EVS_MONO ) ); } } hHQ_core->env_stab_plc = env_stab_smo( min( hHQ_core->env_stab, 1.0f - stab_trans[L_STAB_TBL - 1] ), hHQ_core->env_stab_state_p, &hHQ_core->envstabplc_hocnt ); diff --git a/lib_dec/hq_lr_dec.c b/lib_dec/hq_lr_dec.c index 5e7584384d5522496fc508b53f9251cb3a2b0d1f..774720844c56abf7a28ea7cd13c4c312153f9077 100644 --- a/lib_dec/hq_lr_dec.c +++ b/lib_dec/hq_lr_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "prot.h" #include "stl.h" #include "basop_util.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * Local function prototypes @@ -238,7 +238,7 @@ void hq_lr_dec( if ( flag_spt == 1 ) { - /* initalize the desired parameters for SPT */ + /* initialize the desired parameters for SPT */ spt_shorten_domain_band_save( bands, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width ); spt_shorten_domain_pre( band_start, band_end, hHQ_core->prev_SWB_peak_pos, bands, bwe_br, new_band_start, new_band_end, new_band_width ); spt_shorten_domain_set_dec( st, p2a_flags, new_band_start, new_band_end, new_band_width, bands, band_start, band_end, band_width, &bit_budget ); @@ -252,7 +252,7 @@ void hq_lr_dec( return; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* Estimate number of bits per sub-band */ Q_band_energy = SWB_BWE_LR_Qbe; FOR( i = 0; i < bands; i++ ) @@ -295,7 +295,7 @@ void hq_lr_dec( Ep_tmp_fx[i] = L_shr( L_tmp, sub( 15, exp2 ) ); /*Q13 */ Ep_tmp[i] = (float) ( Ep_tmp_fx[i] / pow( 2.0, 13 ) ); } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP if ( *is_transient == 0 && inner_frame == L_FRAME8k && st->core_brate <= ACELP_13k20 ) { @@ -306,7 +306,7 @@ void hq_lr_dec( last_bitalloc_max_band[i] = get_next_indice( st, 1 ); } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP lowband = 6; move16(); trans_bit = 2; @@ -567,7 +567,7 @@ void hq_lr_dec( #endif /* BASOP_NOGLOB */ } } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP for ( i = 0; i < bands; i++ ) { @@ -578,7 +578,7 @@ void hq_lr_dec( } else if ( *is_transient == 0 && inner_frame == L_FRAME16k ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP bit_budget = sub( bit_budget, 2 ); /* bits in high bands to indicate the last 2 subbands is allocated bits or not */ /* decode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ for ( i = 0; i < 2; i++ ) @@ -839,7 +839,7 @@ void hq_lr_dec( L_band_energy_tmp[i] = L_shl( L_tmp, 1 ); /*Q_band_energy */ } } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP for ( i = 0; i < bands; i++ ) { @@ -1216,14 +1216,14 @@ static float band_energy_dequant( deng_bits += BITS_DE_CMODE; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* Get the reference energy */ exp_normd = norm_l( L_qint ); div_s( &rev_qint_fx, 0x4000, round_fx( L_shl( L_qint, exp_normd ) ) ); /* Q14-(29+exp_normd-16)+15 */ Qrev_qint = sub( 14 - ( 29 - 16 ) + 15, exp_normd ); bq0 = (int16_t) round_fx( L_shl( L_mult( eref_fx, rev_qint_fx ), sub( 5, Qrev_qint ) ) ); /* 16-(10+Qrev_qint+1) */ -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /* Reconstruct quantized spectrum */ bq1[0] = bq2[0] + bq0; @@ -1234,11 +1234,11 @@ static float band_energy_dequant( for ( k = 0; k < bands; k++ ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP L_band_energy[k] = L_mls( L_qint, bq1[k] ); move32(); /* 29+0-15 -> Qbe(Q14) */ band_energy[k] = (float) ( L_band_energy[k] / pow( 2.0f, SWB_BWE_LR_Qbe ) ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } if ( is_transient ) @@ -1309,7 +1309,7 @@ static void mdct_spectrum_fine_gain_dec( Word16 Qgt; Word16 temp_lo_fx, temp_hi_fx; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* Fine gain quantization on only the most significant energy bands */ /*delta = qint / gqlevs; */ exp_normn = norm_l( L_qint ); @@ -1334,7 +1334,7 @@ static void mdct_spectrum_fine_gain_dec( gain_table_fx[i] = shl( gain_table_fx[i], sub( 14, Qgt ) ); /* Qgt -> Q14 */ gain_table[i] = (float) ( gain_table_fx[i] / pow( 2.0f, 14 ) ); } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP for ( k = bands - Ngq; k < bands; k++ ) { diff --git a/lib_dec/igf_dec.c b/lib_dec/igf_dec.c index 55e526d6654fdd5f5d136597d8efdcc543e7a112..a3eefd226ebe39c0baf910d806afaecef48c188d 100644 --- a/lib_dec/igf_dec.c +++ b/lib_dec/igf_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "cnst.h" #include "stat_dec.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -679,7 +679,8 @@ static void IGF_appl( float *pSpectralData, /* i/o: Q31 | MDCT spectrum */ const float *igf_spec, /* i : Q31 | prepared IGF spectrum */ float *virtualSpec, /* o : Q31 | virtual IGF spectrum, used for temp flattening */ - int16_t *flag_sparse /* o : Q0 | temp flattening indicator */ + int16_t *flag_sparse, /* o : Q0 | temp flattening indicator */ + const int16_t bfi_apply_damping /* i : flag to indicate if damping for lost frames should be applied */ ) { H_IGF_GRID hGrid; @@ -855,7 +856,7 @@ static void IGF_appl( for ( sfb = start_sfb; sfb < stop_sfb; sfb++ ) { - if ( hPrivateData->frameLossCounter > 0 ) + if ( bfi_apply_damping && hPrivateData->frameLossCounter > 0 ) { gain[sfb] = min( gain[sfb], 12.f ); @@ -1212,7 +1213,7 @@ void IGFDecApplyMono( /* apply IGF in three steps: */ IGF_prep( hPrivateData, igfGridIdx, hIGFDec->infoTCXNoise, igf_spec, hPrivateData->pSpecFlat, element_mode ); IGF_calc( hPrivateData, igfGridIdx, spectrum, igf_spec ); - IGF_appl( hPrivateData, igfGridIdx, spectrum, igf_spec, hIGFDec->virtualSpec, hIGFDec->flag_sparse ); + IGF_appl( hPrivateData, igfGridIdx, spectrum, igf_spec, hIGFDec->virtualSpec, hIGFDec->flag_sparse, 1 ); } /* reset TCX noise indicator vector */ @@ -1238,8 +1239,8 @@ void IGFDecApplyStereo( const int16_t igfGridIdx, /* i : in case of CELP->TCX switching, use 1.25 framelength */ const int16_t *coreMsMask, const int16_t restrict_hopsize, - const int16_t bfi /* i : frame loss == 1, frame good == 0 */ -) + const int16_t bfi, /* i : frame loss == 1, frame good == 0 */ + const int16_t bfi_apply_damping ) { IGF_DEC_PRIVATE_DATA_HANDLE hPrivateDataL, hPrivateDataR; H_IGF_GRID hGrid; @@ -1335,8 +1336,8 @@ void IGFDecApplyStereo( IGF_calc( hPrivateDataL, igfGridIdx, spectrumL, igf_specL ); IGF_calc( hPrivateDataR, igfGridIdx, spectrumR, igf_specR ); - IGF_appl( hPrivateDataL, igfGridIdx, spectrumL, igf_specL, hIGFDecL->virtualSpec, hIGFDecL->flag_sparse ); - IGF_appl( hPrivateDataR, igfGridIdx, spectrumR, igf_specR, hIGFDecR->virtualSpec, hIGFDecR->flag_sparse ); + IGF_appl( hPrivateDataL, igfGridIdx, spectrumL, igf_specL, hIGFDecL->virtualSpec, hIGFDecL->flag_sparse, bfi_apply_damping ); + IGF_appl( hPrivateDataR, igfGridIdx, spectrumR, igf_specR, hIGFDecR->virtualSpec, hIGFDecR->flag_sparse, bfi_apply_damping ); } /* reset TCX noise indicator vector */ @@ -1588,3 +1589,40 @@ void init_igf_dec( return; } + + +/*-----------------------------------------------------------------------* + * get_igf_startline() + * + * + *-----------------------------------------------------------------------*/ + +/*! r: IGF start line */ +int16_t get_igf_startline( + Decoder_State *st, /* i : decoder state */ + const int16_t L_frame, /* i : length of the frame */ + const int16_t L_frameTCX /* i : full band frame length */ +) +{ + int16_t igf_startline; + + if ( st->igf == 0 ) + { + if ( st->narrowBand == 0 ) + { + /* minimum needed for output with sampling rates lower then the + nominal sampling rate */ + igf_startline = min( L_frameTCX, L_frame ); + } + else + { + igf_startline = L_frameTCX; + } + } + else + { + igf_startline = min( st->hIGFDec->infoIGFStartLine, L_frameTCX ); + } + + return igf_startline; +} diff --git a/lib_dec/igf_scf_dec.c b/lib_dec/igf_scf_dec.c index 29660271b3f6eda68d8dc0d0487c17716ba3b7e9..f152f637a0d83b6e78684766f44a215874793eb0 100644 --- a/lib_dec/igf_scf_dec.c +++ b/lib_dec/igf_scf_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "debug.h" #endif #include "stat_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* diff --git a/lib_dec/init_dec.c b/lib_dec/init_dec.c index 3365682878a7695b7a125b8ec8fa0a641c48ee73..97aa4a0fc836bf20a7ed38cf339df8a1268d307e 100644 --- a/lib_dec/init_dec.c +++ b/lib_dec/init_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "ivas_cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------* * init_decoder() @@ -52,12 +52,9 @@ *----------------------------------------------------------------------*/ ivas_error init_decoder( - Decoder_State *st, /* o : Decoder static variables structure */ - const int16_t idchan /* i : channel ID */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , + Decoder_State *st, /* o : Decoder static variables structure */ + const int16_t idchan, /* i : channel ID */ const MC_MODE mc_mode /* i : MC mode */ -#endif ) { int16_t i; @@ -110,6 +107,7 @@ ivas_error init_decoder( st->last_good = UNVOICED_CLAS; st->clas_dec = UNVOICED_CLAS; st->low_rate_mode = 0; + st->last_low_rate_mode = 0; st->lp_gainp = 0.0f; st->lp_gainc = 0.0f; @@ -130,6 +128,9 @@ ivas_error init_decoder( st->stab_fac_smooth = 0.0f; set_f( st->agc_mem2, 0, 2 ); set_f( st->mem_syn3, 0, M ); + st->stab_fac_smooth_lt = 0.0f; + st->log_energy_diff_lt = 0.0f; + st->log_energy_old = 0.0f; mvr2r( GEWB_Ave, st->lsf_old, M ); lsf2lsp( st->lsf_old, st->lsp_old, M, INT_FS_12k8 ); @@ -196,7 +197,7 @@ ivas_error init_decoder( if ( ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == IVAS_CPE_TD ) { - if ( ( st->hGSCDec = (GSC_DEC_HANDLE) count_malloc( sizeof( GSC_DEC_DATA ) ) ) == NULL ) + if ( ( st->hGSCDec = (GSC_DEC_HANDLE) malloc( sizeof( GSC_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for GSC\n" ) ); } @@ -214,7 +215,7 @@ ivas_error init_decoder( if ( st->output_Fs == 16000 && st->element_mode == EVS_MONO ) { - if ( ( st->hWIDec = (WI_DEC_HANDLE) count_malloc( sizeof( WI_DEC_DATA ) ) ) == NULL ) + if ( ( st->hWIDec = (WI_DEC_HANDLE) malloc( sizeof( WI_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FEC WI\n" ) ); } @@ -233,7 +234,7 @@ ivas_error init_decoder( if ( ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == IVAS_CPE_TD ) { - if ( ( st->hPFstat = (PFSTAT_HANDLE) count_malloc( sizeof( PFSTAT ) ) ) == NULL ) + if ( ( st->hPFstat = (PFSTAT_HANDLE) malloc( sizeof( PFSTAT ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for NB/formant postflter\n" ) ); } @@ -253,7 +254,7 @@ ivas_error init_decoder( if ( ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == IVAS_CPE_TD ) { - if ( ( st->hBWE_zero = (ZERO_BWE_DEC_HANDLE) count_malloc( sizeof( ZERO_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_zero = (ZERO_BWE_DEC_HANDLE) malloc( sizeof( ZERO_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for zero BWE\n" ) ); } @@ -272,7 +273,7 @@ ivas_error init_decoder( if ( ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == IVAS_CPE_TD ) { - if ( ( st->hMusicPF = (MUSIC_POSTFILT_HANDLE) count_malloc( sizeof( MUSIC_POSTFILT_DATA ) ) ) == NULL ) + if ( ( st->hMusicPF = (MUSIC_POSTFILT_HANDLE) malloc( sizeof( MUSIC_POSTFILT_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LD music postflter\n" ) ); } @@ -298,7 +299,7 @@ ivas_error init_decoder( if ( idchan == 0 && ( st->element_mode == EVS_MONO || st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) ) { - if ( ( st->hTdCngDec = (TD_CNG_DEC_HANDLE) count_malloc( sizeof( TD_CNG_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTdCngDec = (TD_CNG_DEC_HANDLE) malloc( sizeof( TD_CNG_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n" ) ); } @@ -325,9 +326,13 @@ ivas_error init_decoder( set_f( st->old_synth_sw, 0.0f, NS2SA( 48000, FRAME_SIZE_NS - ACELP_LOOK_NS - DELAY_BWE_TOTAL_NS ) ); } - if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT || st->element_mode == IVAS_SCE || st->element_mode == EVS_MONO ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT || st->element_mode == IVAS_SCE || st->element_mode == EVS_MONO ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { - if ( ( st->hHQ_core = (HQ_DEC_HANDLE) count_malloc( sizeof( HQ_DEC_DATA ) ) ) == NULL ) + if ( ( st->hHQ_core = (HQ_DEC_HANDLE) malloc( sizeof( HQ_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ core\n" ) ); } @@ -338,7 +343,7 @@ ivas_error init_decoder( if ( st->element_mode == EVS_MONO ) { /* HQ NB FEC initialization */ - if ( ( st->hHQ_nbfec = (HQ_NBFEC_HANDLE) count_malloc( sizeof( HQ_NBFEC_DATA ) ) ) == NULL ) + if ( ( st->hHQ_nbfec = (HQ_NBFEC_HANDLE) malloc( sizeof( HQ_NBFEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ NB FEC\n" ) ); } @@ -362,7 +367,7 @@ ivas_error init_decoder( if ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) { - if ( ( st->hBWE_TD = (TD_BWE_DEC_HANDLE) count_malloc( sizeof( TD_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_TD = (TD_BWE_DEC_HANDLE) malloc( sizeof( TD_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); } @@ -383,7 +388,7 @@ ivas_error init_decoder( if ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) { - if ( ( st->hBWE_FD = (FD_BWE_DEC_HANDLE) count_malloc( sizeof( FD_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_FD = (FD_BWE_DEC_HANDLE) malloc( sizeof( FD_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); } @@ -418,7 +423,7 @@ ivas_error init_decoder( if ( st->element_mode == EVS_MONO ) { - if ( ( st->hBWE_FD_HR = (HR_BWE_DEC_HANDLE) count_malloc( sizeof( HR_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_FD_HR = (HR_BWE_DEC_HANDLE) malloc( sizeof( HR_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HR BWE\n" ) ); } @@ -436,7 +441,7 @@ ivas_error init_decoder( if ( st->Opt_AMR_WB || st->element_mode == EVS_MONO ) { - if ( ( st->hAmrwb_IO = (AMRWB_IO_DEC_HANDLE) count_malloc( sizeof( AMRWB_IO_DEC_DATA ) ) ) == NULL ) + if ( ( st->hAmrwb_IO = (AMRWB_IO_DEC_HANDLE) malloc( sizeof( AMRWB_IO_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for AMR-WB IO\n" ) ); } @@ -481,7 +486,7 @@ ivas_error init_decoder( if ( ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == IVAS_CPE_TD ) { - if ( ( st->hBPF = (BPF_DEC_HANDLE) count_malloc( sizeof( BPF_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBPF = (BPF_DEC_HANDLE) malloc( sizeof( BPF_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for BPF\n" ) ); } @@ -518,17 +523,21 @@ ivas_error init_decoder( } /* open synthesis for output sampling rate */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif if ( ( error = openCldfb( &st->cldfbSyn, CLDFB_SYNTHESIS, st->output_Fs, CLDFB_PROTOTYPE_1_25MS ) ) != IVAS_ERR_OK ) { return error; } +#ifndef ISSUE_24_CLEANUP_MCT_LFE } else { st->cldfbSyn = NULL; } +#endif st->cldfbSynHB = NULL; @@ -556,7 +565,7 @@ ivas_error init_decoder( if ( st->element_mode == EVS_MONO ) { - if ( ( st->hSC_VBR = (SC_VBR_DEC_HANDLE) count_malloc( sizeof( SC_VBR_DEC_DATA ) ) ) == NULL ) + if ( ( st->hSC_VBR = (SC_VBR_DEC_HANDLE) malloc( sizeof( SC_VBR_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SC-VBR\n" ) ); } @@ -584,9 +593,13 @@ ivas_error init_decoder( *-----------------------------------------------------------------*/ /* TCX-LTP */ - if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { - if ( ( st->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) count_malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TCX-LTP handle\n" ) ); } @@ -597,10 +610,10 @@ ivas_error init_decoder( } /* TCX core */ - // VE: reduction possible for MCT_CHAN_MODE_LFE channel - see I1-172 + if ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) { - if ( ( st->hTcxDec = (TCX_DEC_HANDLE) count_malloc( sizeof( TCX_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTcxDec = (TCX_DEC_HANDLE) malloc( sizeof( TCX_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxDec\n" ) ); } @@ -616,9 +629,13 @@ ivas_error init_decoder( } /* TCX config. data structure */ - if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { - if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) count_malloc( sizeof( TCX_config ) ) ) == NULL ) + if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxCfg\n" ) ); } @@ -629,9 +646,13 @@ ivas_error init_decoder( } /* Tonal MDCT concealment data structure */ - if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { - if ( ( st->hTonalMDCTConc = (TonalMDCTConcealPtr) count_malloc( sizeof( TonalMDCTConceal_INSTANCE ) ) ) == NULL ) + if ( ( st->hTonalMDCTConc = (TonalMDCTConcealPtr) malloc( sizeof( TonalMDCTConceal_INSTANCE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TonalMDCTConcealment\n" ) ); } @@ -645,9 +666,13 @@ ivas_error init_decoder( * IGF *-----------------------------------------------------------------*/ - if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { - if ( ( st->hIGFDec = (IGF_DEC_INSTANCE_HANDLE) count_malloc( sizeof( IGFDEC_INSTANCE ) ) ) == NULL ) + if ( ( st->hIGFDec = (IGF_DEC_INSTANCE_HANDLE) malloc( sizeof( IGFDEC_INSTANCE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for IGF\n" ) ); } @@ -664,9 +689,9 @@ ivas_error init_decoder( * Mode 2 initialization *-----------------------------------------------------------------*/ - if ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) + if ( st->element_mode == EVS_MONO ) { - if ( ( st->hPlcInfo = (T_PLCInfo_HANDLE) count_malloc( sizeof( T_PLCInfo ) ) ) == NULL ) + if ( ( st->hPlcInfo = (T_PLCInfo_HANDLE) malloc( sizeof( T_PLCInfo ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for PLC handle\n" ) ); } @@ -678,7 +703,7 @@ ivas_error init_decoder( if ( st->element_mode == EVS_MONO ) { - if ( ( st->hTECDec = (TEC_DEC_HANDLE) count_malloc( sizeof( TEC_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTECDec = (TEC_DEC_HANDLE) malloc( sizeof( TEC_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TEC\n" ) ); } @@ -688,14 +713,8 @@ ivas_error init_decoder( st->hTECDec = NULL; } - st->enablePlcWaveadjust = 0; - /* Init Core Decoder */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT open_decoder_LPD( st, st->total_brate, st->last_total_brate, st->bwidth, 0, st->element_mode, 1 ); -#else - open_decoder_LPD( st, st->total_brate, st->last_total_brate, st->bwidth, 0, 1 ); -#endif /* PLC mode initialization */ st->m_decodeMode = DEC_NO_FRAM_LOSS; @@ -714,11 +733,7 @@ ivas_error init_decoder( * FD-CNG decoder *-----------------------------------------------------------------*/ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( ( st->element_mode == IVAS_CPE_MDCT || idchan == 0 ) && mc_mode != MC_MODE_MCT ) -#else - if ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) -#endif { /* Create FD_CNG instance */ if ( ( error = createFdCngDec( &st->hFdCngDec ) ) != IVAS_ERR_OK ) @@ -746,8 +761,12 @@ ivas_error init_decoder( st->tdm_LRTD_flag = 0; st->cna_dirac_flag = 0; - st->cng_dirac_flag = 0; - st->cng_spar_flag = 0; + st->cng_sba_flag = 0; + st->cng_ism_flag = 0; + st->read_sid_info = 1; /* by default read the sid info from bitstream */ +#ifdef DISCRETE_ISM_DTX_CNG + st->is_ism_format = 0; +#endif return error; @@ -778,12 +797,12 @@ void reset_preecho_dec( /*----------------------------------------------------------------------* - * destroy_decoder() + * destroy_cldfb_decoder() * * Free memory which was allocated in init_decoder() *----------------------------------------------------------------------*/ -void destroy_decoder( +void destroy_cldfb_decoder( Decoder_State *st /* o : Decoder static variables structure */ ) { diff --git a/lib_dec/inov_dec.c b/lib_dec/inov_dec.c index ce3c2728bca15fd4b5e5d7c2b8b386b5f9c7389a..43c7eb2c7be0eac7303258db6eb26c51761f0a87 100644 --- a/lib_dec/inov_dec.c +++ b/lib_dec/inov_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------* * inov_decode() diff --git a/lib_dec/ivas_agc_dec.c b/lib_dec/ivas_agc_dec.c index 97ce3d49d1c6cfc5725fe5cac231f850ffd3494e..72ae68a57b34d61132eee2944adf4b6f27e52a4f 100644 --- a/lib_dec/ivas_agc_dec.c +++ b/lib_dec/ivas_agc_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_AGC @@ -78,7 +78,6 @@ static void ivas_agc_dec_init( /* gain_data */ ptr->absGainExp = hAgcDec->agc_com.absEmin; ptr->absGainExpCurr = hAgcDec->agc_com.absEmin; - ptr->gainException = false; ptr++; } @@ -98,31 +97,32 @@ ivas_error ivas_spar_agc_dec_open( ) { ivas_agc_dec_state_t *hAgc; - int16_t output_frame; + int16_t output_frame, delay; - if ( ( hAgc = (ivas_agc_dec_state_t *) count_malloc( sizeof( ivas_agc_dec_state_t ) ) ) == NULL ) + if ( ( hAgc = (ivas_agc_dec_state_t *) malloc( sizeof( ivas_agc_dec_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for AGC decoder" ); } output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + delay = NS2SA( output_Fs, ( IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ) ); - if ( ( hAgc->agc_com.winFunc = (float *) count_malloc( sizeof( float ) * output_frame ) ) == NULL ) + if ( ( hAgc->agc_com.winFunc = (float *) malloc( sizeof( float ) * ( output_frame - delay ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for AGC decoder" ); } - if ( ( hAgc->gain_state = (ivas_agc_dec_chan_state_t *) count_malloc( sizeof( ivas_agc_dec_chan_state_t ) * FOA_CHANNELS ) ) == NULL ) + if ( ( hAgc->gain_state = (ivas_agc_dec_chan_state_t *) malloc( sizeof( ivas_agc_dec_chan_state_t ) * FOA_CHANNELS ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for AGC decoder" ); } - if ( ( hAgc->gain_data = (ivas_agc_chan_data_t *) count_malloc( sizeof( ivas_agc_chan_data_t ) * FOA_CHANNELS ) ) == NULL ) + if ( ( hAgc->gain_data = (ivas_agc_chan_data_t *) malloc( sizeof( ivas_agc_chan_data_t ) * FOA_CHANNELS ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for AGC decoder" ); } - ivas_agc_dec_init( hAgc, output_frame, NS2SA( output_Fs, ( IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ) ) ); + ivas_agc_dec_init( hAgc, output_frame, delay ); *hAgcDec = hAgc; @@ -142,22 +142,24 @@ void ivas_spar_agc_dec_close( { ivas_agc_dec_state_t *hAgc; + if ( hAgcDec == NULL || *hAgcDec == NULL ) + { + return; + } + hAgc = *hAgcDec; - if ( hAgc != NULL ) - { - count_free( hAgc->agc_com.winFunc ); - hAgc->agc_com.winFunc = NULL; + free( hAgc->agc_com.winFunc ); + hAgc->agc_com.winFunc = NULL; - count_free( hAgc->gain_state ); - hAgc->gain_state = NULL; + free( hAgc->gain_state ); + hAgc->gain_state = NULL; - count_free( hAgc->gain_data ); - hAgc->gain_data = NULL; + free( hAgc->gain_data ); + hAgc->gain_data = NULL; - count_free( hAgc ); - *hAgcDec = NULL; - } + free( *hAgcDec ); + *hAgcDec = NULL; return; } @@ -190,59 +192,39 @@ void ivas_agc_dec_process( if ( ( pState->gain_state[i].gainExpVal > (int32_t) ( pState->agc_com.maxAttExp + 1 ) ) || ( pState->gain_state[i].gainExpVal < -1 ) ) { - assert( 0 ); + /* Such conditions indicate packet loss, better reset and do nothing*/ + pState->gain_data[i].absGainExp = pState->agc_com.absEmin; + pState->gain_state[i].gainExpVal = 0; } - pState->gain_state[i].lastGain = powf( 2, (float) ( pState->gain_data[i].absGainExp - pState->agc_com.absEmin ) ); + pState->gain_state[i].lastGain = powf( pState->agc_com.winFunc[offset - 1], ( -1.f * (float) ( pState->gain_data[i].absGainExp - pState->agc_com.absEmin ) ) ); gainLast = 1.f / pState->gain_state[i].lastGain; - if ( !pState->gain_data[i].gainException ) + if ( pState->gain_state[i].gainExpVal != 0 ) { - if ( pState->gain_state[i].gainExpVal != 0 ) + for ( idx = 0; idx < output_frame; idx++ ) { - for ( idx = 0; idx < output_frame; idx++ ) + if ( idx >= pState->agc_com.in_delay ) { - if ( idx >= pState->agc_com.in_delay ) - { - gain = powf( pState->agc_com.winFunc[idx - pState->agc_com.in_delay], (float) ( -1 * pState->gain_state[i].gainExpVal ) ) * gainLast; - } - else - { - gain = gainLast; - } - - pcm_out[i][idx] = pcm_in[i][idx] * gain; + gain = powf( pState->agc_com.winFunc[idx - pState->agc_com.in_delay], (float) ( -1 * pState->gain_state[i].gainExpVal ) ) * gainLast; } - - pState->gain_state[i].lastGain *= powf( pState->agc_com.winFunc[offset - 1], (float) pState->gain_state[i].gainExpVal ); - } - else - { - gain = gainLast; - for ( idx = 0; idx < output_frame; idx++ ) + else { - pcm_out[i][idx] = pcm_in[i][idx] * gain; + gain = gainLast; } + + pcm_out[i][idx] = pcm_in[i][idx] * gain; } + + pState->gain_state[i].lastGain *= powf( pState->agc_com.winFunc[offset - 1], (float) pState->gain_state[i].gainExpVal ); } else { - float gainCurr = powf( 2, (float) pState->gain_state[i].gainExpVal ); - float gainTot = gainCurr * gainLast; - + gain = gainLast; for ( idx = 0; idx < output_frame; idx++ ) { - if ( idx >= pState->agc_com.in_delay ) - { - gain = gainTot; - } - else - { - gain = gainLast; - } pcm_out[i][idx] = pcm_in[i][idx] * gain; } - pState->gain_state[i].lastGain /= gainCurr; } pState->gain_data[i].absGainExp = pState->gain_data[i].absGainExpCurr; } @@ -291,12 +273,10 @@ void ivas_agc_read_bits( if ( per_ch_bit[i] == 1 ) { pState->gain_data[i].absGainExpCurr = get_next_indice( st0, (int16_t) pState->agc_com.betaE ); - pState->gain_data[i].gainException = get_next_indice( st0, 1 ); } else { pState->gain_data[i].absGainExpCurr = (int32_t) pState->agc_com.absEmin; - pState->gain_data[i].gainException = false; } } } @@ -305,7 +285,6 @@ void ivas_agc_read_bits( for ( i = 0; i < n_channels; i++ ) { pState->gain_data[i].absGainExpCurr = (int32_t) pState->agc_com.absEmin; - pState->gain_data[i].gainException = false; } } @@ -316,8 +295,6 @@ void ivas_agc_read_bits( { fread( &( pState->gain_data[i].absGainExpCurr ), sizeof( int32_t ), 1, stream ); /* n bits */ num_bits += pState->agc_com.betaE; - fread( &( pState->gain_data[i].gainException ), sizeof( int16_t ), 1, stream ); /* 1 bit */ - num_bits++; num_dmx_bits[i]++; /*fprintf(stdout, "AbsGain[%d]:= %d[%d bits]; ", i, pState->gain_data[i].absGainExp, pState->betaE);*/ diff --git a/lib_dec/ivas_binauralRenderer.c b/lib_dec/ivas_binRenderer_internal.c similarity index 68% rename from lib_dec/ivas_binauralRenderer.c rename to lib_dec/ivas_binRenderer_internal.c index 153e159adc0daa06c13c8c6d23cda5c329c8de31..2db5602519dd28b45f9741760b409d062bfc4d8c 100644 --- a/lib_dec/ivas_binauralRenderer.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,17 +33,19 @@ #include #include "options.h" #include -#include "ivas_prot.h" #include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "cnst.h" #include "ivas_cnst.h" +#include "ivas_rom_rend.h" #include "ivas_rom_dec.h" #include "ivas_rom_com.h" #include "ivas_rom_binauralRenderer.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -124,7 +126,8 @@ static ivas_error ivas_binRenderer_convModuleOpen( const int16_t renderer_type, const int16_t isLoudspeaker, const AUDIO_CONFIG input_config, - const RENDER_CONFIG_DATA *hRenderConfig ) + const RENDER_CONFIG_DATA *hRenderConfig, + const HRTFS_FASTCONV_HANDLE hHrtf ) { int16_t bandIdx, chIdx; BINRENDERER_CONV_MODULE_HANDLE hBinRenConvModule; @@ -133,7 +136,7 @@ static ivas_error ivas_binRenderer_convModuleOpen( * prepare library opening *-----------------------------------------------------------------*/ - if ( ( hBinRenConvModule = (BINRENDERER_CONV_MODULE_HANDLE) count_malloc( sizeof( BINRENDERER_CONV_MODULE ) ) ) == NULL ) + if ( ( hBinRenConvModule = (BINRENDERER_CONV_MODULE_HANDLE) malloc( sizeof( BINRENDERER_CONV_MODULE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); } @@ -186,6 +189,87 @@ static ivas_error ivas_binRenderer_convModuleOpen( } } + /* allocate memory for filter states */ + if ( ( hBinRenConvModule->filterTapsLeftReal = (float ***) malloc( hBinRenderer->conv_band * sizeof( float ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterTapsLeftImag = (float ***) malloc( hBinRenderer->conv_band * sizeof( float ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterTapsRightReal = (float ***) malloc( hBinRenderer->conv_band * sizeof( float ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterTapsRightImag = (float ***) malloc( hBinRenderer->conv_band * sizeof( float ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) + { + if ( ( hBinRenConvModule->filterTapsLeftReal[bandIdx] = (float **) malloc( hBinRenderer->nInChannels * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterTapsLeftImag[bandIdx] = (float **) malloc( hBinRenderer->nInChannels * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterTapsRightReal[bandIdx] = (float **) malloc( hBinRenderer->nInChannels * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterTapsRightImag[bandIdx] = (float **) malloc( hBinRenderer->nInChannels * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + } + + if ( ( hBinRenConvModule->filterStatesLeftReal = (float ***) malloc( hBinRenderer->conv_band * sizeof( float ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterStatesLeftImag = (float ***) malloc( hBinRenderer->conv_band * sizeof( float ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) + { + if ( ( hBinRenConvModule->filterStatesLeftReal[bandIdx] = (float **) malloc( hBinRenderer->nInChannels * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterStatesLeftImag[bandIdx] = (float **) malloc( hBinRenderer->nInChannels * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + for ( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) + { + if ( ( hBinRenConvModule->filterStatesLeftReal[bandIdx][chIdx] = (float *) malloc( hBinRenConvModule->numTapsArray[bandIdx] * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterStatesLeftImag[bandIdx][chIdx] = (float *) malloc( hBinRenConvModule->numTapsArray[bandIdx] * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + } + } + + /* set memories */ for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) { for ( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) @@ -225,15 +309,15 @@ static ivas_error ivas_binRenderer_convModuleOpen( if ( renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM && hRenderConfig->roomAcoustics.use_brir ) { /* set the memories to zero */ - set_zero( hBinRenConvModule->filterStatesLeftReal[bandIdx][chIdx], hBinRenConvModule->numTaps ); - set_zero( hBinRenConvModule->filterStatesLeftImag[bandIdx][chIdx], hBinRenConvModule->numTaps ); + set_zero( hBinRenConvModule->filterStatesLeftReal[bandIdx][chIdx], hBinRenConvModule->numTapsArray[bandIdx] ); + set_zero( hBinRenConvModule->filterStatesLeftImag[bandIdx][chIdx], hBinRenConvModule->numTapsArray[bandIdx] ); if ( isLoudspeaker ) { - hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = leftBRIRReal[bandIdx][tmp]; - hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = leftBRIRImag[bandIdx][tmp]; - hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = rightBRIRReal[bandIdx][tmp]; - hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = rightBRIRImag[bandIdx][tmp]; + hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = hHrtf->leftBRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = hHrtf->leftBRIRImag[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = hHrtf->rightBRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = hHrtf->rightBRIRImag[bandIdx][tmp]; } #ifdef DEBUGGING else @@ -251,18 +335,18 @@ static ivas_error ivas_binRenderer_convModuleOpen( if ( isLoudspeaker ) { - hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = leftHRIRReal[bandIdx][tmp]; - hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = leftHRIRImag[bandIdx][tmp]; - hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = rightHRIRReal[bandIdx][tmp]; - hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = rightHRIRImag[bandIdx][tmp]; + hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = hHrtf->leftHRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = hHrtf->leftHRIRImag[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = hHrtf->rightHRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = hHrtf->rightHRIRImag[bandIdx][tmp]; } else { /* HOA3 filter coefficients */ - hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = leftHRIRReal_HOA3[bandIdx][chIdx]; - hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = leftHRIRImag_HOA3[bandIdx][chIdx]; - hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = rightHRIRReal_HOA3[bandIdx][chIdx]; - hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = rightHRIRImag_HOA3[bandIdx][chIdx]; + hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = hHrtf->leftHRIRReal_HOA3[bandIdx][chIdx]; + hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = hHrtf->leftHRIRImag_HOA3[bandIdx][chIdx]; + hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = hHrtf->rightHRIRReal_HOA3[bandIdx][chIdx]; + hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = hHrtf->rightHRIRImag_HOA3[bandIdx][chIdx]; } } } @@ -273,6 +357,68 @@ static ivas_error ivas_binRenderer_convModuleOpen( return IVAS_ERR_OK; } +/*-------------------------------------------------------------------------* + * ivas_binaural_HRTF_open() + * + * + *-------------------------------------------------------------------------*/ + +static ivas_error ivas_binaural_hrtf_open( + HRTFS_FASTCONV_HANDLE *hHrtfFastConv /* i : fastconv HRTF handle */ +) +{ + int16_t i, j; + if ( hHrtfFastConv != NULL && *hHrtfFastConv != NULL ) + { + /* Tables already loaded from file */ + return IVAS_ERR_OK; + } + else + { + /* Initialise tables from ROM */ + HRTFS_FASTCONV *HrtfFastConv; + + if ( ( HrtfFastConv = (HRTFS_FASTCONV *) malloc( sizeof( HRTFS_FASTCONV ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for FastConv HRTF tables" ); + } + + HrtfFastConv->FASTCONV_HRIR_latency_s = FASTCONV_HRIR_latency_s; + HrtfFastConv->FASTCONV_HOA3_latency_s = FASTCONV_HOA3_latency_s; + HrtfFastConv->FASTCONV_BRIR_latency_s = FASTCONV_BRIR_latency_s; + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + mvr2r( leftHRIRReal[i][j], HrtfFastConv->leftHRIRReal[i][j], 7 ); + mvr2r( leftHRIRImag[i][j], HrtfFastConv->leftHRIRImag[i][j], 7 ); + mvr2r( rightHRIRReal[i][j], HrtfFastConv->rightHRIRReal[i][j], 7 ); + mvr2r( rightHRIRImag[i][j], HrtfFastConv->rightHRIRImag[i][j], 7 ); + + mvr2r( leftBRIRReal[i][j], HrtfFastConv->leftBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + mvr2r( leftBRIRImag[i][j], HrtfFastConv->leftBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + mvr2r( rightBRIRReal[i][j], HrtfFastConv->rightBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + mvr2r( rightBRIRImag[i][j], HrtfFastConv->rightBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + } + + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + mvr2r( leftHRIRReal_HOA3[i][j], HrtfFastConv->leftHRIRReal_HOA3[i][j], 7 ); + mvr2r( leftHRIRImag_HOA3[i][j], HrtfFastConv->leftHRIRImag_HOA3[i][j], 7 ); + mvr2r( rightHRIRReal_HOA3[i][j], HrtfFastConv->rightHRIRReal_HOA3[i][j], 7 ); + mvr2r( rightHRIRImag_HOA3[i][j], HrtfFastConv->rightHRIRImag_HOA3[i][j], 7 ); + } + } + + mvr2r( fastconvReverberationTimes, HrtfFastConv->fastconvReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + mvr2r( fastconvReverberationEneCorrections, HrtfFastConv->fastconvReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + + *hHrtfFastConv = HrtfFastConv; + } + + return IVAS_ERR_OK; +} /*-------------------------------------------------------------------------* * ivas_binaural_obtain_DMX() @@ -290,6 +436,7 @@ static void ivas_binaural_obtain_DMX( { int16_t chIdx, bandIdx, k; + // ToDo: hBinRenderer->ivas_format is never set to ISM_FORMAT -> TBV if ( hBinRenderer->ivas_format == MC_FORMAT || hBinRenderer->ivas_format == ISM_FORMAT ) { /* Obtain the downmix */ @@ -405,8 +552,6 @@ ivas_error ivas_binRenderer_open( { BINAURAL_RENDERER_HANDLE hBinRenderer; int16_t convBand, chIdx, k; - float t60[CLDFB_NO_CHANNELS_MAX]; - float ene[CLDFB_NO_CHANNELS_MAX]; ivas_error error; error = IVAS_ERR_OK; @@ -415,7 +560,7 @@ ivas_error ivas_binRenderer_open( * prepare library opening *-----------------------------------------------------------------*/ - if ( ( hBinRenderer = (BINAURAL_RENDERER_HANDLE) count_malloc( sizeof( BINAURAL_RENDERER ) ) ) == NULL ) + if ( ( hBinRenderer = (BINAURAL_RENDERER_HANDLE) malloc( sizeof( BINAURAL_RENDERER ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Renderer\n" ) ); } @@ -461,68 +606,90 @@ ivas_error ivas_binRenderer_open( hBinRenderer->render_lfe = 1; } + /* Load HRTF tables */ + ivas_binaural_hrtf_open( &st_ivas->hHrtfFastConv ); + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM && ( st_ivas->hIntSetup.is_loudspeaker_setup == 0 ) ) { IVAS_OUTPUT_SETUP out_setup; /* Allocate memories and buffers needed for convolutional module in CICP19 */ - if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, 1, AUDIO_CONFIG_7_1_4, st_ivas->hRenderConfig ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, + st_ivas->renderer_type, + 1, + AUDIO_CONFIG_7_1_4, + st_ivas->hRenderConfig, + st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) { return error; } ivas_output_init( &out_setup, AUDIO_CONFIG_7_1_4 ); - if ( ( error = ivas_sba_get_hoa_dec_matrix( out_setup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + + if ( st_ivas->hoa_dec_mtx == NULL ) { - return error; + if ( ( error = ivas_sba_get_hoa_dec_matrix( out_setup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + { + return error; + } } + hBinRenderer->hoa_dec_mtx = st_ivas->hoa_dec_mtx; - st_ivas->binaural_latency_ns = (int32_t) ( FASTCONV_BRIR_latency_s * 1000000000.f ); + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_BRIR_latency_s * 1000000000.f ); } else { /* Allocate memories and buffers needed for convolutional module */ - if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, st_ivas->hIntSetup.is_loudspeaker_setup, st_ivas->hIntSetup.output_config, st_ivas->hRenderConfig ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, + st_ivas->renderer_type, + st_ivas->hIntSetup.is_loudspeaker_setup, + st_ivas->hIntSetup.output_config, + st_ivas->hRenderConfig, + st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) { return error; } - if ( hBinRenderer->ivas_format == MC_FORMAT ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) { - st_ivas->binaural_latency_ns = (int32_t) ( FASTCONV_HRIR_latency_s * 1000000000.f ); + if ( hBinRenderer->ivas_format == MC_FORMAT ) + { + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_HRIR_latency_s * 1000000000.f ); + } + else + { + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_HOA3_latency_s * 1000000000.f ); + } } else { - st_ivas->binaural_latency_ns = (int32_t) ( FASTCONV_HOA3_latency_s * 1000000000.f ); + /* same value for MC or HOA both use MC BRIR*/ + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_BRIR_latency_s * 1000000000.f ); } } /* Allocate memories needed for reverb module */ if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM && st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) { - if ( ( error = ivas_binaural_reverb_open( &( hBinRenderer->hReverb ), hBinRenderer->conv_band, hBinRenderer->timeSlots ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binaural_reverb_open( &( hBinRenderer->hReverb ), + hBinRenderer->conv_band, + hBinRenderer->timeSlots, + &( st_ivas->hRenderConfig->roomAcoustics ), + st_ivas->hIntSetup.output_config, + st_ivas->hDecoderConfig->output_Fs, + RENDERER_BINAURAL_FASTCONV_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) { return error; } - if ( !st_ivas->hRenderConfig->roomAcoustics.override ) - { - ivas_binaural_reverb_setReverbTimes( hBinRenderer->hReverb, st_ivas->hDecoderConfig->output_Fs, fastconvReverberationTimes, fastconvReverberationEneCorrections ); - ivas_binaural_reverb_setPreDelay( hBinRenderer->hReverb, 10 ); - } - else - { - ivas_reverb_prepare_cldfb_params( &st_ivas->hRenderConfig->roomAcoustics, st_ivas->hIntSetup.output_config, st_ivas->hRenderConfig->roomAcoustics.use_brir, st_ivas->hDecoderConfig->output_Fs, t60, ene ); - ivas_binaural_reverb_setReverbTimes( hBinRenderer->hReverb, st_ivas->hDecoderConfig->output_Fs, t60, ene ); - ivas_binaural_reverb_setPreDelay( hBinRenderer->hReverb, (int16_t) roundf( 48000.0f * st_ivas->hRenderConfig->roomAcoustics.acousticPreDelay / CLDFB_NO_CHANNELS_MAX ) ); - } - hBinRenderer->hReverb->useBinauralCoherence = 1; /* initialize the dmx matrix */ for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) { for ( k = 0; k < hBinRenderer->nInChannels; k++ ) { - hBinRenderer->hReverb->dmxmtx[chIdx][k] = dmxmtx[chIdx][k]; + hBinRenderer->hReverb->dmxmtx[chIdx][k] = dmxmtx_table[chIdx][k]; } } } @@ -561,6 +728,86 @@ ivas_error ivas_binRenderer_open( } +/*------------------------------------------------------------------------- + * ivas_binRenderer_convModuleClose() + * + * Close convolution module handle of fastconv binaural renderer + *------------------------------------------------------------------------*/ + +static void ivas_binRenderer_convModuleClose( + BINAURAL_RENDERER_HANDLE *hBinRenderer /* i/o: fastconv binaural renderer handle */ +) +{ + int16_t bandIdx, chIdx; + BINRENDERER_CONV_MODULE_HANDLE hBinRenConvModule; + + hBinRenConvModule = ( *hBinRenderer )->hBinRenConvModule; + + if ( hBinRenConvModule == NULL ) + { + return; + } + + for ( bandIdx = 0; bandIdx < ( *hBinRenderer )->conv_band; bandIdx++ ) + { + free( hBinRenConvModule->filterTapsLeftReal[bandIdx] ); + hBinRenConvModule->filterTapsLeftReal[bandIdx] = NULL; + + free( hBinRenConvModule->filterTapsLeftImag[bandIdx] ); + hBinRenConvModule->filterTapsLeftImag[bandIdx] = NULL; + + free( hBinRenConvModule->filterTapsRightReal[bandIdx] ); + hBinRenConvModule->filterTapsRightReal[bandIdx] = NULL; + + free( hBinRenConvModule->filterTapsRightImag[bandIdx] ); + hBinRenConvModule->filterTapsRightImag[bandIdx] = NULL; + } + + free( hBinRenConvModule->filterTapsLeftReal ); + hBinRenConvModule->filterTapsLeftReal = NULL; + + free( hBinRenConvModule->filterTapsLeftImag ); + hBinRenConvModule->filterTapsLeftImag = NULL; + + free( hBinRenConvModule->filterTapsRightReal ); + hBinRenConvModule->filterTapsRightReal = NULL; + + free( hBinRenConvModule->filterTapsRightImag ); + hBinRenConvModule->filterTapsRightImag = NULL; + + + for ( bandIdx = 0; bandIdx < ( *hBinRenderer )->conv_band; bandIdx++ ) + { + for ( chIdx = 0; chIdx < ( *hBinRenderer )->nInChannels; chIdx++ ) + { + free( hBinRenConvModule->filterStatesLeftReal[bandIdx][chIdx] ); + hBinRenConvModule->filterStatesLeftReal[bandIdx][chIdx] = NULL; + + free( hBinRenConvModule->filterStatesLeftImag[bandIdx][chIdx] ); + hBinRenConvModule->filterStatesLeftImag[bandIdx][chIdx] = NULL; + } + + free( hBinRenConvModule->filterStatesLeftReal[bandIdx] ); + hBinRenConvModule->filterStatesLeftReal[bandIdx] = NULL; + + free( hBinRenConvModule->filterStatesLeftImag[bandIdx] ); + hBinRenConvModule->filterStatesLeftImag[bandIdx] = NULL; + } + + free( hBinRenConvModule->filterStatesLeftReal ); + hBinRenConvModule->filterStatesLeftReal = NULL; + + free( hBinRenConvModule->filterStatesLeftImag ); + hBinRenConvModule->filterStatesLeftImag = NULL; + + + free( ( *hBinRenderer )->hBinRenConvModule ); + ( *hBinRenderer )->hBinRenConvModule = NULL; + + return; +} + + /*------------------------------------------------------------------------- * ivas_binRenderer_close() * @@ -578,8 +825,7 @@ void ivas_binRenderer_close( if ( ( *hBinRenderer )->hBinRenConvModule != NULL ) { - count_free( ( *hBinRenderer )->hBinRenConvModule ); - ( *hBinRenderer )->hBinRenConvModule = NULL; + ivas_binRenderer_convModuleClose( hBinRenderer ); } if ( ( *hBinRenderer )->hReverb != NULL ) @@ -587,7 +833,7 @@ void ivas_binRenderer_close( ivas_binaural_reverb_close( &( ( *hBinRenderer )->hReverb ) ); } - count_free( *hBinRenderer ); + free( *hBinRenderer ); *hBinRenderer = NULL; return; @@ -620,7 +866,14 @@ void ivas_binaural_add_LFE( if ( render_lfe ) { - gain = st_ivas->hHrtf != NULL ? st_ivas->hHrtf->gain_lfe : GAIN_LFE; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + { + gain = GAIN_LFE; + } + else + { + gain = ( ( st_ivas->hCrendWrapper != NULL ) && ( st_ivas->hCrendWrapper->hHrtfCrend != NULL ) ) ? st_ivas->hCrendWrapper->hHrtfCrend->gain_lfe : GAIN_LFE; + } for ( idx_lfe = 0; idx_lfe < st_ivas->hIntSetup.num_lfe; idx_lfe++ ) { v_multc( output_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], gain, output_f[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_frame ); @@ -634,8 +887,9 @@ void ivas_binaural_add_LFE( } +#ifdef DEBUGGING /*-------------------------------------------------------------------------* - * ivas_binRenderer_cldfb() + * ivas_binaural_cldfb() * * Perform CLDFB analysis, fastconv binaural rendering and CLDFB synthesis *-------------------------------------------------------------------------*/ @@ -707,6 +961,7 @@ void ivas_binaural_cldfb( return; } +#endif /*------------------------------------------------------------------------- @@ -727,7 +982,7 @@ void ivas_binRenderer( int16_t chIdx, k; int16_t numTimeSlots = MAX_PARAM_SPATIAL_SUBFRAMES; - wmops_sub_start( "fastconv_binaural_rendering" ); + push_wmops( "fastconv_binaural_rendering" ); /* Compute Convolution */ /* memory reset for the binaural output */ @@ -749,7 +1004,6 @@ void ivas_binRenderer( if ( hHeadTrackData->shd_rot_max_order == -1 ) { QuatToRotMat( hHeadTrackData->Quaternions[hHeadTrackData->num_quaternions++], hHeadTrackData->Rmat ); - rotateFrame_shd_cldfb( RealBuffer, ImagBuffer, hHeadTrackData->Rmat, hBinRenderer->hInputSetup->nchan_out_woLFE, 3 ); } else if ( hHeadTrackData->shd_rot_max_order > 0 ) @@ -775,10 +1029,10 @@ void ivas_binRenderer( /* Obtain the binaural dmx and compute the reverb */ if ( hBinRenderer->hReverb != NULL ) { - float reverbRe[2][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float reverbIm[2][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float inRe[2][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float inIm[2][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float reverbRe[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float reverbIm[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float inRe[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float inIm[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; ivas_binaural_obtain_DMX( numTimeSlots, hBinRenderer, RealBuffer, ImagBuffer, inRe, inIm ); @@ -791,7 +1045,7 @@ void ivas_binRenderer( } } - ivas_binaural_reverb_processFrame( hBinRenderer->hReverb, 2, inRe, inIm, reverbRe, reverbIm, 0u ); + ivas_binaural_reverb_processFrame( hBinRenderer->hReverb, BINAURAL_CHANNELS, inRe, inIm, reverbRe, reverbIm, 0u ); /* Add the conv module and reverb module output */ for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) @@ -805,7 +1059,7 @@ void ivas_binRenderer( } } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_dec/ivas_binaural_reverb.c b/lib_dec/ivas_binaural_reverb.c deleted file mode 100644 index 054b8c1558af5fd09adc51a98d0e26e0c16cbd2e..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_binaural_reverb.c +++ /dev/null @@ -1,498 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include -#include "ivas_prot.h" -#include "prot.h" -#include "ivas_rom_com.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "wmops.h" - - -/* The reverberator structure implemented here is described in detail in: - * Vilkamo, J., Neugebauer, B., & Plogsties, J. (2012). Sparse frequency-domain reverberator. - * Journal of the Audio Engineering Society, 59(12), 936-943. */ - -/*------------------------------------------------------------------------- - * Local constants - *------------------------------------------------------------------------*/ - -#define BIN_REND_RANDOM_SEED 1 /* random seed for generating reverb decorrelators */ - -#define CLDFB_SLOTS_PER_SECOND 800 /* Used for initializing reverb */ - -/*------------------------------------------------------------------------- - * ivas_binaural_reverb_processFrame() - * - * Compute the reverberation - room effect - *------------------------------------------------------------------------*/ - -void ivas_binaural_reverb_processFrame( - REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ - const int16_t numInChannels, /* i : num inputs to be processed */ - float inReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */ - float inImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ - float outReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ - float outImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data imag */ - const uint8_t offsetSamplesIO /* i : number of offset samples */ -) -{ - /* Declare the required variables */ - int16_t idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr; - float **tapRealPr, **tapImagPr; - - /* 1) Rotate the data in the loop buffer of the reverberator. - * Notice that the audio at the loop buffers is at time-inverted order - * for convolution purposes later on. */ - for ( bin = 0; bin < hReverb->numBins; bin++ ) - { - /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */ - mvr2r( hReverb->loopBufReal[bin], hReverb->loopBufReal[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); - mvr2r( hReverb->loopBufImag[bin], hReverb->loopBufImag[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); - - /* Add the data from the end of the loop to the beginning, with an attenuation factor - * according to RT60. This procedure generates an IIR decaying response. The response - * is decorrelated later on. */ - v_multc( hReverb->loopBufReal[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufReal[bin], hReverb->blockSize ); - v_multc( hReverb->loopBufImag[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufImag[bin], hReverb->blockSize ); - } - - /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */ - idx = hReverb->preDelayBufferIndex; - for ( sample = 0; sample < hReverb->blockSize; sample++ ) - { - uint16_t sampleWithOffset; - sampleWithOffset = sample + offsetSamplesIO; - invertSampleIndex = hReverb->blockSize - sample - 1; - for ( bin = 0; bin < hReverb->numBins; bin++ ) - { - /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order. - * Also apply the spectral gains determined for the reverberation */ - hReverb->loopBufReal[bin][invertSampleIndex] += hReverb->preDelayBufferReal[idx][bin] * hReverb->reverbEqGains[bin]; - hReverb->loopBufImag[bin][invertSampleIndex] += hReverb->preDelayBufferImag[idx][bin] * hReverb->reverbEqGains[bin]; - hReverb->preDelayBufferReal[idx][bin] = 0.0f; - hReverb->preDelayBufferImag[idx][bin] = 0.0f; - } - - /* Add every second input channel as is to the pre-delay buffer, and every second input channel with - * 90 degrees phase shift to reduce energy imbalances between coherent and incoherent sounds */ - for ( ch = 0; ch < numInChannels; ch++ ) - { - if ( ch % 2 ) - { - v_add( hReverb->preDelayBufferReal[idx], inReal[ch][sampleWithOffset], hReverb->preDelayBufferReal[idx], hReverb->numBins ); - v_add( hReverb->preDelayBufferImag[idx], inImag[ch][sampleWithOffset], hReverb->preDelayBufferImag[idx], hReverb->numBins ); - } - else - { - v_sub( hReverb->preDelayBufferReal[idx], inImag[ch][sampleWithOffset], hReverb->preDelayBufferReal[idx], hReverb->numBins ); - v_add( hReverb->preDelayBufferImag[idx], inReal[ch][sampleWithOffset], hReverb->preDelayBufferImag[idx], hReverb->numBins ); - } - } - idx = ( idx + 1 ) % hReverb->preDelayBufferLength; - } - hReverb->preDelayBufferIndex = idx; - - /* 3) Perform the filtering/decorrelating, using complex and sparse FIR filtering */ - for ( bin = 0; bin < hReverb->numBins; bin++ ) - { - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - /* These tap pointers have been determined to point to the loop buffer at sparse locations */ - tapRealPr = hReverb->tapPointersReal[bin][ch]; - tapImagPr = hReverb->tapPointersImag[bin][ch]; - phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch]; - - /* Flush output */ - set_f( hReverb->outputBufferReal[bin][ch], 0.0f, hReverb->blockSize ); - set_f( hReverb->outputBufferImag[bin][ch], 0.0f, hReverb->blockSize ); - - /* Add from temporally decaying sparse tap locations the audio to the output. */ - for ( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ ) - { - switch ( phaseShiftTypePr[tapIdx] ) - { - case 0: /* 0 degrees phase */ - v_add( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); - v_add( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); - break; - case 1: /* 90 degrees phase */ - v_sub( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); - v_add( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); - break; - case 2: /* 180 degrees phase */ - v_sub( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); - v_sub( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); - break; - default: /* 270 degrees phase */ - v_add( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); - v_sub( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); - break; - } - } - } - - /* Generate diffuse field binaural coherence by mixing the incoherent reverberated channels with pre-defined gains */ - if ( bin <= hReverb->highestBinauralCoherenceBin ) - { - if ( hReverb->useBinauralCoherence ) - { - for ( sample = 0; sample < hReverb->blockSize; sample++ ) - { - float leftRe, rightRe, leftIm, rightIm; - - leftRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][1][sample]; - rightRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][0][sample]; - leftIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][1][sample]; - rightIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][0][sample]; - - hReverb->outputBufferReal[bin][0][sample] = leftRe; - hReverb->outputBufferReal[bin][1][sample] = rightRe; - hReverb->outputBufferImag[bin][0][sample] = leftIm; - hReverb->outputBufferImag[bin][1][sample] = rightIm; - } - } - } - } - - /* 4) Write data to output */ - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - for ( sample = 0; sample < hReverb->blockSize; sample++ ) - { - uint16_t sampleWithOffset; - - sampleWithOffset = sample + offsetSamplesIO; - /* Audio was in the temporally inverted order for convolution, re-invert audio to output */ - invertSampleIndex = hReverb->blockSize - sample - 1; - - for ( bin = 0; bin < hReverb->numBins; bin++ ) - { - outReal[ch][sampleWithOffset][bin] = hReverb->outputBufferReal[bin][ch][invertSampleIndex]; - outImag[ch][sampleWithOffset][bin] = hReverb->outputBufferImag[bin][ch][invertSampleIndex]; - } - for ( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) - { - outReal[ch][sampleWithOffset][bin] = 0.0f; - outImag[ch][sampleWithOffset][bin] = 0.0f; - } - } - } - - return; -} - - -/*------------------------------------------------------------------------- - * binRend_rand() - * - * - *------------------------------------------------------------------------*/ - -static uint16_t binRend_rand( - REVERB_STRUCT_HANDLE hReverb /* i/o: binaural reverb handle */ -) -{ - hReverb->binRend_RandNext = hReverb->binRend_RandNext * 1103515245 + 12345; - - return (uint16_t) ( hReverb->binRend_RandNext / 65536 ) % 32768; -} - - -/*------------------------------------------------------------------------- - * ivas_binaural_reverb_setPreDelay() - * - * - *------------------------------------------------------------------------*/ - -void ivas_binaural_reverb_setPreDelay( - REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ - const int16_t delaySamples /* i : reverb pre-delay in CLDFB slots */ -) -{ - if ( delaySamples < 1 ) - { - hReverb->preDelayBufferLength = 1; - - return; - } - - if ( delaySamples > REVERB_PREDELAY_MAX ) - { - hReverb->preDelayBufferLength = REVERB_PREDELAY_MAX; - - return; - } - - hReverb->preDelayBufferLength = delaySamples; - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_binaural_reverb_setReverbTimes() - * - * - *------------------------------------------------------------------------*/ - -void ivas_binaural_reverb_setReverbTimes( - REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ - const int32_t output_Fs, /* i : sampling_rate */ - const float *revTimes, /* i : reverberation times T60 for each CLDFB bin in seconds */ - const float *revEnes /* i : spectrum for reverberated sound at each CLDFB bin */ -) -{ - int16_t bin, ch, tap, sample; - float binCenterFreq, diffuseFieldICC, tmpVal, attenuationFactorPerSample; - float intendedEnergy, actualizedEnergy, energyBuildup, currentEnergy, attenuationFactorPerSampleSq; - - hReverb->binRend_RandNext = (uint16_t) BIN_REND_RANDOM_SEED; - hReverb->highestBinauralCoherenceBin = 0; - for ( bin = 0; bin < hReverb->numBins; bin++ ) - { - /* Determine the diffuse field binaural coherence */ - binCenterFreq = ( (float) bin + 0.5f ) / ( (float) hReverb->numBins ) * ( (float) output_Fs ) / 2.0f; - if ( bin == 0 ) - { - diffuseFieldICC = 1.0f; - } - else if ( binCenterFreq < 2700.0f ) - { - diffuseFieldICC = sinf( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) / ( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) * ( 1.0f - binCenterFreq / 2700.0f ); - hReverb->highestBinauralCoherenceBin = bin; - } - else - { - diffuseFieldICC = 0.0f; - } - - /* Mixing gains to generate a diffuse-binaural sound based on incoherent sound */ - tmpVal = ( 1.0f - sqrtf( 1.0f - powf( diffuseFieldICC, 2.0 ) ) ) / 2.0f; - if ( diffuseFieldICC > 0 ) - { - hReverb->binauralCoherenceCrossmixGains[bin] = sqrtf( fabsf( tmpVal ) ); - } - else - { - hReverb->binauralCoherenceCrossmixGains[bin] = -sqrtf( fabsf( tmpVal ) ); - } - hReverb->binauralCoherenceDirectGains[bin] = sqrtf( 1.0f - fabsf( tmpVal ) ); - - /* Determine loop buffer length. The following formula is manually tuned to generate sufficiently long - * but not excessively long loops to generate reverberation. */ - /* Note: the resulted length is very sensitive to the precision of the constants below (e.g. 1.45 vs. 1.45f) */ - hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 ); - hReverb->loopBufLength[bin] = min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] ); - - /* Determine attenuation factor that generates the appropriate energy decay according to reverberation time */ - attenuationFactorPerSample = powf( 10.0f, -3.0f * ( 1.0f / ( (float) CLDFB_SLOTS_PER_SECOND * revTimes[bin] ) ) ); - hReverb->loopAttenuationFactor[bin] = powf( attenuationFactorPerSample, hReverb->loopBufLength[bin] ); - attenuationFactorPerSampleSq = attenuationFactorPerSample * attenuationFactorPerSample; - - /* Design sparse decorrelation filters. The decorrelation filters, due to random procedures involved, - * may affect the spectrum of the output. The spectral effect is therefore monitored and compensated for. */ - intendedEnergy = 0.0f; - actualizedEnergy = 0.0f; - - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - energyBuildup = 0.0f; - currentEnergy = 1.0f; - tap = 0; - - for ( sample = 0; sample < hReverb->loopBufLength[bin]; sample++ ) - { - intendedEnergy += currentEnergy; - /* The randomization at the energy build up affects where the sparse taps are located */ - energyBuildup += currentEnergy + 0.1f * ( (float) binRend_rand( hReverb ) / PCM16_TO_FLT_FAC - 0.5f ); - if ( energyBuildup >= 1.0f ) /* A new filter tap is added at this condition */ - { - /* Four efficient phase operations: n*pi/2, n=0,1,2,3 */ - hReverb->tapPhaseShiftType[bin][ch][tap] = (int16_t) ( binRend_rand( hReverb ) % 4 ); - /* Set the tapPointer to point to the determined sample at the loop buffer */ - hReverb->tapPointersReal[bin][ch][tap] = &( hReverb->loopBufReal[bin][sample] ); - hReverb->tapPointersImag[bin][ch][tap] = &( hReverb->loopBufImag[bin][sample] ); - energyBuildup -= 1.0f; /* A tap is added, thus remove its energy from the buildup */ - tap++; - actualizedEnergy += 1.0f; - } - currentEnergy *= attenuationFactorPerSampleSq; - } - hReverb->taps[bin][ch] = tap; /* Number of taps determined at the above random procedure */ - } - - /* The decorrelator design and IIR attenuation rate affects the energy of reverb, which is compensated here */ - hReverb->reverbEqGains[bin] = sqrtf( revEnes[bin] ); /* Determined reverb spectrum */ - hReverb->reverbEqGains[bin] *= sqrtf( intendedEnergy / actualizedEnergy ); /* Correction of random effects at the decorrelator design */ - hReverb->reverbEqGains[bin] *= sqrtf( 0.5f * ( 1.0f - attenuationFactorPerSampleSq ) ); /* Correction of IIR decay rate */ - } - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_binaural_reverb_open() - * - * Allocate and initialize binaural room reverberator handle - *------------------------------------------------------------------------*/ - -ivas_error ivas_binaural_reverb_open( - REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ - const int16_t numBins, /* i : number of CLDFB bins */ - const int16_t numCldfbSlotsPerFrame /* i : number of CLDFB slots per frame, i.e., reverberator block size */ -) -{ - int16_t bin, chIdx, k, tmp; - REVERB_STRUCT_HANDLE hReverb; - - if ( ( *hReverbPr = (REVERB_STRUCT_HANDLE) count_malloc( sizeof( REVERB_STRUCT ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - hReverb = *hReverbPr; - - hReverb->useBinauralCoherence = 0; - hReverb->preDelayBufferLength = 1; - hReverb->preDelayBufferIndex = 0; - - hReverb->numBins = numBins; - hReverb->blockSize = numCldfbSlotsPerFrame; - - for ( k = 0; k < REVERB_PREDELAY_MAX + 1; k++ ) - { - set_f( hReverb->preDelayBufferReal[k], 0.0f, hReverb->numBins ); - set_f( hReverb->preDelayBufferImag[k], 0.0f, hReverb->numBins ); - } - - for ( bin = 0; bin < hReverb->numBins; bin++ ) - { - /* Loop Buffer */ - hReverb->loopBufLengthMax[bin] = (int16_t) ( 500 / ( 1 + bin ) + ( CLDFB_NO_CHANNELS_MAX - bin ) ); - - tmp = hReverb->loopBufLengthMax[bin] + hReverb->blockSize; - if ( ( hReverb->loopBufReal[bin] = (float *) count_malloc( tmp * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - if ( ( hReverb->loopBufImag[bin] = (float *) count_malloc( tmp * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - set_f( hReverb->loopBufReal[bin], 0.0f, tmp ); - set_f( hReverb->loopBufImag[bin], 0.0f, tmp ); - - /* Sparse Filter Tap Locations */ - for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) - { - tmp = hReverb->loopBufLengthMax[bin]; - - if ( ( hReverb->tapPhaseShiftType[bin][chIdx] = (int16_t *) count_malloc( tmp * sizeof( int16_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - if ( ( hReverb->tapPointersReal[bin][chIdx] = (float **) count_malloc( tmp * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - if ( ( hReverb->tapPointersImag[bin][chIdx] = (float **) count_malloc( tmp * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - set_s( hReverb->tapPhaseShiftType[bin][chIdx], 0, tmp ); - - tmp = hReverb->blockSize; - if ( ( hReverb->outputBufferReal[bin][chIdx] = (float *) count_malloc( tmp * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - if ( ( hReverb->outputBufferImag[bin][chIdx] = (float *) count_malloc( tmp * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); - } - - set_f( hReverb->outputBufferReal[bin][chIdx], 0.0f, tmp ); - set_f( hReverb->outputBufferImag[bin][chIdx], 0.0f, tmp ); - } - } - - return IVAS_ERR_OK; -} - - -/*------------------------------------------------------------------------- - * ivas_binaural_reverb_close() - * - * Close binaural room reverberator handle - *------------------------------------------------------------------------*/ - -void ivas_binaural_reverb_close( - REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */ -) -{ - int16_t bin, chIdx; - - if ( hReverb == NULL || *hReverb == NULL ) - { - return; - } - - for ( bin = 0; bin < ( *hReverb )->numBins; bin++ ) - { - for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) - { - count_free( ( *hReverb )->tapPhaseShiftType[bin][chIdx] ); - count_free( ( *hReverb )->tapPointersReal[bin][chIdx] ); - count_free( ( *hReverb )->tapPointersImag[bin][chIdx] ); - count_free( ( *hReverb )->outputBufferReal[bin][chIdx] ); - count_free( ( *hReverb )->outputBufferImag[bin][chIdx] ); - } - count_free( ( *hReverb )->loopBufReal[bin] ); - count_free( ( *hReverb )->loopBufImag[bin] ); - } - - count_free( ( *hReverb ) ); - - return; -} diff --git a/lib_dec/ivas_core_dec.c b/lib_dec/ivas_core_dec.c index b5dd559f5fddeca1736ab618f8c6fc08c93b4285..05c1f41727e87111757dd6ca304ae100226350cc 100644 --- a/lib_dec/ivas_core_dec.c +++ b/lib_dec/ivas_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,16 +35,14 @@ #ifdef DEBUGGING #include "debug.h" #endif -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT #include -#endif #include #include "cnst.h" #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" #include "ivas_rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif @@ -99,7 +97,7 @@ ivas_error ivas_core_dec( error = IVAS_ERR_OK; - wmops_sub_start( "ivas_core_dec" ); + push_wmops( "ivas_core_dec" ); /*------------------------------------------------------------------* * General initialization @@ -183,51 +181,11 @@ ivas_error ivas_core_dec( st->flagGuidedAcelp = 0; } -#ifndef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - /* PLC: [TCX: Fade-out-recovery] - overlapping part needs to be attenuated for first good frame */ - if ( !st->bfi && st->prev_bfi && ( st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE ) && st->element_mode != IVAS_CPE_MDCT ) - { - if ( st->hPlcInfo != NULL ) - { - v_multc( st->hHQ_core->old_out, st->hPlcInfo->recovery_gain, st->hHQ_core->old_out, st->hTcxDec->L_frameTCX ); - v_multc( st->hHQ_core->old_outLB, st->hPlcInfo->recovery_gain, st->hHQ_core->old_outLB, st->L_frame ); - - if ( !st->hTcxCfg->last_aldo && st->hTcxDec != NULL ) - { - v_multc( st->hTcxDec->syn_OverlFB, st->hPlcInfo->recovery_gain, st->hTcxDec->syn_OverlFB, st->hTcxCfg->tcx_mdct_window_lengthFB ); - v_multc( st->hTcxDec->syn_Overl, st->hPlcInfo->recovery_gain, st->hTcxDec->syn_Overl, st->hTcxCfg->tcx_mdct_window_length ); - } - } - } -#else - /* PLC: [TCX: Fade-out-recovery] - overlapping part needs to be attenuated for first good frame */ - if ( !st->bfi && st->prev_bfi && ( st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE ) ) + if ( !st->bfi && st->prev_bfi && ( st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE ) && st->hTcxDec != NULL ) { - float gain; - if ( st->hPlcInfo != NULL ) - { - gain = st->hPlcInfo->recovery_gain; - } - else if ( st->hTcxDec != NULL ) - { - gain = st->hTcxDec->conceal_eof_gain; - } - else - { - gain = 0.f; - assert( !"This should never happen." ); - } - - v_multc( st->hHQ_core->old_out, gain, st->hHQ_core->old_out, st->hTcxDec->L_frameTCX ); - v_multc( st->hHQ_core->old_outLB, gain, st->hHQ_core->old_outLB, st->L_frame ); - - if ( !st->hTcxCfg->last_aldo && st->hTcxDec != NULL ) - { - v_multc( st->hTcxDec->syn_OverlFB, gain, st->hTcxDec->syn_OverlFB, st->hTcxCfg->tcx_mdct_window_lengthFB ); - v_multc( st->hTcxDec->syn_Overl, gain, st->hTcxDec->syn_Overl, st->hTcxCfg->tcx_mdct_window_length ); - } + v_multc( st->hHQ_core->old_out, st->hTcxDec->conceal_eof_gain * st->last_concealed_gain_syn_deemph, st->hHQ_core->old_out, st->hTcxDec->L_frameTCX ); + v_multc( st->hHQ_core->old_outLB, st->hTcxDec->conceal_eof_gain * st->last_concealed_gain_syn_deemph, st->hHQ_core->old_outLB, st->L_frame ); } -#endif set_f( voice_factors[n], 0.f, NB_SUBFR16k ); set_f( hb_synth[n], 0.0f, L_FRAME48k ); @@ -282,7 +240,7 @@ ivas_error ivas_core_dec( hCPE->hStereoCng->flag_cna_fade = 0; } - if ( sba_dirac_stereo_flag && sts[0]->total_brate <= SID_2k40 && sts[0]->cng_type == FD_CNG ) + if ( sba_dirac_stereo_flag && hSCE && sts[0]->total_brate <= SID_2k40 && sts[0]->cng_type == FD_CNG ) { save_hb_synth = hSCE->save_hb_synth; } @@ -297,7 +255,7 @@ ivas_error ivas_core_dec( if ( sts[0]->element_mode == IVAS_CPE_MDCT && sts[0]->total_brate == SID_2k40 ) { - if ( sts[0]->cng_dirac_flag ) + if ( sts[0]->cng_sba_flag ) { FdCngDecodeDiracMDCTStereoSID( hCPE ); } @@ -383,7 +341,12 @@ ivas_error ivas_core_dec( if ( ( st->core == TCX_20_CORE || st->core == TCX_10_CORE ) && st->element_mode != IVAS_CPE_MDCT ) { /* TCX decoder */ - stereo_tcx_core_dec( st, frameMode[n], output[n], synth[n], pitch_buf[n], sba_dirac_stereo_flag, hStereoTD, last_element_mode, flag_sec_CNA, hCPE == NULL ? NULL : hCPE->hStereoCng, nchan_out ); + stereo_tcx_core_dec( st, frameMode[n], output[n], synth[n], pitch_buf[n], sba_dirac_stereo_flag, hStereoTD, last_element_mode, flag_sec_CNA, hCPE == NULL ? NULL : hCPE->hStereoCng, nchan_out, st_ivas == NULL ? 0 : st_ivas->ivas_format +#ifndef DISCRETE_ISM_DTX_CNG + , + st_ivas == NULL ? 0 : st_ivas->ism_mode +#endif + ); } if ( st->core == HQ_CORE ) @@ -414,7 +377,7 @@ ivas_error ivas_core_dec( { if ( hMCT ) { - wmops_sub_end(); + pop_wmops(); return error; } @@ -428,6 +391,18 @@ ivas_error ivas_core_dec( { updateBuffersForDmxMdctStereo( hCPE, output_frame, output, synth ); } + + if ( sts[0]->bfi == 0 && sts[0]->prev_bfi == 1 ) + { + /* On first good frame after frameloss undo the whitening of the bg noise shape */ + for ( n = 0; n < n_channels; ++n ) + { + if ( sts[n]->last_core_bfi != ACELP_CORE ) + { + TonalMdctConceal_whiten_noise_shape( sts[n], L_FRAME16k, ON_FIRST_GOOD_FRAME ); + } + } + } } /*---------------------------------------------------------------------* @@ -471,19 +446,23 @@ ivas_error ivas_core_dec( *---------------------------------------------------------------------*/ /* save synth and output in case of SBA DirAC stereo output as core switching is done outside of core decoder */ - if ( sba_dirac_stereo_flag && !( st->core_brate == SID_2k40 && st->cng_type == FD_CNG ) ) + if ( sba_dirac_stereo_flag && st->element_mode != IVAS_CPE_MDCT && !( st->core_brate == SID_2k40 && st->cng_type == FD_CNG ) ) { mvr2r( synth[n], hSCE->save_synth, output_frame ); } +#ifdef FIX_ISM_DTX_CLICKS + if ( ( error = core_switching_post_dec( st, synth[n], output[n], p_output_mem, ( st_ivas != NULL ) ? st_ivas->ivas_format : UNDEFINED_FORMAT, use_cldfb_for_dft, output_frame, 0 /*core_switching_flag*/, sba_dirac_stereo_flag, nchan_out, ( hCPE != NULL ) ? hCPE->last_element_mode : IVAS_SCE ) ) != IVAS_ERR_OK ) +#else if ( ( error = core_switching_post_dec( st, synth[n], output[n], p_output_mem, use_cldfb_for_dft, output_frame, 0 /*core_switching_flag*/, sba_dirac_stereo_flag, nchan_out, ( hCPE != NULL ) ? hCPE->last_element_mode : IVAS_SCE ) ) != IVAS_ERR_OK ) +#endif { return error; } /* for FD-CNG we need the delay compensation in the synth, so do this afterwards */ - if ( sba_dirac_stereo_flag && st->core_brate == SID_2k40 && st->cng_type == FD_CNG ) + if ( sba_dirac_stereo_flag && hSCE && st->core_brate == SID_2k40 && st->cng_type == FD_CNG ) { mvr2r( synth[n], hSCE->save_synth, output_frame ); } @@ -531,9 +510,9 @@ ivas_error ivas_core_dec( swb_tbe_dec( st, hStereoICBWE, bwe_exc_extended[n], voice_factors[n], old_syn_12k8_16k[n], tmp_buffer /*fb_exc*/, hb_synth[n], pitch_buf[n] ); /* FB TBE decoder */ - if ( output_frame == L_FRAME48k && st->extl == FB_TBE ) + if ( st->extl == FB_TBE ) { - fb_tbe_dec( st, tmp_buffer /*fb_exc*/, hb_synth[n], tmp_buffer /*fb_synth_ref*/ ); + fb_tbe_dec( st, tmp_buffer /*fb_exc*/, hb_synth[n], tmp_buffer /*fb_synth_ref*/, output_frame ); } } else if ( st->extl == SWB_BWE || st->extl == FB_BWE || ( output_Fs >= 32000 && st->core == ACELP_CORE && st->bwidth > NB && st->bws_cnt > 0 && !st->ppp_mode_dec && !( st->nelp_mode_dec == 1 && st->bfi == 1 ) ) ) @@ -690,7 +669,7 @@ ivas_error ivas_core_dec( } } - if ( sba_dirac_stereo_flag ) + if ( sba_dirac_stereo_flag && st->element_mode != IVAS_CPE_MDCT ) { /* for SBA DirAC stereo output DFT Stereo core switching and updates are done in ivas_sba_dirac_stereo_dec() as hCPE is not available at this point */ break; @@ -705,13 +684,16 @@ ivas_error ivas_core_dec( if ( st->element_mode != IVAS_CPE_DFT ) { - if ( st->element_mode != IVAS_CPE_MDCT ) + if ( st->element_mode != IVAS_CPE_MDCT || sba_dirac_stereo_flag ) { - ivas_post_proc( hSCE, hCPE, n, synth[n], NULL, output_frame, 0 ); + ivas_post_proc( hSCE, hCPE, n, synth[n], NULL, output_frame, sba_dirac_stereo_flag ); } /* update OLA buffers - needed for switching to DFT stereo */ - stereo_td2dft_update( hCPE, n, output[n], synth[n], hb_synth[n], output_frame ); + if ( !sba_dirac_stereo_flag ) + { + stereo_td2dft_update( hCPE, n, output[n], synth[n], hb_synth[n], output_frame ); + } } else /* IVAS_CPE_DFT */ { @@ -751,7 +733,7 @@ ivas_error ivas_core_dec( output_debug_mode_info_dec( sts, n_channels, output_frame, pitch_buf ); #endif - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_dec/ivas_corecoder_dec_reconfig.c b/lib_dec/ivas_corecoder_dec_reconfig.c new file mode 100644 index 0000000000000000000000000000000000000000..d2cf408dce3bafcd1208a8aaa89c1e0692e1e2fb --- /dev/null +++ b/lib_dec/ivas_corecoder_dec_reconfig.c @@ -0,0 +1,576 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" +#include "ivas_cnst.h" +#include "ivas_prot.h" +#include "prot.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * ivas_corecoder_dec_reconfig() + * + * Allocate, initialize, and configure SCE/CPE/MCT handles in case of bitrate switching + *-------------------------------------------------------------------*/ + +ivas_error ivas_corecoder_dec_reconfig( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nSCE_old, /* i : number of SCEs in previous frame */ + int16_t nCPE_old, /* i : number of CPEs in previous frame */ + const int16_t nchan_transport_old, /* i : number of TCs in previous frame */ + const int16_t sba_dirac_stereo_flag_old, /* i : signal stereo rendering using DFT upmix in previous frame */ + const int32_t brate_SCE, /* i : bitrate to be set for the SCEs */ + const int32_t brate_CPE /* i : bitrate to be set for the CPEs */ +) +{ + int16_t n, sce_id, cpe_id, output_frame; + int16_t nSCE_existing, nCPE_existing; + int32_t ivas_total_brate; + MC_MODE last_mc_mode; + DECODER_CONFIG_HANDLE hDecoderConfig; + ivas_error error; + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + hDecoderConfig = st_ivas->hDecoderConfig; + ivas_total_brate = hDecoderConfig->ivas_total_brate; + output_frame = (int16_t) ( hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + error = IVAS_ERR_OK; + + if ( st_ivas->ivas_format == MC_FORMAT ) + { + last_mc_mode = ivas_mc_mode_select( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ), st_ivas->hDecoderConfig->last_ivas_total_brate ); /* NB: this assumes that LS config remains the same between frames */ + } + else + { + last_mc_mode = MC_MODE_NONE; + } + + /*-----------------------------------------------------------------* + * Allocate, initialize, and configure SCE/CPE/MCT handles + *-----------------------------------------------------------------*/ + + /* remove dummy CPE element for DFT stereo-like upmix */ +#ifdef SBA2MONO + if ( ( st_ivas->ivas_format == SBA_FORMAT && sba_dirac_stereo_flag_old && nchan_transport_old == 1 && ( !st_ivas->sba_dirac_stereo_flag || st_ivas->nchan_transport > 1 ) ) || + ( st_ivas->ivas_format == MC_FORMAT && last_mc_mode == MC_MODE_MCMASA && sba_dirac_stereo_flag_old && nchan_transport_old == 1 && ( !st_ivas->sba_dirac_stereo_flag || st_ivas->nchan_transport > 1 ) ) ) +#else + if ( ( st_ivas->ivas_format == SBA_FORMAT && sba_dirac_stereo_flag_old && !st_ivas->sba_dirac_stereo_flag ) || + ( st_ivas->ivas_format == MC_FORMAT && last_mc_mode == MC_MODE_MCMASA && sba_dirac_stereo_flag_old && !st_ivas->sba_dirac_stereo_flag ) ) +#endif + { + st_ivas->hCPE[0]->hCoreCoder[0] = NULL; + st_ivas->hCPE[0]->hCoreCoder[1] = NULL; + destroy_cpe_dec( st_ivas->hCPE[0] ); + st_ivas->hCPE[0] = NULL; + + if ( st_ivas->hSCE[0] != NULL ) + { + free( st_ivas->hSCE[0]->save_synth ); + st_ivas->hSCE[0]->save_synth = NULL; + + free( st_ivas->hSCE[0]->save_hb_synth ); + st_ivas->hSCE[0]->save_hb_synth = NULL; + } + } + + if ( st_ivas->nchan_transport == nchan_transport_old && st_ivas->nSCE == nSCE_old && st_ivas->nCPE == nCPE_old ) + { + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + st_ivas->hSCE[sce_id]->element_brate = brate_SCE; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + } + + for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + st_ivas->hCPE[cpe_id]->element_brate = brate_CPE; + + /* prepare bitstream buffers */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + } + } + + if ( st_ivas->nCPE > 1 ) + { + if ( ( error = mct_dec_reconfigure( st_ivas, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else + { + nSCE_existing = min( nSCE_old, st_ivas->nSCE ); + nCPE_existing = min( nCPE_old, st_ivas->nCPE ); + + /* destroy superfluous core coder elements */ + for ( sce_id = st_ivas->nSCE; sce_id < nSCE_old; sce_id++ ) + { + destroy_sce_dec( st_ivas->hSCE[sce_id] ); + st_ivas->hSCE[sce_id] = NULL; + } + + for ( cpe_id = st_ivas->nCPE; cpe_id < nCPE_old; cpe_id++ ) + { +#ifdef SBA2MONO + /* don't deallocate first CPE in case of mono/stereo output of 1 TC SBA, only deallocate core coder */ + if ( cpe_id == 0 && st_ivas->sba_dirac_stereo_flag && sba_dirac_stereo_flag_old ) + { + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + if ( st_ivas->hCPE[cpe_id]->hCoreCoder[n] != NULL ) + { + destroy_core_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); + + free( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); + st_ivas->hCPE[cpe_id]->hCoreCoder[n] = NULL; + } + } + continue; + } +#endif + destroy_cpe_dec( st_ivas->hCPE[cpe_id] ); + st_ivas->hCPE[cpe_id] = NULL; + } + + /* the CPE-internal settings depend from ivas_format and mc_mode, so clean-up when switching between mc_modes */ + if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode != last_mc_mode && ( st_ivas->mc_mode == MC_MODE_MCMASA || last_mc_mode == MC_MODE_MCMASA ) ) + { + for ( cpe_id = 0; cpe_id < nCPE_existing; cpe_id++ ) + { + destroy_cpe_dec( st_ivas->hCPE[cpe_id] ); + st_ivas->hCPE[cpe_id] = NULL; + } + nCPE_old = 0; + nCPE_existing = min( nCPE_old, st_ivas->nCPE ); + } + if ( st_ivas->nCPE <= 1 && st_ivas->hMCT != NULL ) + { + ivas_mct_dec_close( &st_ivas->hMCT ); + } + + /* special case, if we have MCT now and had a single CPE before, remove the MDCT Stereo handles from the first CPE*/ + if ( st_ivas->nCPE > 1 && nCPE_old == 1 ) + { + free( st_ivas->hCPE[0]->hStereoMdct ); + st_ivas->hCPE[0]->hStereoMdct = NULL; + } + + for ( sce_id = 0; sce_id < nSCE_existing; sce_id++ ) + { + st_ivas->hSCE[sce_id]->element_brate = brate_SCE; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + } + for ( ; sce_id < st_ivas->nSCE; sce_id++ ) + { + if ( ( error = create_sce_dec( st_ivas, sce_id, brate_SCE ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#ifdef SBA2MONO + if ( st_ivas->sba_dirac_stereo_flag && sba_dirac_stereo_flag_old && st_ivas->nchan_transport == 1 && nSCE_old == 0 ) + { + st_ivas->hCPE[0]->hCoreCoder[0] = st_ivas->hSCE[0]->hCoreCoder[0]; /* don't allocate unnecessary core coder, simply point to core coder of SCE element */ + st_ivas->hCPE[0]->hCoreCoder[1] = NULL; + } +#endif + + for ( cpe_id = 0; cpe_id < nCPE_existing; cpe_id++ ) + { + st_ivas->hCPE[cpe_id]->element_brate = brate_CPE; + + /* prepare bitstream buffers */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + } + } + for ( ; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + if ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->hOutSetup.separateChannelEnabled ) + { + st_ivas->element_mode_init = IVAS_CPE_MDCT; + } + if ( ( error = create_cpe_dec( st_ivas, cpe_id, brate_CPE ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->nCPE > 1 && nCPE_old <= 1 ) + { + if ( nCPE_old == 1 ) + { + /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handles for MCT */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[0]->element_brate / FRAMES_PER_SEC ); + st_ivas->hCPE[0]->hCoreCoder[n]->igf = 0; + } + } + + if ( ( error = create_mct_dec( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hMCT != NULL && st_ivas->nCPE > 1 ) + { + if ( ( error = mct_dec_reconfigure( st_ivas, st_ivas->nchan_transport != nchan_transport_old ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* special case, if we have a single CPE and had MCT before we need to init the MDCT stereo handles here */ + if ( st_ivas->nCPE == 1 && nCPE_old > 1 ) + { + if ( ( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); + } + + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->use_itd = 0; + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->reverse_dmx = 0; + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->smooth_ratio = 1.f; + set_s( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->prev_ms_mask[0], 0, MAX_SFB ); + set_s( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->prev_ms_mask[1], 0, MAX_SFB ); + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->lastCoh = 1.f; + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->mdct_stereo_mode[0] = SMDCT_DUAL_MONO; + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->mdct_stereo_mode[1] = SMDCT_DUAL_MONO; + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->IGFStereoMode[0] = -1; + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->IGFStereoMode[1] = -1; + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + /* reset mct_chan_mode */ + st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } + } + } + + /* create dummy CPE element for DFT stereo-like upmix */ + if ( ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_dirac_stereo_flag && !sba_dirac_stereo_flag_old ) || + ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->sba_dirac_stereo_flag && !sba_dirac_stereo_flag_old ) ) + { +#ifdef SBA2MONO + /* if at least one CPE is already available, only allocate DFT Stereo struct */ + if ( st_ivas->nCPE > 0 ) + { + if ( ( error = stereo_dft_dec_create( &( st_ivas->hCPE[0]->hStereoDft ), st_ivas->hCPE[0]->element_brate, st_ivas->hDecoderConfig->output_Fs, st_ivas->sba_dirac_stereo_flag, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) + { + return error; + } + } + /* otherwise create extra dummy CPE */ + else + { + if ( ( error = create_cpe_dec( st_ivas, 0, ivas_total_brate / ( st_ivas->nSCE + st_ivas->nCPE ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#else + if ( ( error = create_cpe_dec( st_ivas, 0, ivas_total_brate / ( st_ivas->nSCE + st_ivas->nCPE ) ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + + set_f( st_ivas->hCPE[0]->hStereoDft->buff_LBTCX_mem, 0, NS2SA( 16000, STEREO_DFT32MS_OVL_NS ) ); + + st_ivas->hCPE[0]->hCoreCoder[0] = st_ivas->hSCE[0]->hCoreCoder[0]; /* don't allocate unnecessary core coder, simply point to core coder of SCE element */ + st_ivas->hCPE[0]->hCoreCoder[1] = NULL; + + if ( st_ivas->hSCE[0]->save_synth == NULL ) + { + if ( ( st_ivas->hSCE[0]->save_synth = (float *) malloc( sizeof( float ) * output_frame ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) ); + } + set_zero( st_ivas->hSCE[0]->save_synth, output_frame ); + } + + if ( st_ivas->hSCE[0]->save_hb_synth == NULL ) + { + if ( ( st_ivas->hSCE[0]->save_hb_synth = (float *) malloc( sizeof( float ) * output_frame ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) ); + } + set_zero( st_ivas->hSCE[0]->save_hb_synth, output_frame ); + } + } + + /*-----------------------------------------------------------------* + * Set CNA/CNG flags + *-----------------------------------------------------------------*/ + +#ifdef FIX_386_CORECODER_RECONFIG + if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) + { + ivas_sba_set_cna_cng_flag( st_ivas ); + } +#else + /// VE: this could be merged with part of ivas_init_decoder() + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + if ( st_ivas->sba_mode == SBA_MODE_SPAR && st_ivas->nchan_transport == 1 ) + { + /* skip as done in init function */ + } + else if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 1; + st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 1; + } + else if ( st_ivas->nchan_transport == 2 ) + { + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[0]->hCoreCoder[n]->cna_dirac_flag = 0; + st_ivas->hCPE[0]->hCoreCoder[n]->cng_sba_flag = 1; + } + } + else + { + for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cna_dirac_flag = 0; + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_sba_flag = 0; + } + } + } + } +#endif + + /* special case, if the decoder goes from 1TC DTX to 2TC active frame (in case the bitstream started with an SBA SID frame), allocate DTX memories */ + if ( hDecoderConfig->last_ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE >= 1 ) + { + if ( ( error = initMdctStereoDtxData( st_ivas->hCPE[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return error; +} + + +/*-------------------------------------------------------------------* + * ivas_hp20_dec_reconfig() + * + * Allocate, initialize, and configure HP20 memory handles in case of bitrate switching + *-------------------------------------------------------------------*/ + +ivas_error ivas_hp20_dec_reconfig( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nchan_hp20_old /* i : number of HP20 filters in previous frame */ +) +{ + int16_t i, nchan_hp20; + float **old_mem_hp20_out; + ivas_error error; + + error = IVAS_ERR_OK; + + /*-----------------------------------------------------------------* + * HP20 memories + *-----------------------------------------------------------------*/ + + nchan_hp20 = getNumChanSynthesis( st_ivas ); + + if ( nchan_hp20 > nchan_hp20_old ) + { + /* save old mem_hp_20 pointer */ + old_mem_hp20_out = st_ivas->mem_hp20_out; + st_ivas->mem_hp20_out = NULL; + + if ( ( st_ivas->mem_hp20_out = (float **) malloc( nchan_hp20 * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); + } + + for ( i = 0; i < nchan_hp20_old; i++ ) + { + st_ivas->mem_hp20_out[i] = old_mem_hp20_out[i]; + old_mem_hp20_out[i] = NULL; + } + /* create additional hp20 memories */ + for ( ; i < nchan_hp20; i++ ) + { + if ( ( st_ivas->mem_hp20_out[i] = (float *) malloc( L_HP20_MEM * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); + } + + set_f( st_ivas->mem_hp20_out[i], 0.0f, L_HP20_MEM ); + } + + free( old_mem_hp20_out ); + old_mem_hp20_out = NULL; + } + else if ( nchan_hp20 < nchan_hp20_old ) + { + /* save old mem_hp_20 pointer */ + old_mem_hp20_out = st_ivas->mem_hp20_out; + st_ivas->mem_hp20_out = NULL; + + if ( ( st_ivas->mem_hp20_out = (float **) malloc( nchan_hp20 * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); + } + + for ( i = 0; i < nchan_hp20; i++ ) + { + st_ivas->mem_hp20_out[i] = old_mem_hp20_out[i]; + old_mem_hp20_out[i] = NULL; + } + /* remove superfluous hp20 memories */ + for ( ; i < nchan_hp20_old; i++ ) + { + free( old_mem_hp20_out[i] ); + old_mem_hp20_out[i] = NULL; + } + + free( old_mem_hp20_out ); + old_mem_hp20_out = NULL; + } + + return error; +} + + +/*-------------------------------------------------------------------* + * ivas_cldfb_dec_reconfig() + * + * Allocate, initialize, and configure CLDFB handles in case of bitrate switching + *-------------------------------------------------------------------*/ + +ivas_error ivas_cldfb_dec_reconfig( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nchan_transport_old, /* i : number of TCs in previous frame */ + int16_t numCldfbAnalyses_old, /* i : number of CLDFB analysis instances in previous frame */ + const int16_t numCldfbSyntheses_old /* i : number of CLDFB synthesis instances in previous frame */ +) +{ + int16_t i, numCldfbAnalyses, numCldfbSyntheses; + DECODER_CONFIG_HANDLE hDecoderConfig; + ivas_error error; + + hDecoderConfig = st_ivas->hDecoderConfig; + + ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses, &numCldfbSyntheses ); + + /* special case, if there was one transport channel in the previous frame and more than one in the current frame, + remove the second CLDFB here, it was for CNA/CNG */ + if ( st_ivas->ivas_format == SBA_FORMAT && nchan_transport_old == 1 && numCldfbAnalyses_old == 2 && st_ivas->nchan_transport > 1 ) + { + deleteCldfb( &( st_ivas->cldfbAnaDec[1] ) ); + numCldfbAnalyses_old--; + } + + /* resample CLDFB analysis instances */ + for ( i = 0; i < min( numCldfbAnalyses, numCldfbAnalyses_old ); i++ ) + { + if ( ( st_ivas->cldfbAnaDec[i]->no_channels * st_ivas->cldfbAnaDec[i]->no_col ) != ( hDecoderConfig->output_Fs / FRAMES_PER_SEC ) ) + { + resampleCldfb( st_ivas->cldfbAnaDec[i], hDecoderConfig->output_Fs ); + } + } + + /* Analysis*/ + if ( numCldfbAnalyses_old > numCldfbAnalyses ) + { + /* delete superfluous CLDFB synthesis instances */ + for ( i = numCldfbAnalyses; i < numCldfbAnalyses_old; i++ ) + { + deleteCldfb( &( st_ivas->cldfbAnaDec[i] ) ); + } + } + else if ( numCldfbAnalyses_old < numCldfbAnalyses ) + { + /* create additional CLDFB synthesis instances */ + for ( i = numCldfbAnalyses_old; i < numCldfbAnalyses; i++ ) + { + if ( ( error = openCldfb( &( st_ivas->cldfbAnaDec[i] ), CLDFB_ANALYSIS, hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + /* Synthesis */ + if ( numCldfbSyntheses_old > numCldfbSyntheses ) + { + /* delete superfluous CLDFB synthesis instances */ + for ( i = numCldfbSyntheses; i < numCldfbSyntheses_old; i++ ) + { + deleteCldfb( &( st_ivas->cldfbSynDec[i] ) ); + } + } + else if ( numCldfbSyntheses_old < numCldfbSyntheses ) + { + /* create additional CLDFB synthesis instances */ + for ( i = numCldfbSyntheses_old; i < numCldfbSyntheses; i++ ) + { + if ( ( error = openCldfb( &( st_ivas->cldfbSynDec[i] ), CLDFB_SYNTHESIS, hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + /* CLDFB Interpolation weights */ +#ifdef SBA2MONO + if ( st_ivas->sba_mode == SBA_MODE_SPAR && ( numCldfbAnalyses_old != numCldfbAnalyses || numCldfbSyntheses_old != numCldfbSyntheses || nchan_transport_old != st_ivas->nchan_transport ) && numCldfbAnalyses != 0 && numCldfbSyntheses != 0 ) +#else + if ( st_ivas->sba_mode == SBA_MODE_SPAR && ( numCldfbAnalyses_old != numCldfbAnalyses || numCldfbSyntheses_old != numCldfbSyntheses || nchan_transport_old != st_ivas->nchan_transport ) ) +#endif + { + ivas_spar_get_cldfb_gains( st_ivas->hSpar, st_ivas->cldfbAnaDec[0], st_ivas->cldfbSynDec[0], hDecoderConfig ); + } + + return IVAS_ERR_OK; +} diff --git a/lib_dec/ivas_cpe_dec.c b/lib_dec/ivas_cpe_dec.c index cf0d5b508d2e59a80cc90d7a122e87781312e5b9..5156aad08c16c209e9fab116858cf2b04d08e983 100644 --- a/lib_dec/ivas_cpe_dec.c +++ b/lib_dec/ivas_cpe_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include @@ -75,13 +75,12 @@ ivas_error ivas_cpe_dec( float res_buf[STEREO_DFT_N_8k]; CPE_DEC_HANDLE hCPE; Decoder_State **sts; - int16_t last_tdm_LRTD_flag; int32_t ivas_total_brate; ivas_error error; error = IVAS_ERR_OK; - wmops_sub_start( "ivas_cpe_dec" ); + push_wmops( "ivas_cpe_dec" ); ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; @@ -94,12 +93,6 @@ ivas_error ivas_cpe_dec( sts[0]->BER_detect |= st_ivas->BER_detect; sts[1]->BER_detect |= st_ivas->BER_detect; - last_tdm_LRTD_flag = 0; - if ( hCPE->hStereoTD != NULL ) - { - last_tdm_LRTD_flag = hCPE->hStereoTD->tdm_LRTD_flag; - } - /*------------------------------------------------------------------* * Read stereo technology info & audio bandwidth *-----------------------------------------------------------------*/ @@ -110,12 +103,11 @@ ivas_error ivas_cpe_dec( * dynamically allocate data structures depending on the actual stereo mode *----------------------------------------------------------------*/ - if ( ( error = stereo_memory_dec( ivas_total_brate, hCPE, nb_bits_metadata, st_ivas->hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) + if ( ( error = stereo_memory_dec( ivas_total_brate, hCPE, nb_bits_metadata, st_ivas->hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->mc_mode, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) { return error; } - /*------------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ @@ -168,14 +160,14 @@ ivas_error ivas_cpe_dec( if ( hCPE->element_mode != IVAS_CPE_MDCT && ( hCPE->element_brate != hCPE->last_element_brate || hCPE->last_element_mode != hCPE->element_mode || sts[0]->ini_frame == 0 || ( ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) ) ) { - if ( st_ivas->hQMetaData != NULL && ivas_total_brate > IVAS_SID_4k4 ) + if ( st_ivas->hQMetaData != NULL && ivas_total_brate > IVAS_SID_5k2 ) { stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); } else { - /* Note: This only works for stereo operation. If DTX would be applied for multiple CPEs a different bitrate signalling is needed */ - if ( ivas_total_brate <= IVAS_SID_4k4 ) + /* Note: This only works for stereo operation. If DTX would be applied for multiple CPEs a different bitrate signaling is needed */ + if ( ivas_total_brate <= IVAS_SID_5k2 ) { stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, ivas_total_brate, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); } @@ -186,7 +178,7 @@ ivas_error ivas_cpe_dec( } } - if ( hCPE->element_mode == IVAS_CPE_TD && last_tdm_LRTD_flag != hCPE->hStereoTD->tdm_LRTD_flag ) + if ( hCPE->element_mode == IVAS_CPE_TD ) { if ( hCPE->hStereoTD->tdm_LRTD_flag ) { @@ -211,7 +203,7 @@ ivas_error ivas_cpe_dec( /* Update DFT Stereo memories */ stereo_dft_dec_update( hCPE->hStereoDft, output_frame, 0 ); - if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_4k4 ) + if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_5k2 ) { if ( ivas_total_brate == FRAME_NO_DATA ) { @@ -228,13 +220,13 @@ ivas_error ivas_cpe_dec( nb_bits = (int16_t) ( ( hCPE->element_brate ) / FRAMES_PER_SEC - 0.8f * sts[0]->bits_frame_nominal ); sts[1]->bit_stream = sts[0]->bit_stream + ivas_total_brate / FRAMES_PER_SEC - 1 - nb_bits_metadata; - if ( ivas_total_brate == IVAS_SID_4k4 ) + if ( ivas_total_brate == IVAS_SID_5k2 ) { nb_bits -= SID_FORMAT_NBITS; sts[1]->bit_stream -= SID_FORMAT_NBITS; } - if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ivas_total_brate > IVAS_SID_4k4 ) + if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ivas_total_brate > IVAS_SID_5k2 ) { sts[0]->total_brate = hCPE->element_brate; /* Only mono downmix was transmitted in this case */ } @@ -274,7 +266,7 @@ ivas_error ivas_cpe_dec( /* this is just for initialization, the true values of "total_brate" and "bits_frame_channel" are set later */ for ( n = 0; n < n_channels; n++ ) { - if ( ivas_total_brate == IVAS_SID_4k4 || ivas_total_brate == IVAS_SID_5k ) + if ( ivas_total_brate == IVAS_SID_5k2 ) { sts[n]->total_brate = SID_2k40; @@ -291,7 +283,7 @@ ivas_error ivas_cpe_dec( if ( !st_ivas->hMCT ) { - if ( st_ivas->ivas_format == SBA_FORMAT && ivas_total_brate == IVAS_SID_5k ) + if ( st_ivas->ivas_format == SBA_FORMAT && ivas_total_brate == IVAS_SID_5k2 ) { for ( n = 0; n < n_channels; n++ ) { @@ -299,7 +291,6 @@ ivas_error ivas_cpe_dec( } } else - { /* subtract metadata bitbudget */ /* IVAS_fmToDo: TBC whether it is not better to distribute the metadata bits equally between 2 channels */ sts[0]->bits_frame_channel -= nb_bits_metadata; @@ -369,25 +360,15 @@ ivas_error ivas_cpe_dec( if ( hCPE->element_mode != IVAS_CPE_DFT || ( hCPE->nchan_out == 1 && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) ) { - if ( st_ivas->renderer_type == RENDERER_MC_PARAMMC && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) ) - { - if ( ( error = ivas_core_dec( st_ivas, NULL, hCPE, st_ivas->hMCT, n_channels, output, outputHB, NULL, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else + if ( ( error = ivas_core_dec( st_ivas, NULL, hCPE, st_ivas->hMCT, n_channels, output, outputHB, NULL, st_ivas->sba_dirac_stereo_flag ) ) != IVAS_ERR_OK ) { - if ( ( error = ivas_core_dec( NULL, NULL, hCPE, st_ivas->hMCT, n_channels, output, outputHB, NULL, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } } if ( st_ivas->hMCT ) { - wmops_sub_end(); + pop_wmops(); return error; } @@ -406,7 +387,6 @@ ivas_error ivas_cpe_dec( return error; } - /* DFT Stereo residual decoding */ if ( hCPE->hStereoDft->res_cod_band_max > 0 && !st_ivas->bfi ) { @@ -425,7 +405,11 @@ ivas_error ivas_cpe_dec( } else { - stereo_dft_dec( hCPE->hStereoDft, sts[0], DFT, hCPE->input_mem[1], hCPE->hStereoCng, 0 ); +#ifdef SBA2MONO + stereo_dft_dec( hCPE->hStereoDft, sts[0], DFT, hCPE->input_mem[1], hCPE->hStereoCng, 0, 0, 0, 0, 0, 0 ); +#else + stereo_dft_dec( hCPE->hStereoDft, sts[0], DFT, hCPE->input_mem[1], hCPE->hStereoCng, 0, 0, 0, 0, 0 ); +#endif } /* synthesis iFFT */ @@ -463,10 +447,6 @@ ivas_error ivas_cpe_dec( } } } - else if ( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->nchan_out == 1 && ( is_DTXrate( ivas_total_brate ) == 0 || ( is_DTXrate( ivas_total_brate ) == 1 && is_DTXrate( st_ivas->hDecoderConfig->last_ivas_total_brate ) == 0 ) ) ) - { - applyDmxMdctStereo( hCPE, output, output_frame ); - } /*----------------------------------------------------------------* * Update parameters for stereo CNA @@ -478,7 +458,15 @@ ivas_error ivas_cpe_dec( * Synthesis synchronization between CPE modes *----------------------------------------------------------------*/ - synchro_synthesis( ivas_total_brate, hCPE, output, output_frame, 0 ); + if ( !st_ivas->sba_dirac_stereo_flag ) + { + synchro_synthesis( ivas_total_brate, hCPE, output, output_frame, 0 ); + } + + if ( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->nchan_out == 1 && ( is_DTXrate( ivas_total_brate ) == 0 || ( is_DTXrate( ivas_total_brate ) == 1 && is_DTXrate( st_ivas->hDecoderConfig->last_ivas_total_brate ) == 0 ) ) ) + { + applyDmxMdctStereo( hCPE, output, output_frame ); + } #ifndef DEBUG_STEREO_DFT_OUTRESPRED /*----------------------------------------------------------------* @@ -515,7 +503,7 @@ ivas_error ivas_cpe_dec( #ifdef DEBUG_MODE_INFO { - float tmpF = ivas_total_brate / 1000.0f; + float tmpF = hCPE->element_brate / 1000.0f; n = 1; if ( st_ivas->ini_frame == 0 && frame > 0 ) @@ -527,17 +515,20 @@ ivas_error ivas_cpe_dec( for ( i = 0; i < n; i++ ) { dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "element_brate", 0, cpe_id, DEC ) ); - dbgwrite( &hCPE->element_mode, 2, 1, output_frame, fname( debug_dir, "element_mode", 0, cpe_id, DEC ) ); + dbgwrite( &hCPE->element_mode, sizeof( int16_t ), 1, output_frame, fname( debug_dir, "element_mode", 0, cpe_id, DEC ) ); for ( int16_t j = 0; j < CPE_CHANNELS; j++ ) { dbgwrite( output[j], sizeof( float ), output_frame, 1, fname( debug_dir, "output.cpe", j, cpe_id, DEC ) ); } + tmpF = 0; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.sce", 0, cpe_id, DEC ) ); + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.mct", 0, cpe_id, DEC ) ); } } #endif - wmops_sub_end(); + pop_wmops(); return error; } @@ -566,7 +557,7 @@ ivas_error create_cpe_dec( * Allocate CPE handle *-----------------------------------------------------------------*/ - if ( ( hCPE = (CPE_DEC_HANDLE) count_malloc( sizeof( CPE_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE = (CPE_DEC_HANDLE) malloc( sizeof( CPE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CPE\n" ) ); } @@ -590,7 +581,6 @@ ivas_error create_cpe_dec( hCPE->hStereoMdct = NULL; hCPE->hStereoTCA = NULL; hCPE->hStereoICBWE = NULL; - hCPE->hStereoCng = NULL; hCPE->stereo_switching_counter = 10; @@ -598,7 +588,7 @@ ivas_error create_cpe_dec( hCPE->lt_es_em = 0.0f; /* Note: nchan_out is considered to be related to the structure. This is nchan_out for CPE and for MASA_format is always 2. */ - if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) + if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MC_FORMAT ) { hCPE->nchan_out = CPE_CHANNELS; } @@ -607,7 +597,7 @@ ivas_error create_cpe_dec( hCPE->nchan_out = min( CPE_CHANNELS, st_ivas->hDecoderConfig->nchan_out ); } - if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_4k4 ) + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_5k2 ) { hCPE->nchan_out = 1; } @@ -627,13 +617,13 @@ ivas_error create_cpe_dec( if ( st_ivas->ivas_format == STEREO_FORMAT || st_ivas->ivas_format == MASA_FORMAT || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) || st_ivas->sba_dirac_stereo_flag ) { - if ( ( hCPE->input_mem[i] = (float *) count_malloc( sizeof( float ) * NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) + if ( ( hCPE->input_mem[i] = (float *) malloc( sizeof( float ) * NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } set_zero( hCPE->input_mem[i], NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ); - if ( ( hCPE->input_mem_LB[i] = (float *) count_malloc( sizeof( float ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) + if ( ( hCPE->input_mem_LB[i] = (float *) malloc( sizeof( float ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } @@ -641,14 +631,14 @@ ivas_error create_cpe_dec( if ( i == 0 ) { - if ( ( hCPE->input_mem_BPF[0] = (float *) count_malloc( sizeof( float ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) + if ( ( hCPE->input_mem_BPF[0] = (float *) malloc( sizeof( float ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } set_zero( hCPE->input_mem_BPF[0], STEREO_DFT32MS_OVL_16k ); } - if ( ( hCPE->output_mem[i] = (float *) count_malloc( sizeof( float ) * NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) + if ( ( hCPE->output_mem[i] = (float *) malloc( sizeof( float ) * NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } @@ -656,7 +646,7 @@ ivas_error create_cpe_dec( if ( i < hCPE->nchan_out ) { - if ( ( hCPE->prev_synth_chs[i] = (float *) count_malloc( sizeof( float ) * NS2SA( output_Fs, FRAME_SIZE_NS ) ) ) == NULL ) + if ( ( hCPE->prev_synth_chs[i] = (float *) malloc( sizeof( float ) * NS2SA( output_Fs, FRAME_SIZE_NS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } @@ -686,13 +676,13 @@ ivas_error create_cpe_dec( for ( n = 0; n < CPE_CHANNELS; n++ ) { - if ( st_ivas->sba_dirac_stereo_flag ) + if ( st_ivas->sba_dirac_stereo_flag && st_ivas->nchan_transport == 1 ) { /* for SBA DirAC stereo output CPE element is only used for upmix, core coder is found in SCE element used for core decoding */ break; } - if ( ( st = (DEC_CORE_HANDLE) count_malloc( sizeof( Decoder_State ) ) ) == NULL ) + if ( ( st = (DEC_CORE_HANDLE) malloc( sizeof( Decoder_State ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); } @@ -701,16 +691,14 @@ ivas_error create_cpe_dec( st->total_brate = hCPE->element_brate / ( CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT && ( n + cpe_id * CPE_CHANNELS ) == LFE_CHANNEL ) { st->mct_chan_mode = MCT_CHAN_MODE_LFE; } +#endif -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( ( error = init_decoder( st, n, st_ivas->mc_mode ) ) != IVAS_ERR_OK ) -#else - if ( ( error = init_decoder( st, n ) ) != IVAS_ERR_OK ) -#endif { return error; } @@ -722,9 +710,9 @@ ivas_error create_cpe_dec( * DFT stereo initialization *-----------------------------------------------------------------*/ - if ( hCPE->element_mode == IVAS_CPE_DFT || st_ivas->sba_dirac_stereo_flag ) + if ( hCPE->element_mode == IVAS_CPE_DFT || ( st_ivas->sba_dirac_stereo_flag && hCPE->cpe_id == 0 ) ) { - if ( ( error = stereo_dft_dec_create( &( hCPE->hStereoDft ), hCPE->element_brate, output_Fs, st_ivas->sba_dirac_stereo_flag ) ) != IVAS_ERR_OK ) + if ( ( error = stereo_dft_dec_create( &( hCPE->hStereoDft ), hCPE->element_brate, output_Fs, st_ivas->sba_dirac_stereo_flag, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) { return error; } @@ -736,7 +724,7 @@ ivas_error create_cpe_dec( if ( hCPE->element_mode != IVAS_CPE_MDCT && hCPE->nchan_out == 1 ) { - if ( ( hCPE->hStereoDftDmx = (STEREO_DFT_DMX_DATA_HANDLE) count_malloc( sizeof( STEREO_DFT_DMX_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoDftDmx = (STEREO_DFT_DMX_DATA_HANDLE) malloc( sizeof( STEREO_DFT_DMX_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo DFT mono output\n" ) ); } @@ -750,7 +738,7 @@ ivas_error create_cpe_dec( if ( ( hCPE->element_mode != IVAS_CPE_MDCT || ( st_ivas->ivas_format == STEREO_FORMAT && hCPE->element_brate <= MAX_MDCT_ITD_BRATE ) ) && hCPE->nchan_out != 1 ) { - if ( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) count_malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); } @@ -764,7 +752,7 @@ ivas_error create_cpe_dec( if ( hCPE->element_mode != IVAS_CPE_MDCT && !( hCPE->element_mode == IVAS_CPE_DFT && hCPE->nchan_out == 1 ) ) { - if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) count_malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE\n" ) ); } @@ -778,7 +766,7 @@ ivas_error create_cpe_dec( if ( hCPE->element_mode == IVAS_CPE_TD ) { - if ( ( hCPE->hStereoTD = (STEREO_TD_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_TD_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTD = (STEREO_TD_DEC_DATA_HANDLE) malloc( sizeof( STEREO_TD_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) ); } @@ -792,10 +780,11 @@ ivas_error create_cpe_dec( if ( hCPE->element_mode == IVAS_CPE_MDCT && st_ivas->nCPE == 1 ) { - if ( ( hCPE->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo MDCT\n" ) ); } + if ( st_ivas->ivas_format == STEREO_FORMAT && hCPE->element_brate <= MAX_MDCT_ITD_BRATE ) { hCPE->hStereoMdct->use_itd = 1; @@ -804,11 +793,16 @@ ivas_error create_cpe_dec( { hCPE->hStereoMdct->use_itd = 0; } + hCPE->hStereoMdct->reverse_dmx = 0; hCPE->hStereoMdct->smooth_ratio = 1.f; set_s( hCPE->hStereoMdct->prev_ms_mask[0], 0, MAX_SFB ); set_s( hCPE->hStereoMdct->prev_ms_mask[1], 0, MAX_SFB ); hCPE->hStereoMdct->lastCoh = 1.f; + hCPE->hStereoMdct->mdct_stereo_mode[0] = SMDCT_DUAL_MONO; + hCPE->hStereoMdct->mdct_stereo_mode[1] = SMDCT_DUAL_MONO; + hCPE->hStereoMdct->IGFStereoMode[0] = -1; + hCPE->hStereoMdct->IGFStereoMode[1] = -1; } /*-----------------------------------------------------------------* @@ -817,7 +811,7 @@ ivas_error create_cpe_dec( if ( hCPE->element_mode == IVAS_CPE_TD || hCPE->element_mode == IVAS_CPE_DFT ) { - if ( ( hCPE->hStereoCng = (STEREO_CNG_DEC_HANDLE) count_malloc( sizeof( STEREO_CNG_DEC ) ) ) == NULL ) + if ( ( hCPE->hStereoCng = (STEREO_CNG_DEC_HANDLE) malloc( sizeof( STEREO_CNG_DEC ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo CNG\n" ) ); } @@ -843,6 +837,16 @@ void destroy_cpe_dec( int16_t n; Decoder_State *st; + /* make sure we deallocate a potential distinct hTcxCfg for a MCT LFE channel (can only happen in rs) */ /*TODO Check this again with LFE clean up!*/ + if ( hCPE->hCoreCoder[1] != NULL +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && hCPE->hCoreCoder[1]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + && hCPE->hCoreCoder[1]->hTcxCfg != hCPE->hCoreCoder[0]->hTcxCfg ) + { + hCPE->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + } + for ( n = 0; n < CPE_CHANNELS; n++ ) { st = hCPE->hCoreCoder[n]; @@ -851,7 +855,7 @@ void destroy_cpe_dec( { destroy_core_dec( st ); - count_free( st ); + free( st ); st = NULL; } } @@ -864,31 +868,31 @@ void destroy_cpe_dec( if ( hCPE->hStereoDftDmx != NULL ) { - count_free( hCPE->hStereoDftDmx ); + free( hCPE->hStereoDftDmx ); hCPE->hStereoDftDmx = NULL; } if ( hCPE->hStereoTD != NULL ) { - count_free( hCPE->hStereoTD ); + free( hCPE->hStereoTD ); hCPE->hStereoTD = NULL; } if ( hCPE->hStereoMdct != NULL ) { - count_free( hCPE->hStereoMdct ); + free( hCPE->hStereoMdct ); hCPE->hStereoMdct = NULL; } if ( hCPE->hStereoTCA != NULL ) { - count_free( hCPE->hStereoTCA ); + free( hCPE->hStereoTCA ); hCPE->hStereoTCA = NULL; } if ( hCPE->hStereoICBWE != NULL ) { - count_free( hCPE->hStereoICBWE ); + free( hCPE->hStereoICBWE ); hCPE->hStereoICBWE = NULL; } @@ -896,29 +900,29 @@ void destroy_cpe_dec( { for ( n = 0; n < CPE_CHANNELS; n++ ) { - count_free( hCPE->input_mem_LB[n] ); + free( hCPE->input_mem_LB[n] ); hCPE->input_mem_LB[n] = NULL; - count_free( hCPE->input_mem[n] ); + free( hCPE->input_mem[n] ); hCPE->input_mem[n] = NULL; - count_free( hCPE->output_mem[n] ); + free( hCPE->output_mem[n] ); hCPE->output_mem[n] = NULL; if ( hCPE->prev_synth_chs[n] != NULL ) { - count_free( hCPE->prev_synth_chs[n] ); + free( hCPE->prev_synth_chs[n] ); hCPE->prev_synth_chs[n] = NULL; } } - count_free( hCPE->input_mem_BPF[0] ); + free( hCPE->input_mem_BPF[0] ); hCPE->input_mem_BPF[0] = NULL; } if ( hCPE->hStereoCng != NULL ) { - count_free( hCPE->hStereoCng ); + free( hCPE->hStereoCng ); hCPE->hStereoCng = NULL; } - count_free( hCPE ); + free( hCPE ); return; } @@ -941,7 +945,7 @@ static void read_stereo_mode_and_bwidth( * BFI or NO_DATA frame: Use stereo parameters from last (active) frame *-----------------------------------------------------------------*/ - if ( st_ivas->bfi || st_ivas->hDecoderConfig->ivas_total_brate < IVAS_SID_4k4 ) + if ( st_ivas->bfi || st_ivas->hDecoderConfig->ivas_total_brate < IVAS_SID_5k2 ) { hCPE->element_mode = hCPE->last_element_mode; @@ -951,7 +955,7 @@ static void read_stereo_mode_and_bwidth( * SID frame: get element mode from SID side info *-----------------------------------------------------------------*/ - else if ( st_ivas->hDecoderConfig->ivas_total_brate == IVAS_SID_4k4 || st_ivas->hDecoderConfig->ivas_total_brate == IVAS_SID_5k ) + else if ( st_ivas->hDecoderConfig->ivas_total_brate == IVAS_SID_5k2 ) { switch ( st_ivas->sid_format ) { @@ -969,7 +973,7 @@ static void read_stereo_mode_and_bwidth( hCPE->element_mode = IVAS_CPE_MDCT; break; case SID_SBA_1TC: - assert( "Forbidden value for sid format in CPE (SBA 1TC), should have already been adressed earlier" ); + assert( !"Forbidden value for SID format in CPE (SBA 1TC), should have already been adressed earlier" ); break; case SID_MASA_1TC: hCPE->element_mode = IVAS_SCE; diff --git a/lib_dec/ivas_crend.c b/lib_dec/ivas_crend.c deleted file mode 100644 index 772101ecff194ebb205ca9aca58fad6a23ca8d12..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_crend.c +++ /dev/null @@ -1,1138 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include "prot.h" -#include "ivas_prot.h" -#include "ivas_cnst.h" -#include "ivas_rom_dec.h" -#include "ivas_stat_dec.h" -#include -#include "ivas_rom_binaural_crend_head.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "wmops.h" - - -/*------------------------------------------------------------------------- - * ivas_hrtf_init() - * - * Initialize hHrtf handle - *------------------------------------------------------------------------*/ - -static ivas_error ivas_hrtf_init( - HRTFS_DATA *hHrtf /* i/o: HRTF handle */ -) -{ - int16_t i, j; - - if ( hHrtf == NULL ) - { - return IVAS_ERR_WRONG_PARAMS; - } - - hHrtf->latency_s = 0; - hHrtf->max_num_ir = 0; - hHrtf->max_num_iterations = 0; - hHrtf->gain_lfe = 0; - hHrtf->index_frequency_max_diffuse = 0; - - for ( i = 0; i < IVAS_MAX_NUM_CH; i++ ) - { - hHrtf->inv_diffuse_weight[i] = 0; - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = 0; - hHrtf->pIndex_frequency_max[i][j] = NULL; - hHrtf->pOut_to_bin_re[i][j] = NULL; - hHrtf->pOut_to_bin_im[i][j] = NULL; - } - } - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = 0; - hHrtf->pIndex_frequency_max_diffuse[j] = NULL; - hHrtf->pOut_to_bin_diffuse_re[j] = NULL; - hHrtf->pOut_to_bin_diffuse_im[j] = NULL; - } - - return IVAS_ERR_OK; -} - -/*------------------------------------------------------------------------- - * ivas_hrtf_open() - * - * Open hHrtf handle - *------------------------------------------------------------------------*/ - -static ivas_error ivas_hrtf_open( - HRTFS_HANDLE *hHrtf /* o : HRTF handle */ -) -{ - HRTFS_HANDLE pState; - - if ( *hHrtf == NULL ) - { - if ( ( pState = (HRTFS_HANDLE) count_malloc( sizeof( HRTFS_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "Can not allocate memory for SPAR decoder\n" ); - } - - ivas_hrtf_init( pState ); - - *hHrtf = pState; - } - else - { - return IVAS_ERR_INTERNAL; - } - - return ( IVAS_ERR_OK ); -} - - -/*------------------------------------------------------------------------- - * ivas_hrtf_close() - * - * Close hHrtf handle - *------------------------------------------------------------------------*/ - -static ivas_error ivas_hrtf_close( - HRTFS_HANDLE *hHrtf /* i/o: HRTF handle */ -) -{ - if ( *hHrtf == NULL || hHrtf == NULL ) - { - return IVAS_ERR_WRONG_PARAMS; - } - - count_free( *hHrtf ); - *hHrtf = NULL; - - return IVAS_ERR_OK; -} - - -/*------------------------------------------------------------------------- - * ivas_crend_init_from_rom() - * - * Allocate and initialize crend renderer handle - *------------------------------------------------------------------------*/ - -ivas_error ivas_crend_init_from_rom( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -) -{ - int16_t i, j, tmp; - int32_t output_Fs; - AUDIO_CONFIG intern_config; - HRTFS_HANDLE hHrtf; - - hHrtf = st_ivas->hHrtf; - output_Fs = st_ivas->hDecoderConfig->output_Fs; - - intern_config = st_ivas->intern_config; - - if ( intern_config == AUDIO_CONFIG_BINAURAL || intern_config == AUDIO_CONFIG_BINAURAL_ROOM ) - { - return IVAS_ERR_INTERNAL_FATAL; - } - - if ( hHrtf == NULL ) - { - if ( ivas_hrtf_open( &hHrtf ) != IVAS_ERR_OK ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for HRTF handle" ); - } - } - - hHrtf->max_num_ir = audioCfg2channels( intern_config ); - - if ( hHrtf->max_num_ir <= 0 ) - { - return IVAS_ERR_INTERNAL_FATAL; - } - - /* Do all error checks up front so that the nested if later is easier */ - if ( st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV && st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV_ROOM ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Encountered unsupported renderer type" ); - } - - if ( intern_config != AUDIO_CONFIG_5_1 && intern_config != AUDIO_CONFIG_5_1_2 && intern_config != AUDIO_CONFIG_5_1_4 && - intern_config != AUDIO_CONFIG_7_1 && intern_config != AUDIO_CONFIG_7_1_4 && - intern_config != AUDIO_CONFIG_FOA && intern_config != AUDIO_CONFIG_HOA2 && intern_config != AUDIO_CONFIG_HOA3 ) - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Encountered unsupported transport config in Crend" ); - } - - if ( ( ( st_ivas->hRenderConfig != NULL ) && !st_ivas->hRenderConfig->roomAcoustics.use_brir ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV ) ) - { - if ( intern_config == AUDIO_CONFIG_5_1 || intern_config == AUDIO_CONFIG_5_1_2 || intern_config == AUDIO_CONFIG_5_1_4 || - intern_config == AUDIO_CONFIG_7_1 || intern_config == AUDIO_CONFIG_7_1_4 ) - { - hHrtf->max_num_ir -= 1; /* subtract LFE */ - hHrtf->gain_lfe = GAIN_LFE; - - if ( output_Fs == 48000 ) - { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_48kHz; - hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_48kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_48kHz; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[j]; - } - } - else if ( output_Fs == 32000 ) - { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_32kHz; - hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_32kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_32kHz; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[j]; - } - } - else if ( output_Fs == 16000 ) - { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_16kHz; - hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_16kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_16kHz; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[j]; - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); - } - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - if ( intern_config == AUDIO_CONFIG_5_1 ) - { - tmp = channelIndex_CICP6[i]; - } - else if ( intern_config == AUDIO_CONFIG_7_1 ) - { - tmp = channelIndex_CICP12[i]; - } - else if ( intern_config == AUDIO_CONFIG_5_1_2 ) - { - tmp = channelIndex_CICP14[i]; - } - else if ( intern_config == AUDIO_CONFIG_5_1_4 ) - { - tmp = channelIndex_CICP16[i]; - } - else if ( intern_config == AUDIO_CONFIG_7_1_4 ) - { - tmp = channelIndex_CICP19[i]; - } - else - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); - } - - if ( output_Fs == 48000 ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_48kHz[tmp]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_48kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_48kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_48kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_48kHz[tmp][j]; - } - } - else if ( output_Fs == 32000 ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_32kHz[tmp]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_32kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_32kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_32kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_32kHz[tmp][j]; - } - } - else if ( output_Fs == 16000 ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_16kHz[tmp]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_16kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_16kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_16kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_16kHz[tmp][j]; - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); - } - } - } - else if ( intern_config == AUDIO_CONFIG_FOA || intern_config == AUDIO_CONFIG_HOA2 || intern_config == AUDIO_CONFIG_HOA3 ) - { - if ( output_Fs == 48000 ) - { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_48kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_48kHz[i]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_48kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_48kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_48kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_48kHz[i][j]; - } - } - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[j]; - } - } - else if ( output_Fs == 32000 ) - { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_32kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_32kHz[i]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_32kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_32kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_32kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_32kHz[i][j]; - } - } - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[j]; - } - } - else if ( output_Fs == 16000 ) - { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_16kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_16kHz[i]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_16kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_16kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_16kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_16kHz[i][j]; - } - } - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[j]; - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); - } - } - } - else if ( ( ( st_ivas->hRenderConfig != NULL ) && st_ivas->hRenderConfig->roomAcoustics.use_brir ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - if ( intern_config == AUDIO_CONFIG_5_1 || intern_config == AUDIO_CONFIG_5_1_2 || intern_config == AUDIO_CONFIG_5_1_4 || - intern_config == AUDIO_CONFIG_7_1 || intern_config == AUDIO_CONFIG_7_1_4 ) - { - hHrtf->max_num_ir -= 1; /* subtract LFE */ - hHrtf->gain_lfe = GAIN_LFE; - - if ( output_Fs == 48000 ) - { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_48kHz; - hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_48kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_48kHz; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[j]; - } - } - else if ( output_Fs == 32000 ) - { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_32kHz; - hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_32kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_32kHz; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[j]; - } - } - else if ( output_Fs == 16000 ) - { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_16kHz; - hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_16kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_16kHz; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_16kHz[j]; - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); - } - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - if ( intern_config == AUDIO_CONFIG_5_1 ) - { - tmp = channelIndex_CICP6[i]; - } - else if ( intern_config == AUDIO_CONFIG_7_1 ) - { - tmp = channelIndex_CICP12[i]; - } - else if ( intern_config == AUDIO_CONFIG_5_1_2 ) - { - tmp = channelIndex_CICP14[i]; - } - else if ( intern_config == AUDIO_CONFIG_5_1_4 ) - { - tmp = channelIndex_CICP16[i]; - } - else if ( intern_config == AUDIO_CONFIG_7_1_4 ) - { - tmp = channelIndex_CICP19[i]; - } - else - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); - } - - if ( output_Fs == 48000 ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_48kHz[tmp]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_48kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_48kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_48kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_48kHz[tmp][j]; - } - } - else if ( output_Fs == 32000 ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_32kHz[tmp]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_32kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_32kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_32kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_32kHz[tmp][j]; - } - } - else if ( output_Fs == 16000 ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_16kHz[tmp]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_16kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_16kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_16kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_16kHz[tmp][j]; - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); - } - } - } - else if ( intern_config == AUDIO_CONFIG_FOA || intern_config == AUDIO_CONFIG_HOA2 || intern_config == AUDIO_CONFIG_HOA3 ) - { - if ( output_Fs == 48000 ) - { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_48kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_48kHz[i]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_48kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_48kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_48kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_48kHz[i][j]; - } - } - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[j]; - } - } - else if ( output_Fs == 32000 ) - { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_32kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_32kHz[i]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_32kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_32kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_32kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_32kHz[i][j]; - } - } - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[j]; - } - } - else if ( output_Fs == 16000 ) - { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_16kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_16kHz[i]; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_16kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_16kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_16kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_16kHz[i][j]; - } - } - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[j]; - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported intern_config type in Crend" ); - } - } - else - { - return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported renderer type in Crend" ); - } - - st_ivas->hHrtf = hHrtf; - - return IVAS_ERR_OK; -} - - -/*------------------------------------------------------------------------- - * ivas_crend_open() - * - * Allocate and initialize Crend renderer handle - *------------------------------------------------------------------------*/ - -ivas_error ivas_crend_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -) -{ - int16_t i, subframe_length; - int32_t max_total_ir_len, k; - HRTFS_HANDLE hHrtf; - CREND_HANDLE hCrend; - ivas_error error; - - error = IVAS_ERR_OK; - subframe_length = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES; - - if ( ( st_ivas->hHrtf == NULL ) && ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - if ( ( error = ivas_crend_init_from_rom( st_ivas ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - if ( ( hCrend = (CREND_HANDLE) count_malloc( sizeof( CREND_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for renderer handle" ); - } - - hCrend->lfe_delay_line = NULL; - - for ( i = 0; i < IVAS_MAX_NUM_CH; i++ ) - { - hCrend->freq_buffer_re[i] = NULL; - hCrend->freq_buffer_im[i] = NULL; - } - - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - hCrend->prev_out_buffer[i] = NULL; - } - - hCrend->freq_buffer_re_diffuse = NULL; - hCrend->freq_buffer_im_diffuse = NULL; - hCrend->hReverb = NULL; - hCrend->delay_line_rw_index = 0; - hCrend->diffuse_delay_line_rw_index = 0; - hCrend->hTrack = NULL; - hCrend->m_fYaw = 0; - hCrend->m_fPitch = 0; - hCrend->m_fRoll = 0; - - hHrtf = st_ivas->hHrtf; - - if ( ( hHrtf != NULL ) && ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - max_total_ir_len = hHrtf->max_num_iterations * subframe_length; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) - { - if ( ( hCrend->freq_buffer_re[i] = (float *) count_malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - for ( k = 0; k < max_total_ir_len; k++ ) - { - hCrend->freq_buffer_re[i][k] = 0; - } - - if ( ( hCrend->freq_buffer_im[i] = (float *) count_malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - for ( k = 0; k < max_total_ir_len; k++ ) - { - hCrend->freq_buffer_im[i][k] = 0; - } - } - - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - if ( ( hCrend->prev_out_buffer[i] = (float *) count_malloc( sizeof( float ) * subframe_length ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - for ( k = 0; k < subframe_length; k++ ) - { - hCrend->prev_out_buffer[i][k] = 0; - } - } - - max_total_ir_len = hHrtf->num_iterations_diffuse[0] * subframe_length; - - if ( max_total_ir_len > 0 ) - { - if ( ( hCrend->freq_buffer_re_diffuse = (float *) count_malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - for ( k = 0; k < max_total_ir_len; k++ ) - { - hCrend->freq_buffer_re_diffuse[k] = 0; - } - - if ( ( hCrend->freq_buffer_im_diffuse = (float *) count_malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - for ( k = 0; k < max_total_ir_len; k++ ) - { - hCrend->freq_buffer_im_diffuse[k] = 0; - } - } - else - { - hCrend->freq_buffer_re_diffuse = NULL; - hCrend->freq_buffer_im_diffuse = NULL; - } - - max_total_ir_len = (int16_t) ( hHrtf->latency_s * st_ivas->hDecoderConfig->output_Fs + 0.5f ) + subframe_length; - if ( max_total_ir_len > 0 ) - { - if ( ( hCrend->lfe_delay_line = (float *) count_malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - for ( k = 0; k < max_total_ir_len; k++ ) - { - hCrend->lfe_delay_line[k] = 0; - } - } - else - { - hCrend->lfe_delay_line = NULL; - } - - if ( st_ivas->hDecoderConfig->Opt_Headrotation ) - { - if ( ( hCrend->hTrack = (ivas_orient_trk_state_t *) count_malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" ); - } - - ivas_orient_trk_Init( hCrend->hTrack ); - } - else - { - hCrend->hTrack = NULL; - } - - if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT && st_ivas->hDecoderConfig->Opt_Headrotation ) - { - if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - if ( ( ( st_ivas->hRenderConfig != NULL ) && st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) ) - { - if ( ( error = ivas_reverb_open( &( hCrend->hReverb ), hHrtf, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - hCrend->hReverb = NULL; - } - - st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtf->latency_s * 1000000000.f ); - } - - - st_ivas->hCrend = hCrend; - - return error; -} - - -/*------------------------------------------------------------------------- - * ivas_crend_close() - * - * Deallocate Crend renderer handle - *------------------------------------------------------------------------*/ - -ivas_error ivas_crend_close( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -) -{ - int16_t i; - - if ( st_ivas->hHrtf != NULL ) - { - ivas_hrtf_close( &st_ivas->hHrtf ); - } - - if ( st_ivas->hCrend != NULL ) - { - if ( st_ivas->renderer_type != RENDERER_BINAURAL_OBJECTS_TD ) - { - for ( i = 0; i < IVAS_MAX_NUM_CH; i++ ) - { - if ( st_ivas->hCrend->freq_buffer_re[i] != NULL ) - { - count_free( st_ivas->hCrend->freq_buffer_re[i] ); - st_ivas->hCrend->freq_buffer_re[i] = NULL; - } - if ( st_ivas->hCrend->freq_buffer_im[i] != NULL ) - { - count_free( st_ivas->hCrend->freq_buffer_im[i] ); - st_ivas->hCrend->freq_buffer_im[i] = NULL; - } - } - - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - if ( st_ivas->hCrend->prev_out_buffer[i] != NULL ) - { - count_free( st_ivas->hCrend->prev_out_buffer[i] ); - st_ivas->hCrend->prev_out_buffer[i] = NULL; - } - } - - if ( st_ivas->hCrend->lfe_delay_line != NULL ) - { - count_free( st_ivas->hCrend->lfe_delay_line ); - st_ivas->hCrend->lfe_delay_line = NULL; - } - - if ( st_ivas->hCrend->freq_buffer_re_diffuse != NULL ) - { - count_free( st_ivas->hCrend->freq_buffer_re_diffuse ); - st_ivas->hCrend->freq_buffer_re_diffuse = NULL; - } - - if ( st_ivas->hCrend->freq_buffer_im_diffuse != NULL ) - { - count_free( st_ivas->hCrend->freq_buffer_im_diffuse ); - st_ivas->hCrend->freq_buffer_im_diffuse = NULL; - } - - if ( st_ivas->hCrend->hTrack != NULL ) - { - count_free( st_ivas->hCrend->hTrack ); - st_ivas->hCrend->hTrack = NULL; - } - } - ivas_reverb_close( &st_ivas->hCrend->hReverb ); - - count_free( st_ivas->hCrend ); - st_ivas->hCrend = NULL; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_crend_convolver() - * - * Convolver block - *-----------------------------------------------------------------------------------------*/ - -static ivas_error ivas_crend_convolver( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float pcm_in[][L_FRAME48k], - float pcm_out[][L_FRAME48k], - const int16_t i_ts ) -{ - float *pIn; - float *pFreq_buf_re; - float *pFreq_buf_im; - float *pFreq_filt_re; - float *pFreq_filt_im; - int16_t i, j, m, nchan_out, subframe_length, nchan_intern, idx_in; - float pOut[L_FRAME48k * 2]; - float tmp_out_re[L_FRAME48k]; - float tmp_out_im[L_FRAME48k]; - int32_t offset, offset_in, offset_diffuse; - int32_t output_Fs, k; - AUDIO_CONFIG intern_config; - - intern_config = st_ivas->intern_config; - nchan_intern = audioCfg2channels( intern_config ); - nchan_out = st_ivas->hDecoderConfig->nchan_out; - output_Fs = st_ivas->hDecoderConfig->output_Fs; - subframe_length = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES; - - offset = st_ivas->hCrend->delay_line_rw_index * subframe_length; /* subframe_length * ( st_ivas->hHrtf->max_num_iterations - 1 ); */ - offset_diffuse = st_ivas->hCrend->diffuse_delay_line_rw_index * subframe_length; /* subframe_length *( st_ivas->hHrtf->num_iterations_diffuse[0] - 1 ); */ - - if ( st_ivas->hHrtf->num_iterations_diffuse[0] > 0 ) - { - set_zero( &st_ivas->hCrend->freq_buffer_re_diffuse[offset_diffuse], subframe_length ); - set_zero( &st_ivas->hCrend->freq_buffer_im_diffuse[offset_diffuse], subframe_length ); - } - - i = 0; - for ( idx_in = 0; idx_in < nchan_intern; idx_in++ ) - { - pIn = &pcm_in[idx_in][i_ts * subframe_length]; - if ( st_ivas->hIntSetup.index_lfe[0] != idx_in ) - { - if ( st_ivas->hHrtf->num_iterations_diffuse[0] > 0 ) - { - pFreq_buf_re = &st_ivas->hCrend->freq_buffer_re_diffuse[offset_diffuse]; - pFreq_buf_im = &st_ivas->hCrend->freq_buffer_im_diffuse[offset_diffuse]; - pFreq_filt_re = &st_ivas->hCrend->freq_buffer_re[i][offset]; - pFreq_filt_im = &st_ivas->hCrend->freq_buffer_im[i][offset]; - - for ( k = 0; k < st_ivas->hHrtf->index_frequency_max_diffuse; k++ ) - { - pFreq_buf_re[k] += pFreq_filt_re[k] * st_ivas->hHrtf->inv_diffuse_weight[i]; - pFreq_buf_im[k] += pFreq_filt_im[k] * st_ivas->hHrtf->inv_diffuse_weight[i]; - } - } - - pFreq_buf_re = &st_ivas->hCrend->freq_buffer_re[i][offset]; - pFreq_buf_im = &st_ivas->hCrend->freq_buffer_im[i][offset]; - - ivas_mdft( pIn, pFreq_buf_re, pFreq_buf_im, subframe_length, subframe_length ); - i++; - } - } - - for ( j = 0; j < nchan_out; j++ ) - { - set_zero( tmp_out_re, subframe_length ); - set_zero( tmp_out_im, subframe_length ); - - i = 0; - for ( idx_in = 0; idx_in < nchan_intern; idx_in++ ) - { - if ( idx_in != st_ivas->hIntSetup.index_lfe[0] ) - { - offset = 0; - for ( m = 0; m < st_ivas->hHrtf->num_iterations[i][j]; m++ ) - { - offset_in = ( st_ivas->hCrend->delay_line_rw_index + st_ivas->hHrtf->max_num_iterations - st_ivas->hHrtf->num_iterations[i][j] + m + 1 ); - offset_in = offset_in % ( st_ivas->hHrtf->max_num_iterations ); - offset_in = offset_in * subframe_length; - pFreq_buf_re = &st_ivas->hCrend->freq_buffer_re[i][offset_in]; - pFreq_buf_im = &st_ivas->hCrend->freq_buffer_im[i][offset_in]; - pFreq_filt_re = &st_ivas->hHrtf->pOut_to_bin_re[i][j][offset]; - pFreq_filt_im = &st_ivas->hHrtf->pOut_to_bin_im[i][j][offset]; - - for ( k = 0; k < st_ivas->hHrtf->pIndex_frequency_max[i][j][m]; k++ ) - { - tmp_out_re[k] += pFreq_buf_re[k] * pFreq_filt_re[k] - pFreq_buf_im[k] * pFreq_filt_im[k]; - tmp_out_im[k] += pFreq_buf_re[k] * pFreq_filt_im[k] + pFreq_buf_im[k] * pFreq_filt_re[k]; - } - offset = offset + k; - } - i++; - } - } - - offset = 0; - for ( m = 0; m < st_ivas->hHrtf->num_iterations_diffuse[j]; m++ ) - { - offset_diffuse = ( st_ivas->hCrend->diffuse_delay_line_rw_index + m + 1 ); - offset_diffuse = offset_diffuse % st_ivas->hHrtf->num_iterations_diffuse[0]; - offset_diffuse = offset_diffuse * subframe_length; - pFreq_buf_re = &st_ivas->hCrend->freq_buffer_re_diffuse[offset_diffuse]; - pFreq_buf_im = &st_ivas->hCrend->freq_buffer_im_diffuse[offset_diffuse]; - pFreq_filt_re = &st_ivas->hHrtf->pOut_to_bin_diffuse_re[j][offset]; - pFreq_filt_im = &st_ivas->hHrtf->pOut_to_bin_diffuse_im[j][offset]; - - for ( k = 0; k < st_ivas->hHrtf->pIndex_frequency_max_diffuse[j][m]; k++ ) - { - tmp_out_re[k] += pFreq_buf_re[k] * pFreq_filt_re[k] - pFreq_buf_im[k] * pFreq_filt_im[k]; - tmp_out_im[k] += pFreq_buf_re[k] * pFreq_filt_im[k] + pFreq_buf_im[k] * pFreq_filt_re[k]; - } - offset = offset + k; - } - - ivas_imdft( tmp_out_re, tmp_out_im, pOut, subframe_length ); - - pFreq_buf_re = &pcm_out[j][i_ts * subframe_length]; - for ( k = 0; k < subframe_length; k++ ) - { - pFreq_buf_re[k] = pOut[k] + st_ivas->hCrend->prev_out_buffer[j][k]; - st_ivas->hCrend->prev_out_buffer[j][k] = pOut[k + subframe_length]; - } - } - - st_ivas->hCrend->delay_line_rw_index++; - st_ivas->hCrend->delay_line_rw_index = st_ivas->hCrend->delay_line_rw_index % ( st_ivas->hHrtf->max_num_iterations ); - if ( st_ivas->hHrtf->num_iterations_diffuse[0] > 0 ) - { - st_ivas->hCrend->diffuse_delay_line_rw_index++; - st_ivas->hCrend->diffuse_delay_line_rw_index = st_ivas->hCrend->diffuse_delay_line_rw_index % ( st_ivas->hHrtf->num_iterations_diffuse[0] ); - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_crend_process() - * - * Process call for IVAS Crend renderer - *-----------------------------------------------------------------------------------------*/ - -ivas_error ivas_crend_process( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output[][L_FRAME48k] /* i/o: input/output audio channels */ -) -{ - int16_t i, nchan_out, output_frame; - int16_t subframe_len, subframe_idx; - float pcm_tmp[MAX_TRANSPORT_CHANNELS][L_FRAME48k]; - AUDIO_CONFIG intern_config; - ivas_error error; - - wmops_sub_start( "ivas_crend_process" ); - - intern_config = st_ivas->intern_config; - nchan_out = st_ivas->hDecoderConfig->nchan_out; - output_frame = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); - subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; - - for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) - { - if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData && st_ivas->hHeadTrackData->num_quaternions >= 0 ) - { - /* Orientation tracking */ - if ( st_ivas->hCrend->hTrack != NULL ) - { - if ( st_ivas->hDecoderConfig->orientation_tracking == IVAS_ORIENT_TRK_AVG ) - { - ivas_orient_trk_SetTrackingType( st_ivas->hCrend->hTrack, OTR_TRACKING_AVG_ORIENT ); - } - else - { - ivas_orient_trk_SetTrackingType( st_ivas->hCrend->hTrack, OTR_TRACKING_REF_ORIENT ); - } - - /* get current subframe quaternion and convert to euler angles */ - Quat2Euler( st_ivas->hHeadTrackData->Quaternions[subframe_idx], &( st_ivas->hCrend->m_fYaw ), &( st_ivas->hCrend->m_fPitch ), &( st_ivas->hCrend->m_fRoll ) ); - ivas_orient_trk_SetAbsoluteOrientation( st_ivas->hCrend->hTrack, st_ivas->hCrend->m_fYaw, st_ivas->hCrend->m_fPitch, st_ivas->hCrend->m_fRoll ); - ivas_orient_trk_Process( st_ivas->hCrend->hTrack ); - ivas_orient_trk_GetTrackedOrientation( st_ivas->hCrend->hTrack, &( st_ivas->hCrend->m_fYaw ), &( st_ivas->hCrend->m_fPitch ), &( st_ivas->hCrend->m_fRoll ) ); - } - - /* Rotation in SHD for: - MC with elevation (5_1_2 / 5_1_4 / 7_1_4) -> BINAURAL - SBA SPAR -> BINAURAL or BINAURAL_ROOM - */ - if ( intern_config == AUDIO_CONFIG_FOA || intern_config == AUDIO_CONFIG_HOA2 || intern_config == AUDIO_CONFIG_HOA3 ) - { - rotateFrame_shd( st_ivas->hHeadTrackData, output, st_ivas->hDecoderConfig->output_Fs, subframe_len, st_ivas->hIntSetup, subframe_idx ); - } - /* Rotation in SD for MC -> BINAURAL_ROOM */ - else if ( st_ivas->ivas_format != ISM_FORMAT && st_ivas->hIntSetup.is_loudspeaker_setup ) - { - rotateFrame_sd( st_ivas->hHeadTrackData, output, st_ivas->hDecoderConfig->output_Fs, subframe_len, st_ivas->hIntSetup, st_ivas->hEFAPdata, subframe_idx ); - } - } - - if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) - { - if ( ( intern_config == AUDIO_CONFIG_FOA ) || ( intern_config == AUDIO_CONFIG_HOA2 ) || ( intern_config == AUDIO_CONFIG_HOA3 ) || - ( intern_config == AUDIO_CONFIG_5_1 ) || ( intern_config == AUDIO_CONFIG_7_1 ) || - ( intern_config == AUDIO_CONFIG_5_1_2 ) || ( intern_config == AUDIO_CONFIG_5_1_4 ) || ( intern_config == AUDIO_CONFIG_7_1_4 ) ) - { - ivas_crend_convolver( st_ivas, output, pcm_tmp, subframe_idx ); - - if ( st_ivas->hCrend->hReverb != NULL ) - { - if ( ( error = ivas_reverb_process( st_ivas->hCrend->hReverb, intern_config, 1, output, pcm_tmp, subframe_idx ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } - else - { - return IVAS_ERR_INVALID_INPUT_FORMAT; - } - } - else - { - return IVAS_ERR_INTERNAL_FATAL; - } - } - - /* move to output */ - for ( i = 0; i < nchan_out; i++ ) - { - mvr2r( pcm_tmp[i], output[i], output_frame ); - } - - return IVAS_ERR_OK; -} diff --git a/lib_dec/ivas_dec.c b/lib_dec/ivas_dec.c index f852eeed269e75cc3448c2adcefad9cec335ff9d..b4eb783624a3e2115d73c4dda09e06d991af8799 100644 --- a/lib_dec/ivas_dec.c +++ b/lib_dec/ivas_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,11 +37,12 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_rom_com.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* @@ -67,12 +68,12 @@ ivas_error ivas_dec( error = IVAS_ERR_OK; - wmops_sub_start( "ivas_dec" ); + push_wmops( "ivas_dec" ); /*----------------------------------------------------------------* * IVAS decoder setup * - read IVAS format signaling - * - read IVAS format specific signalling + * - read IVAS format specific signaling * - initialize decoder in the first frame based on IVAS format and number of transport channels * - reconfigure the decoder when the number of TC or IVAS total bitrate change *----------------------------------------------------------------*/ @@ -139,13 +140,83 @@ ivas_error ivas_dec( else if ( st_ivas->ivas_format == ISM_FORMAT ) { /* Metadata decoding and configuration */ - if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + if ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) + { + if ( ( error = ivas_ism_dtx_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { + // VE: call ivas_ism_metadata_dec() with 'st_ivas' - TBD +#ifdef DISCRETE_ISM_DTX_CNG +#ifdef NCHAN_ISM_PARAMETER +#ifdef FIX_379_EXT_METADATA + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, st_ivas->hDirAC->hParamIsm, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, st_ivas->hDirAC->hParamIsm ) ) != IVAS_ERR_OK ) +#endif +#else +#ifdef FIX_379_EXT_METADATA + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, st_ivas->hDirAC->hParamIsm, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, st_ivas->hDirAC->hParamIsm ) ) != IVAS_ERR_OK ) +#endif +#endif + { + return error; + } +#else +#ifdef NCHAN_ISM_PARAMETER +#ifdef FIX_379_EXT_METADATA + ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ); +#else + ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm ); +#endif +#else +#ifdef FIX_379_EXT_METADATA + ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ); +#else ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm ); +#endif +#endif +#endif } else /* ISM_MODE_DISC */ { +#ifdef DISCRETE_ISM_DTX_CNG +#ifdef NCHAN_ISM_PARAMETER +#ifdef FIX_379_EXT_METADATA + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL ) ) != IVAS_ERR_OK ) +#endif +#else +#ifdef FIX_379_EXT_METADATA + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL ) ) != IVAS_ERR_OK ) +#endif +#endif + { + return error; + } +#else +#ifdef NCHAN_ISM_PARAMETER +#ifdef FIX_379_EXT_METADATA + ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ); +#else + ivas_ism_metadata_dec( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, NULL ); +#endif +#else +#ifdef FIX_379_EXT_METADATA + ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt ); +#else ivas_ism_metadata_dec( ivas_total_brate, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, NULL ); +#endif +#endif +#endif } for ( n = 0; n < st_ivas->nchan_transport; n++ ) @@ -165,6 +236,7 @@ ivas_error ivas_dec( if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { ivas_param_ism_params_to_masa_param_mapping( st_ivas ); + ivas_dirac_dec_binaural( st_ivas, output, st_ivas->nchan_transport ); } else if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) @@ -197,23 +269,35 @@ ivas_error ivas_dec( else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) { /* Convert to Ambisonics; used also for ISM->HOA3->binaural rendering */ +#ifdef NCHAN_ISM_PARAMETER + ivas_ism2sba( output, st_ivas->hIsmRendererData, st_ivas->hIsmMetaData, st_ivas->nchan_ism, output_frame, st_ivas->hIntSetup.ambisonics_order ); +#else ivas_ism2sba( output, st_ivas->hIsmRendererData, st_ivas->hIsmMetaData, st_ivas->nchan_transport, output_frame, st_ivas->hIntSetup.ambisonics_order ); +#endif } /* Binaural rendering */ if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { - ObjRenderIVASFrame( st_ivas, output, output_frame ); + if ( ( ivas_td_binaural_renderer( st_ivas, output, output_frame ) ) != IVAS_ERR_OK ) + { + return error; + } } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - ivas_crend_process( st_ivas, output ); + if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_BINAURAL_ROOM, NULL, NULL, NULL, NULL, output, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } ivas_binaural_add_LFE( st_ivas, output_frame, output ); } +#ifdef DEBUGGING else if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) { ivas_binaural_cldfb( st_ivas, output ); } +#endif } } else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) @@ -221,8 +305,7 @@ ivas_error ivas_dec( set_s( nb_bits_metadata, 0, MAX_SCE ); /* read parameters from the bitstream */ - if ( ( st_ivas->hQMetaData != NULL ) && - ( st_ivas->sba_mode != SBA_MODE_SPAR ) ) + if ( st_ivas->hQMetaData != NULL && st_ivas->sba_mode != SBA_MODE_SPAR ) { st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; @@ -240,12 +323,12 @@ ivas_error ivas_dec( } else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - if ( ( st_ivas->hQMetaData != NULL ) && ( SPAR_DIRAC_SPLIT_START_BAND < IVAS_MAX_NUM_BANDS ) ) + if ( st_ivas->hQMetaData != NULL ) { st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; - ivas_dirac_dec_read_BS( ivas_total_brate, st, st_ivas->hDirAC, st_ivas->hQMetaData, &nb_bits_metadata[0], - st_ivas->sba_mode, st_ivas->hSpar->hSparFoa->dirac_to_spar_md_bands ); + ivas_dirac_dec_read_BS( ivas_total_brate, st, st_ivas->hDirAC, st_ivas->hQMetaData, &nb_bits_metadata[0], st_ivas->sba_mode, st_ivas->hSpar->dirac_to_spar_md_bands ); } + if ( ( error = ivas_spar_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) { return error; @@ -279,33 +362,58 @@ ivas_error ivas_dec( return error; } } -#ifdef DEBUG_LBR_SBA - /* SCE Decoder Output */ - for ( int t = 0; t < 960; t++ ) - { - for ( int c = 0; c < st_ivas->nchan_transport; c++ ) - { - float val = output[c][t] / MAX16B_FLT; - dbgwrite( &val , sizeof( float ), 1, 1, "int_dec_core_out.raw" ); - } - } + +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after core-decoding */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[0], "core-decoding" ); #endif /* TCs remapping */ nchan_remapped = st_ivas->nchan_transport; if ( st_ivas->sba_dirac_stereo_flag ) { +#ifdef SBA2MONO + nchan_remapped = nchan_out; +#else nchan_remapped = CPE_CHANNELS; - ivas_sba_dirac_stereo_dec( st_ivas, output, output_frame ); +#endif + + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { +#ifdef SBA2MONO + ivas_agc_dec_process( st_ivas->hSpar->hAgcDec, output, output, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); + + if ( st_ivas->hSpar->hPCA != NULL ) + { + ivas_pca_dec( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, output ); + } + +#endif + ivas_spar_dec_gen_umx_mat( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi ); + } + + ivas_sba_dirac_stereo_dec( st_ivas, output, output_frame, st_ivas->ivas_format == MC_FORMAT ); } - else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && - ( ivas_total_brate > IVAS_SID_4k4 || ( ivas_total_brate <= IVAS_SID_4k4 && st_ivas->nCPE > 0 && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) + else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) { nchan_remapped = 1; /* Only one channel transported */ } /* HP filtering */ #ifndef DEBUG_SPAR_BYPASS_EVS_CODEC +#ifdef SBA_HPF_TUNING_DEC + int16_t nchan_hp20; + if ( st_ivas->ivas_format == MASA_FORMAT ) + { + nchan_hp20 = nchan_remapped; + } + else + { + nchan_hp20 = getNumChanSynthesis( st_ivas ); + } + for ( n = 0; n < nchan_hp20; n++ ) +#else for ( n = 0; n < nchan_remapped; n++ ) +#endif { hp20( output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); } @@ -316,7 +424,7 @@ ivas_error ivas_dec( if ( st_ivas->sba_mode == SBA_MODE_SPAR && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { - ivas_sba_mix_matrix_determiner( st_ivas, output, nchan_remapped, output_frame ); + ivas_sba_mix_matrix_determiner( st_ivas->hSpar, output, st_ivas->bfi, nchan_remapped, output_frame ); } } @@ -335,23 +443,31 @@ ivas_error ivas_dec( } /* Loudspeakers, Ambisonics or Binaural rendering */ - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->sba_mode == SBA_MODE_DIRAC ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - ivas_sba_linear_renderer( output, output_frame, nchan_remapped, output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ); - } - else if ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->sba_mode != SBA_MODE_SPAR ) ) - { - ivas_dirac_dec( st_ivas, output, nchan_remapped, NULL, NULL, -1 ); + ivas_dirac_dec_binaural( st_ivas, output, nchan_remapped ); } - else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + else if ( st_ivas->sba_mode == SBA_MODE_DIRAC || st_ivas->ivas_format == MASA_FORMAT ) { - ivas_dirac_dec_binaural( st_ivas, output, nchan_remapped ); + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) + { + if ( ( error = ivas_sba_linear_renderer( output, output_frame, nchan_remapped, output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->renderer_type == RENDERER_DIRAC ) + { + ivas_dirac_dec( st_ivas, output, nchan_remapped, NULL, NULL, -1 ); + } } - else if ( - ( ( st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) && st_ivas->sba_mode == SBA_MODE_SPAR ) || - ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) ) +#ifdef SBA2MONO + else if ( !st_ivas->sba_dirac_stereo_flag && nchan_out != 1 ) +#else + else if ( !st_ivas->sba_dirac_stereo_flag ) +#endif { - ivas_sba_upmixer_renderer( st_ivas, output, nchan_remapped, output_frame ); + ivas_sba_upmixer_renderer( st_ivas, output, output_frame ); /* Note: ivas_sba_linear_renderer() or ivas_dirac_dec() are called internally */ } } else if ( st_ivas->ivas_format == MC_FORMAT ) @@ -361,7 +477,12 @@ ivas_error ivas_dec( /* LFE channel decoder */ if ( st_ivas->mc_mode == MC_MODE_MCT ) { - st_ivas->hCPE[1]->hCoreCoder[1]->hTcxCfg = st_ivas->hCPE[1]->hCoreCoder[0]->hTcxCfg; +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( st_ivas->hCPE[1]->hCoreCoder[1]->hTcxCfg == NULL ) + { + st_ivas->hCPE[1]->hCoreCoder[1]->hTcxCfg = st_ivas->hCPE[1]->hCoreCoder[0]->hTcxCfg; + } +#endif ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, output_lfe_ch ); } @@ -391,13 +512,12 @@ ivas_error ivas_dec( /* Rendering */ if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - ivas_crend_process( st_ivas, output ); - ivas_binaural_add_LFE( st_ivas, output_frame, output ); - } - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) - { + if ( ( error = ivas_rend_crendProcess( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hHeadTrackData, &st_ivas->hIntSetup, st_ivas->hEFAPdata, output, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + ivas_binaural_add_LFE( st_ivas, output_frame, output ); - ivas_binaural_cldfb( st_ivas, output ); } else if ( st_ivas->renderer_type == RENDERER_MC ) { @@ -409,7 +529,11 @@ ivas_error ivas_dec( } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { - ObjRenderIVASFrame( st_ivas, output, output_frame ); + if ( ( ivas_td_binaural_renderer( st_ivas, output, output_frame ) ) != IVAS_ERR_OK ) + { + return error; + } + ivas_binaural_add_LFE( st_ivas, output_frame, output ); } } @@ -482,8 +606,7 @@ ivas_error ivas_dec( /* Delay the separated channel to sync with CLDFB delay of the DirAC synthesis, and synthesize the LFE signal. */ if ( output_config == AUDIO_CONFIG_5_1 || output_config == AUDIO_CONFIG_7_1 || output_config == AUDIO_CONFIG_5_1_4 || output_config == AUDIO_CONFIG_7_1_4 || - output_config == AUDIO_CONFIG_5_1_2 || - ( output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) + output_config == AUDIO_CONFIG_5_1_2 || ( output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) { ivas_lfe_synth_with_filters( st_ivas->hMasa->hMasaLfeSynth, output, output_frame, n, LFE_CHANNEL ); } @@ -513,7 +636,7 @@ ivas_error ivas_dec( if ( st_ivas->sba_dirac_stereo_flag ) /* use the flag to trigger the DFT upmix */ { - ivas_sba_dirac_stereo_dec( st_ivas, output, output_frame ); + ivas_sba_dirac_stereo_dec( st_ivas, output, output_frame, 1 ); } /* HP filtering */ @@ -571,13 +694,15 @@ ivas_error ivas_dec( if ( !st_ivas->bfi ) /* do not update if first frame(s) are lost or NO_DATA */ { st_ivas->hDecoderConfig->last_ivas_total_brate = ivas_total_brate; + st_ivas->last_active_ivas_total_brate = ( ivas_total_brate <= IVAS_SID_5k2 ) ? st_ivas->last_active_ivas_total_brate : ivas_total_brate; } if ( st_ivas->ini_frame < MAX_FRAME_COUNTER && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) ) /* keep "st_ivas->ini_frame = 0" until first good received frame */ { st_ivas->ini_frame++; } - if ( st_ivas->ini_active_frame < MAX_FRAME_COUNTER && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) && ivas_total_brate > IVAS_SID_4k4 ) + + if ( st_ivas->ini_active_frame < MAX_FRAME_COUNTER && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) && ivas_total_brate > IVAS_SID_5k2 ) /* needed in MASA decoder in case the first active frame is BFI, and there were SID-frames decoded before */ { st_ivas->ini_active_frame++; } @@ -585,8 +710,12 @@ ivas_error ivas_dec( #ifdef DEBUG_MODE_INFO dbgwrite( &st_ivas->bfi, sizeof( int16_t ), 1, output_frame, "res/bfi" ); dbgwrite( &st_ivas->BER_detect, sizeof( int16_t ), 1, output_frame, "res/BER_detect" ); + { + float tmpF = ivas_total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, "res/ivas_total_brate.dec" ); + } #endif - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_dec/ivas_decision_matrix_dec.c b/lib_dec/ivas_decision_matrix_dec.c index 3e6e87dc86114e655f844874a77763b330f1e6c7..e5be65ae24dc7204e3eb20cf21e643f4f150f566 100644 --- a/lib_dec/ivas_decision_matrix_dec.c +++ b/lib_dec/ivas_decision_matrix_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,13 +40,13 @@ #include "ivas_prot.h" #include "prot.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * ivas_decision_matrix_dec() * * ACELP/TCX/HQ core selection - * Read ACELP signalling bits from the bitstream + * Read ACELP signaling bits from the bitstream * Set extension layers *-----------------------------------------------------------------*/ @@ -73,7 +73,7 @@ void ivas_decision_matrix_dec( st->vbr_hw_BWE_disable_dec = 0; /*-----------------------------------------------------------------* - * Read SID signalling bits from the bitstream + * Read SID signaling bits from the bitstream *-----------------------------------------------------------------*/ if ( ( st->idchan == 0 && ( st->total_brate == FRAME_NO_DATA || st->total_brate == SID_2k40 ) ) || ( st->element_mode == IVAS_CPE_MDCT && st->total_brate <= SID_2k40 ) ) @@ -101,7 +101,7 @@ void ivas_decision_matrix_dec( st->L_frame = L_FRAME; } } - else if ( st->total_brate == SID_2k40 && st->idchan == 1 && st->element_mode == IVAS_CPE_MDCT && st->cng_dirac_flag == 0 ) + else if ( st->total_brate == SID_2k40 && st->idchan == 1 && st->element_mode == IVAS_CPE_MDCT && st->cng_sba_flag == 0 ) { /* read channel coherence */ st->hFdCngDec->hFdCngCom->coherence = (float) get_next_indice( st, 4 ) / 15.f; @@ -129,12 +129,12 @@ void ivas_decision_matrix_dec( if ( st->element_mode == IVAS_CPE_TD && st->idchan == 1 ) { - /* minimal signalling for the secondary channel, most of the parameters are deduced from the primary channel */ + /* minimal signaling for the secondary channel, most of the parameters are deduced from the primary channel */ st->core = ACELP_CORE; } else if ( st->element_mode == IVAS_SCE && st->low_rate_mode ) { - /* ISm Low-rate mode -> always WB, ACELP core, IC coder_type */ + /* ISM Low-rate mode -> always WB, ACELP core, IC coder_type */ st->core = ACELP_CORE; } else if ( st->element_mode == IVAS_CPE_MDCT ) @@ -160,14 +160,14 @@ void ivas_decision_matrix_dec( } /*-----------------------------------------------------------------* - * Read ACELP signalling bits from the bitstream + * Read ACELP signaling bits from the bitstream *-----------------------------------------------------------------*/ if ( st->core == ACELP_CORE ) { if ( st->element_mode == IVAS_SCE && st->low_rate_mode ) { - /* ISm Low-rate mode */ + /* ISM Low-rate mode */ st->bwidth = WB; st->coder_type = INACTIVE; *sharpFlag = 0; @@ -354,7 +354,7 @@ void ivas_decision_matrix_dec( st->core_brate = st->total_brate - st->extl_brate - icbwe_brate; /*-----------------------------------------------------------------* - * Read transform core (TCX vs. HQ) signalling bit from the bitstream + * Read transform core (TCX vs. HQ) signaling bit from the bitstream *-----------------------------------------------------------------*/ if ( st->element_mode != IVAS_CPE_MDCT && !( st->idchan == 1 && st->element_mode == IVAS_CPE_TD ) && st->core == HQ_CORE ) diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index d18a013df206dd8a7e46ddb1e0d0d25dfa5380a2..baab5f9346f107fbbe5993dfaeb91539a467e329 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,46 +37,29 @@ #include "cnst.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ -static void ivas_dirac_alloc_mem( DIRAC_DEC_HANDLE hDirAC, DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem ); +static ivas_error ivas_dirac_alloc_mem( DIRAC_DEC_HANDLE hDirAC, const RENDERER_TYPE renderer_type, DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem ); static void ivas_dirac_free_mem( DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem ); -static void initDiffuseResponses( - float *diffuse_response_function, - const int16_t num_channels, - AUDIO_CONFIG output_config, - IVAS_OUTPUT_SETUP hOutSetup, - const int16_t ambisonics_order, - const IVAS_FORMAT ivas_format, - int16_t *num_ele_spk_no_diffuse_rendering, - AUDIO_CONFIG transport_config ); +static void initDiffuseResponses( float *diffuse_response_function, const int16_t num_channels, AUDIO_CONFIG output_config, IVAS_OUTPUT_SETUP hOutSetup, const int16_t ambisonics_order, const IVAS_FORMAT ivas_format, int16_t *num_ele_spk_no_diffuse_rendering, AUDIO_CONFIG transport_config ); static void computeIntensityVector_dec( float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], const int16_t num_frequency_bands, float *intensity_real_x, float *intensity_real_y, float *intensity_real_z ); -static void protoSignalComputation_shd( - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], - float *proto_direct_buffer_f, - float *proto_diffuse_buffer_f, - float *reference_power, - const int16_t slot_index, - const int16_t num_inputs, - const int16_t num_outputs_diff, - const int16_t num_freq_bands, - float *p_Rmat ); +static void protoSignalComputation_shd( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float *proto_direct_buffer_f, float *proto_diffuse_buffer_f, float *reference_power, const int16_t slot_index, const int16_t num_inputs, const int16_t num_outputs_diff, const int16_t num_freq_bands, float *p_Rmat ); static void protoSignalComputation1( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float *proto_frame_f, float *proto_direct_buffer_f, float *reference_power, float *proto_power_smooth, const int16_t slot_index, const int16_t num_outputs_diff, const int16_t num_freq_bands ); @@ -86,7 +69,6 @@ static void protoSignalComputation4( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRA static void ivas_dirac_dec_compute_diffuse_proto( DIRAC_DEC_HANDLE hDirAC, const int16_t slot_idx ); - static void computeDirectionAngles( float *intensity_real_x, float *intensity_real_y, float *intensity_real_z, const int16_t num_frequency_bands, int16_t *azimuth, int16_t *elevation ); static void ivas_masa_init_stereotype_detection( MASA_STEREO_TYPE_DETECT *stereo_type_detect ); @@ -95,6 +77,8 @@ static void ivas_masa_stereotype_detection( MASA_STEREO_TYPE_DETECT *stereo_type static void ivas_lfe_synth_with_cldfb( MCMASA_LFE_SYNTH_DATA_HANDLE hMasaLfeSynth, float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float RealBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float ImagBufferLfe[MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], const int16_t slot_index, const int16_t subframe_index, const int16_t nchan_transport ); +static void rotateAziEle_DirAC( int16_t *azi, int16_t *ele, const int16_t band1, const int16_t band2, const float *p_Rmat ); + /*------------------------------------------------------------------------- * ivas_dirac_dec_open() @@ -126,8 +110,8 @@ ivas_error ivas_dirac_dec_open( *-------------------------------------------------------------------------*/ ivas_error ivas_dirac_dec_config( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const DIRAC_CONFIG_FLAG flag_config /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const DIRAC_CONFIG_FLAG flag_config_inp /* i/ : Flag determining if we open or reconfigure the DirAC decoder */ ) { DIRAC_DEC_HANDLE hDirAC; @@ -146,7 +130,9 @@ ivas_error ivas_dirac_dec_config( int32_t output_Fs, ivas_total_brate; ivas_error error; int16_t nchan_transport_orig; + DIRAC_CONFIG_FLAG flag_config; + flag_config = ( flag_config_inp == DIRAC_RECONFIGURE_MODE ) ? DIRAC_RECONFIGURE : flag_config_inp; error = IVAS_ERR_OK; hDirAC = NULL; @@ -163,12 +149,12 @@ ivas_error ivas_dirac_dec_config( * prepare library opening *-----------------------------------------------------------------*/ - if ( ( hDirAC = (DIRAC_DEC_HANDLE) count_malloc( sizeof( DIRAC_DEC_DATA ) ) ) == NULL ) + if ( ( hDirAC = (DIRAC_DEC_HANDLE) malloc( sizeof( DIRAC_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - if ( ( hDirAC->hConfig = (DIRAC_CONFIG_DATA_HANDLE) count_malloc( sizeof( DIRAC_CONFIG_DATA ) ) ) == NULL ) + if ( ( hDirAC->hConfig = (DIRAC_CONFIG_DATA_HANDLE) malloc( sizeof( DIRAC_CONFIG_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC Config\n" ) ); } @@ -186,10 +172,11 @@ ivas_error ivas_dirac_dec_config( nchan_transport_orig = st_ivas->nchan_transport; if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR && !( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { - st_ivas->nchan_transport = ivas_sba_get_nchan_metadata( st_ivas->sba_order ); + st_ivas->nchan_transport = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order ); } + nchan_transport = st_ivas->nchan_transport; - if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ivas_total_brate > IVAS_SID_4k4 ) + if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ivas_total_brate > IVAS_SID_5k2 ) { nchan_transport = 1; } @@ -197,7 +184,7 @@ ivas_error ivas_dirac_dec_config( if ( flag_config == DIRAC_RECONFIGURE && st_ivas->ivas_format == SBA_FORMAT ) { int16_t tmp1, tmp2, tmp3; - ivas_sba_config( st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->sba_order, -1, &nchan_transport_old, st_ivas->sba_planar, &tmp1, &tmp2, &tmp3, SBA_MODE_DIRAC ); + ivas_sba_config( ivas_total_brate, st_ivas->sba_analysis_order, -1, &nchan_transport_old, st_ivas->sba_planar, &tmp1, &tmp2, &tmp3 ); } /*-----------------------------------------------------------------* @@ -233,13 +220,13 @@ ivas_error ivas_dirac_dec_config( if ( hDirAC->hOutSetup.ambisonics_order == -1 ) { - hDirAC->hOutSetup.ambisonics_order = 3; /* Order 3 is used by default in DirAC for SHD processing */ + hDirAC->hOutSetup.ambisonics_order = SBA_HOA3_ORDER; /* Order 3 is used by default in DirAC for SHD processing */ if ( hDirAC->hOutSetup.output_config == AUDIO_CONFIG_MONO || hDirAC->hOutSetup.output_config == AUDIO_CONFIG_STEREO ) { - hDirAC->hOutSetup.ambisonics_order = 1; + hDirAC->hOutSetup.ambisonics_order = SBA_FOA_ORDER; } } - else if ( hDirAC->hOutSetup.ambisonics_order >= 1 ) + else if ( hDirAC->hOutSetup.ambisonics_order >= SBA_FOA_ORDER ) { mvr2r( ls_azimuth_4d4, ls_azimuth, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); mvr2r( ls_elevation_4d4, ls_elevation, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); @@ -258,6 +245,8 @@ ivas_error ivas_dirac_dec_config( * set input parameters *-----------------------------------------------------------------*/ + st_ivas->nchan_transport = nchan_transport_orig; + if ( flag_config == DIRAC_OPEN ) { hDirAC->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); @@ -272,8 +261,6 @@ ivas_error ivas_dirac_dec_config( return IVAS_ERR_OK; } - st_ivas->nchan_transport = nchan_transport_orig; - if ( nchan_transport_orig > 2 && hDirAC->hOutSetup.is_loudspeaker_setup && st_ivas->renderer_type == RENDERER_DIRAC ) { hDirAC->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; @@ -310,7 +297,10 @@ ivas_error ivas_dirac_dec_config( if ( flag_config == DIRAC_OPEN ) { hDirAC->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); - hDirAC->frequency_axis = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + if ( ( hDirAC->frequency_axis = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->frequency_axis, 0.0f, hDirAC->num_freq_bands ); ivas_dirac_dec_get_frequency_axis( hDirAC->frequency_axis, output_Fs, hDirAC->num_freq_bands ); @@ -320,7 +310,10 @@ ivas_error ivas_dirac_dec_config( { if ( ( flag_config == DIRAC_RECONFIGURE && hDirAC->masa_stereo_type_detect == NULL ) || flag_config == DIRAC_OPEN ) { - hDirAC->masa_stereo_type_detect = (MASA_STEREO_TYPE_DETECT *) count_malloc( sizeof( MASA_STEREO_TYPE_DETECT ) ); + if ( ( hDirAC->masa_stereo_type_detect = (MASA_STEREO_TYPE_DETECT *) malloc( sizeof( MASA_STEREO_TYPE_DETECT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } ivas_masa_init_stereotype_detection( hDirAC->masa_stereo_type_detect ); } @@ -328,7 +321,7 @@ ivas_error ivas_dirac_dec_config( { if ( flag_config == DIRAC_RECONFIGURE && hDirAC->masa_stereo_type_detect != NULL ) { - count_free( hDirAC->masa_stereo_type_detect ); + free( hDirAC->masa_stereo_type_detect ); } hDirAC->masa_stereo_type_detect = NULL; } @@ -368,7 +361,7 @@ ivas_error ivas_dirac_dec_config( hDirAC->num_outputs_diff += 2; /* Add 2nd-order planar components for HRs */ } - hDirAC->num_outputs_dir = ( hDirAC->hOutSetup.ambisonics_order + 1 ) * ( hDirAC->hOutSetup.ambisonics_order + 1 ); + hDirAC->num_outputs_dir = ivas_sba_get_nchan( hDirAC->hOutSetup.ambisonics_order, 0 ); } else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) { @@ -388,22 +381,34 @@ ivas_error ivas_dirac_dec_config( if ( flag_config == DIRAC_OPEN ) { num_outputs_dir_old = hDirAC->num_outputs_dir; - hDirAC->proto_index_dir = (int16_t *) count_malloc( sizeof( int16_t ) * hDirAC->num_outputs_dir ); + if ( ( hDirAC->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } num_outputs_diff_old = hDirAC->num_outputs_diff; - hDirAC->proto_index_diff = (int16_t *) count_malloc( sizeof( int16_t ) * hDirAC->num_outputs_diff ); + if ( ( hDirAC->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } if ( hDirAC->num_outputs_dir != num_outputs_dir_old && flag_config == DIRAC_RECONFIGURE ) { - count_free( hDirAC->proto_index_dir ); - hDirAC->proto_index_dir = (int16_t *) count_malloc( sizeof( int16_t ) * hDirAC->num_outputs_dir ); + free( hDirAC->proto_index_dir ); + if ( ( hDirAC->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } set_s( hDirAC->proto_index_dir, 0, hDirAC->num_outputs_dir ); if ( hDirAC->num_outputs_diff != num_outputs_diff_old && flag_config == DIRAC_RECONFIGURE ) { - count_free( hDirAC->proto_index_diff ); - hDirAC->proto_index_diff = (int16_t *) count_malloc( sizeof( int16_t ) * hDirAC->num_outputs_diff ); + free( hDirAC->proto_index_diff ); + if ( ( hDirAC->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirAC->num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } set_s( hDirAC->proto_index_diff, 0, hDirAC->num_outputs_diff ); @@ -523,14 +528,20 @@ ivas_error ivas_dirac_dec_config( /* direct/diffuse responses */ if ( flag_config == DIRAC_OPEN ) { - hDirAC->diffuse_response_function = (float *) count_malloc( sizeof( float ) * hDirAC->num_outputs_dir ); + if ( ( hDirAC->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirAC->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } /* reallocate static memory */ else if ( flag_config == DIRAC_RECONFIGURE && hDirAC->num_outputs_dir != num_outputs_dir_old ) { - count_free( hDirAC->diffuse_response_function ); + free( hDirAC->diffuse_response_function ); hDirAC->diffuse_response_function = NULL; - hDirAC->diffuse_response_function = (float *) count_malloc( sizeof( float ) * hDirAC->num_outputs_dir ); + if ( ( hDirAC->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirAC->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } if ( ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) || ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) || ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) ) @@ -548,13 +559,19 @@ ivas_error ivas_dirac_dec_config( { if ( flag_config == DIRAC_OPEN ) { - hDirAC->hoa_encoder = (float *) count_malloc( nchan_out_woLFE * hDirAC->num_outputs_diff * sizeof( float ) ); + if ( ( hDirAC->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } else if ( flag_config == DIRAC_RECONFIGURE && hDirAC->hoa_encoder && ( hDirAC->num_outputs_diff != num_outputs_diff_old ) ) { - count_free( hDirAC->hoa_encoder ); + free( hDirAC->hoa_encoder ); hDirAC->hoa_encoder = NULL; - hDirAC->hoa_encoder = (float *) count_malloc( nchan_out_woLFE * hDirAC->num_outputs_diff * sizeof( float ) ); + if ( ( hDirAC->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } set_f( hDirAC->hoa_encoder, 0.0f, nchan_out_woLFE * hDirAC->num_outputs_diff ); compute_hoa_encoder_mtx( ls_azimuth, ls_elevation, hDirAC->hoa_encoder, hDirAC->num_outputs_diff, hDirAC->hOutSetup.ambisonics_order ); @@ -563,7 +580,7 @@ ivas_error ivas_dirac_dec_config( { if ( flag_config == DIRAC_RECONFIGURE && hDirAC->hoa_encoder ) { - count_free( hDirAC->hoa_encoder ); + free( hDirAC->hoa_encoder ); } hDirAC->hoa_encoder = NULL; } @@ -576,10 +593,11 @@ ivas_error ivas_dirac_dec_config( if ( hDirAC->panningConf == DIRAC_PANNING_VBAP ) { - if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata ) + if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata != NULL ) { vbap_free_data( &( st_ivas->hVBAPdata ) ); } + if ( ( error = vbap_init_data( &( st_ivas->hVBAPdata ), ls_azimuth, ls_elevation, nchan_out_woLFE ) ) != IVAS_ERR_OK ) { return error; @@ -587,13 +605,13 @@ ivas_error ivas_dirac_dec_config( } else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { - if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata ) + if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata != NULL ) { vbap_free_data( &( st_ivas->hVBAPdata ) ); } hDirAC->hoa_decoder = NULL; } - else if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata ) + else if ( flag_config == DIRAC_RECONFIGURE && st_ivas->hVBAPdata != NULL ) { vbap_free_data( &( st_ivas->hVBAPdata ) ); } @@ -608,7 +626,7 @@ ivas_error ivas_dirac_dec_config( { if ( st_ivas->hoa_dec_mtx != NULL ) { - count_free( st_ivas->hoa_dec_mtx ); + free( st_ivas->hoa_dec_mtx ); st_ivas->hoa_dec_mtx = NULL; } if ( ( error = ivas_sba_get_hoa_dec_matrix( hDirAC->hOutSetup, &st_ivas->hoa_dec_mtx, hDirAC->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) @@ -636,15 +654,18 @@ ivas_error ivas_dirac_dec_config( if ( ( flag_config == DIRAC_OPEN && hDirAC->proto_signal_decorr_on ) || ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->proto_signal_decorr_on && !proto_signal_decorr_on_old ) ) ) { - ivas_dirac_dec_decorr_open( &( hDirAC->h_freq_domain_decorr_ap_params ), - &( hDirAC->h_freq_domain_decorr_ap_state ), - hDirAC->num_freq_bands, - hDirAC->num_outputs_diff, - hDirAC->num_protos_diff, - hDirAC->synthesisConf, - hDirAC->frequency_axis, - nchan_transport > 2 ? 4 : nchan_transport, - output_Fs ); + if ( ( error = ivas_dirac_dec_decorr_open( &( hDirAC->h_freq_domain_decorr_ap_params ), + &( hDirAC->h_freq_domain_decorr_ap_state ), + hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + hDirAC->frequency_axis, + nchan_transport > 2 ? 4 : nchan_transport, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } } else if ( flag_config == DIRAC_RECONFIGURE && ( !hDirAC->proto_signal_decorr_on && proto_signal_decorr_on_old ) ) { @@ -652,33 +673,43 @@ ivas_error ivas_dirac_dec_config( } else if ( flag_config == DIRAC_RECONFIGURE && hDirAC->proto_signal_decorr_on && proto_signal_decorr_on_old ) { - if ( ( nchan_transport != nchan_transport_old ) || ( hDirAC->num_outputs_diff != num_outputs_diff_old ) ) + if ( nchan_transport != nchan_transport_old || hDirAC->num_outputs_diff != num_outputs_diff_old || flag_config_inp == DIRAC_RECONFIGURE_MODE ) { /* close and reopen the decorrelator */ ivas_dirac_dec_decorr_close( &hDirAC->h_freq_domain_decorr_ap_params, &hDirAC->h_freq_domain_decorr_ap_state ); - ivas_dirac_dec_decorr_open( &( hDirAC->h_freq_domain_decorr_ap_params ), - &( hDirAC->h_freq_domain_decorr_ap_state ), - hDirAC->num_freq_bands, - hDirAC->num_outputs_diff, - hDirAC->num_protos_diff, - hDirAC->synthesisConf, - hDirAC->frequency_axis, - nchan_transport > 2 ? 4 : nchan_transport, - output_Fs ); + if ( ( error = ivas_dirac_dec_decorr_open( &( hDirAC->h_freq_domain_decorr_ap_params ), + &( hDirAC->h_freq_domain_decorr_ap_state ), + hDirAC->num_freq_bands, + hDirAC->num_outputs_diff, + hDirAC->num_protos_diff, + hDirAC->synthesisConf, + hDirAC->frequency_axis, + nchan_transport > 2 ? 4 : nchan_transport, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } } } /* output synthesis */ if ( flag_config == DIRAC_OPEN ) { - ivas_dirac_dec_output_synthesis_open( hDirAC, st_ivas->renderer_type, nchan_transport, output_Fs ); + if ( ( ivas_dirac_dec_output_synthesis_open( hDirAC, st_ivas->renderer_type, nchan_transport, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } hDirAC->h_output_synthesis_psd_params.use_onset_filters = hDirAC->proto_signal_decorr_on; } else if ( ( flag_config == DIRAC_RECONFIGURE ) && ( ( nchan_transport != nchan_transport_old ) || ( hDirAC->num_outputs_diff != num_outputs_diff_old ) ) ) { ivas_dirac_dec_output_synthesis_close( hDirAC ); - ivas_dirac_dec_output_synthesis_open( hDirAC, st_ivas->renderer_type, nchan_transport, output_Fs ); + + if ( ( ivas_dirac_dec_output_synthesis_open( hDirAC, st_ivas->renderer_type, nchan_transport, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } hDirAC->h_output_synthesis_psd_params.use_onset_filters = hDirAC->proto_signal_decorr_on; } @@ -695,7 +726,7 @@ ivas_error ivas_dirac_dec_config( { if ( flag_config == DIRAC_RECONFIGURE && hDirAC->proto_frame_f ) { - count_free( hDirAC->proto_frame_f ); + free( hDirAC->proto_frame_f ); } hDirAC->proto_frame_f = NULL; } @@ -703,16 +734,27 @@ ivas_error ivas_dirac_dec_config( { if ( flag_config == DIRAC_OPEN || ( flag_config == DIRAC_RECONFIGURE && hDirAC->proto_frame_f == NULL ) ) { - hDirAC->proto_frame_f = (float *) count_malloc( sizeof( float ) * 2 * hDirAC->num_protos_diff * hDirAC->num_freq_bands ); + if ( ( hDirAC->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirAC->num_protos_diff * hDirAC->num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } else if ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->num_protos_diff != num_protos_diff_old ) ) { proto_frame_f_old = hDirAC->proto_frame_f; - count_free( proto_frame_f_old ); - hDirAC->proto_frame_f = (float *) count_malloc( sizeof( float ) * 2 * hDirAC->num_protos_diff * hDirAC->num_freq_bands ); + free( proto_frame_f_old ); + if ( ( hDirAC->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirAC->num_protos_diff * hDirAC->num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } } } + + if ( flag_config == DIRAC_OPEN ) + { + hDirAC->buffer_energy = NULL; + } if ( ( flag_config == DIRAC_OPEN && hDirAC->hConfig->dec_param_estim == TRUE ) || ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->hConfig->dec_param_estim == TRUE && dec_param_estim_old == FALSE ) ) ) { hDirAC->index_buffer_intensity = 0; @@ -721,11 +763,20 @@ ivas_error ivas_dirac_dec_config( { for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) { - hDirAC->buffer_intensity_real[i][j] = (float *) count_malloc( CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + if ( ( hDirAC->buffer_intensity_real[i][j] = (float *) malloc( CLDFB_NO_CHANNELS_MAX * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->buffer_intensity_real[i][j], 0.0f, CLDFB_NO_CHANNELS_MAX ); } } - + if ( hDirAC->buffer_energy == NULL ) + { + if ( ( hDirAC->buffer_energy = (float *) malloc( DIRAC_NO_COL_AVG_DIFF * CLDFB_NO_CHANNELS_MAX * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + } set_f( hDirAC->buffer_energy, 0.0f, DIRAC_NO_COL_AVG_DIFF * CLDFB_NO_CHANNELS_MAX ); } else if ( ( flag_config == DIRAC_OPEN && hDirAC->hConfig->dec_param_estim == FALSE ) || ( flag_config == DIRAC_RECONFIGURE && ( hDirAC->hConfig->dec_param_estim == FALSE && dec_param_estim_old == TRUE ) ) ) @@ -736,11 +787,16 @@ ivas_error ivas_dirac_dec_config( { if ( flag_config == DIRAC_RECONFIGURE && hDirAC->buffer_intensity_real[i][j] ) { - count_free( hDirAC->buffer_intensity_real[i][j] ); + free( hDirAC->buffer_intensity_real[i][j] ); } hDirAC->buffer_intensity_real[i][j] = NULL; } } + if ( hDirAC->buffer_energy != NULL ) + { + free( hDirAC->buffer_energy ); + hDirAC->buffer_energy = NULL; + } } /* output synthesis */ @@ -751,11 +807,13 @@ ivas_error ivas_dirac_dec_config( { ivas_dirac_free_mem( &( hDirAC->stack_mem ) ); } - ivas_dirac_alloc_mem( hDirAC, &( hDirAC->stack_mem ) ); + if ( ( error = ivas_dirac_alloc_mem( hDirAC, st_ivas->renderer_type, &( hDirAC->stack_mem ) ) ) != IVAS_ERR_OK ) + { + return error; + } mvs2s( DirAC_block_grouping, hDirAC->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); - if ( flag_config == DIRAC_OPEN ) { hDirAC->dirac_md_buffer_length = 0; @@ -763,10 +821,22 @@ ivas_error ivas_dirac_dec_config( hDirAC->dirac_read_idx = 0; hDirAC->spar_to_dirac_write_idx = 0; +#ifdef FIX_350_MASA_DELAY_COMP + if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; + } + else if ( st_ivas->ivas_format == MASA_FORMAT ) + { + hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; + hDirAC->dirac_bs_md_write_idx = DELAY_MASA_PARAM_DEC_SFR; + } +#else if ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->mc_mode == MC_MODE_MCMASA ) { hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; } +#endif else { int16_t num_slots_in_subfr; @@ -790,45 +860,121 @@ ivas_error ivas_dirac_dec_config( } } - hDirAC->azimuth = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->elevation = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->diffuseness_vector = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->energy_ratio1 = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->spreadCoherence = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->surroundingCoherence = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); + if ( ( hDirAC->azimuth = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->elevation = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->diffuseness_vector = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->energy_ratio1 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->spreadCoherence = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->surroundingCoherence = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - hDirAC->azimuth[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + if ( ( hDirAC->azimuth[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_s( hDirAC->azimuth[i], 0, hDirAC->num_freq_bands ); - hDirAC->elevation[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + + if ( ( hDirAC->elevation[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_s( hDirAC->elevation[i], 0, hDirAC->num_freq_bands ); - hDirAC->diffuseness_vector[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->diffuseness_vector[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->diffuseness_vector[i], 1.0f, hDirAC->num_freq_bands ); - hDirAC->energy_ratio1[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + if ( ( hDirAC->energy_ratio1[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->energy_ratio1[i], 0.0f, hDirAC->num_freq_bands ); - hDirAC->spreadCoherence[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->spreadCoherence[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->spreadCoherence[i], 0.0f, hDirAC->num_freq_bands ); - hDirAC->surroundingCoherence[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->surroundingCoherence[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->surroundingCoherence[i], 0.0f, hDirAC->num_freq_bands ); } if ( st_ivas->ivas_format == MASA_FORMAT ) { - hDirAC->azimuth2 = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->elevation2 = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->energy_ratio2 = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->spreadCoherence2 = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); + if ( ( hDirAC->azimuth2 = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->elevation2 = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->energy_ratio2 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirAC->spreadCoherence2 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - hDirAC->azimuth2[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + if ( ( hDirAC->azimuth2[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_s( hDirAC->azimuth2[i], 0, hDirAC->num_freq_bands ); - hDirAC->elevation2[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + + if ( ( hDirAC->elevation2[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_s( hDirAC->elevation2[i], 0, hDirAC->num_freq_bands ); - hDirAC->energy_ratio2[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + if ( ( hDirAC->energy_ratio2[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->energy_ratio2[i], 0.0f, hDirAC->num_freq_bands ); - hDirAC->spreadCoherence2[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->spreadCoherence2[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->spreadCoherence2[i], 0.0f, hDirAC->num_freq_bands ); } } @@ -846,8 +992,6 @@ ivas_error ivas_dirac_dec_config( st_ivas->hDirAC = hDirAC; } - st_ivas->nchan_transport = nchan_transport_orig; - return error; } @@ -859,15 +1003,23 @@ ivas_error ivas_dirac_dec_config( *------------------------------------------------------------------------*/ void ivas_dirac_dec_close( - DIRAC_DEC_HANDLE hDirAC /* i/o: decoder DirAC handle */ + DIRAC_DEC_HANDLE *hDirAC_out /* i/o: decoder DirAC handle */ ) { int16_t i, j; + DIRAC_DEC_HANDLE hDirAC; + + if ( hDirAC_out == NULL || *hDirAC_out == NULL ) + { + return; + } + + hDirAC = *hDirAC_out; /* Config & CLDFB */ if ( hDirAC->hConfig != NULL ) { - count_free( hDirAC->hConfig ); + free( hDirAC->hConfig ); hDirAC->hConfig = NULL; } @@ -885,32 +1037,32 @@ void ivas_dirac_dec_close( /* free frequency axis buffer */ if ( hDirAC->frequency_axis != NULL ) { - count_free( hDirAC->frequency_axis ); + free( hDirAC->frequency_axis ); hDirAC->frequency_axis = NULL; } if ( hDirAC->diffuse_response_function != NULL ) { - count_free( hDirAC->diffuse_response_function ); + free( hDirAC->diffuse_response_function ); hDirAC->diffuse_response_function = NULL; } if ( hDirAC->hoa_encoder != NULL ) { - count_free( hDirAC->hoa_encoder ); + free( hDirAC->hoa_encoder ); hDirAC->hoa_encoder = NULL; } /* prototype indexing */ if ( hDirAC->proto_index_dir != NULL ) { - count_free( hDirAC->proto_index_dir ); + free( hDirAC->proto_index_dir ); hDirAC->proto_index_dir = NULL; } if ( hDirAC->proto_index_diff != NULL ) { - count_free( hDirAC->proto_index_diff ); + free( hDirAC->proto_index_diff ); hDirAC->proto_index_dir = NULL; } @@ -920,7 +1072,7 @@ void ivas_dirac_dec_close( /* free prototype signal buffers */ if ( hDirAC->proto_frame_f != NULL ) { - count_free( hDirAC->proto_frame_f ); + free( hDirAC->proto_frame_f ); hDirAC->proto_frame_f = NULL; } @@ -930,44 +1082,49 @@ void ivas_dirac_dec_close( { if ( hDirAC->buffer_intensity_real[i][j] != NULL ) { - count_free( hDirAC->buffer_intensity_real[i][j] ); + free( hDirAC->buffer_intensity_real[i][j] ); hDirAC->buffer_intensity_real[i][j] = NULL; } } } + if ( hDirAC->buffer_energy != NULL ) + { + free( hDirAC->buffer_energy ); + hDirAC->buffer_energy = NULL; + } for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { if ( hDirAC->azimuth[i] != NULL ) { - count_free( hDirAC->azimuth[i] ); + free( hDirAC->azimuth[i] ); hDirAC->azimuth[i] = NULL; } if ( hDirAC->elevation[i] != NULL ) { - count_free( hDirAC->elevation[i] ); + free( hDirAC->elevation[i] ); hDirAC->elevation[i] = NULL; } if ( hDirAC->diffuseness_vector[i] != NULL ) { - count_free( hDirAC->diffuseness_vector[i] ); + free( hDirAC->diffuseness_vector[i] ); hDirAC->diffuseness_vector[i] = NULL; } } if ( hDirAC->azimuth != NULL ) { - count_free( hDirAC->azimuth ); + free( hDirAC->azimuth ); hDirAC->azimuth = NULL; } if ( hDirAC->elevation != NULL ) { - count_free( hDirAC->elevation ); + free( hDirAC->elevation ); hDirAC->elevation = NULL; } if ( hDirAC->diffuseness_vector != NULL ) { - count_free( hDirAC->diffuseness_vector ); + free( hDirAC->diffuseness_vector ); hDirAC->diffuseness_vector = NULL; } @@ -977,11 +1134,11 @@ void ivas_dirac_dec_close( { if ( hDirAC->azimuth2[i] != NULL ) { - count_free( hDirAC->azimuth2[i] ); + free( hDirAC->azimuth2[i] ); hDirAC->azimuth2[i] = NULL; } } - count_free( hDirAC->azimuth2 ); + free( hDirAC->azimuth2 ); hDirAC->azimuth2 = NULL; } @@ -991,11 +1148,11 @@ void ivas_dirac_dec_close( { if ( hDirAC->elevation2[i] != NULL ) { - count_free( hDirAC->elevation2[i] ); + free( hDirAC->elevation2[i] ); hDirAC->elevation2[i] = NULL; } } - count_free( hDirAC->elevation2 ); + free( hDirAC->elevation2 ); hDirAC->elevation2 = NULL; } @@ -1005,11 +1162,11 @@ void ivas_dirac_dec_close( { if ( hDirAC->energy_ratio1[i] != NULL ) { - count_free( hDirAC->energy_ratio1[i] ); + free( hDirAC->energy_ratio1[i] ); hDirAC->energy_ratio1[i] = NULL; } } - count_free( hDirAC->energy_ratio1 ); + free( hDirAC->energy_ratio1 ); hDirAC->energy_ratio1 = NULL; } @@ -1019,11 +1176,11 @@ void ivas_dirac_dec_close( { if ( hDirAC->energy_ratio2[i] != NULL ) { - count_free( hDirAC->energy_ratio2[i] ); + free( hDirAC->energy_ratio2[i] ); hDirAC->energy_ratio2[i] = NULL; } } - count_free( hDirAC->energy_ratio2 ); + free( hDirAC->energy_ratio2 ); hDirAC->energy_ratio2 = NULL; } @@ -1033,11 +1190,11 @@ void ivas_dirac_dec_close( { if ( hDirAC->spreadCoherence[i] != NULL ) { - count_free( hDirAC->spreadCoherence[i] ); + free( hDirAC->spreadCoherence[i] ); hDirAC->spreadCoherence[i] = NULL; } } - count_free( hDirAC->spreadCoherence ); + free( hDirAC->spreadCoherence ); hDirAC->spreadCoherence = NULL; } @@ -1047,11 +1204,11 @@ void ivas_dirac_dec_close( { if ( hDirAC->spreadCoherence2[i] != NULL ) { - count_free( hDirAC->spreadCoherence2[i] ); + free( hDirAC->spreadCoherence2[i] ); hDirAC->spreadCoherence2[i] = NULL; } } - count_free( hDirAC->spreadCoherence2 ); + free( hDirAC->spreadCoherence2 ); hDirAC->spreadCoherence2 = NULL; } @@ -1061,23 +1218,24 @@ void ivas_dirac_dec_close( { if ( hDirAC->surroundingCoherence[i] != NULL ) { - count_free( hDirAC->surroundingCoherence[i] ); + free( hDirAC->surroundingCoherence[i] ); hDirAC->surroundingCoherence[i] = NULL; } } - count_free( hDirAC->surroundingCoherence ); + free( hDirAC->surroundingCoherence ); hDirAC->surroundingCoherence = NULL; } if ( hDirAC->masa_stereo_type_detect != NULL ) { - count_free( hDirAC->masa_stereo_type_detect ); + free( hDirAC->masa_stereo_type_detect ); hDirAC->masa_stereo_type_detect = NULL; } ivas_dirac_free_mem( &( hDirAC->stack_mem ) ); - count_free( hDirAC ); + free( *hDirAC_out ); + *hDirAC_out = NULL; return; } @@ -1089,8 +1247,9 @@ void ivas_dirac_dec_close( * Allocate stack memory for DirAC renderer *------------------------------------------------------------------------*/ -static void ivas_dirac_alloc_mem( +static ivas_error ivas_dirac_alloc_mem( DIRAC_DEC_HANDLE hDirAC, + const RENDERER_TYPE renderer_type, DIRAC_DEC_STACK_MEM_HANDLE hDirAC_mem ) { int16_t num_freq_bands, num_freq_bands_diff, size; @@ -1115,16 +1274,36 @@ static void ivas_dirac_alloc_mem( hDirAC_mem->frame_dec_f = NULL; if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - hDirAC_mem->cy_auto_dir_smooth = (float *) malloc( sizeof( float ) * size ); + if ( ( hDirAC_mem->cy_auto_dir_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } set_zero( hDirAC_mem->cy_auto_dir_smooth, size ); - hDirAC_mem->proto_power_smooth = (float *) malloc( sizeof( float ) * size ); + + if ( ( hDirAC_mem->proto_power_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } set_zero( hDirAC_mem->proto_power_smooth, size ); - hDirAC_mem->proto_power_diff_smooth = (float *) malloc( sizeof( float ) * size ); + + if ( ( hDirAC_mem->proto_power_diff_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } set_zero( hDirAC_mem->proto_power_diff_smooth, size ); - hDirAC_mem->direct_responses_square = (float *) malloc( sizeof( float ) * size ); - set_zero( hDirAC_mem->direct_responses_square, size ); - hDirAC_mem->frame_dec_f = (float *) malloc( sizeof( float ) * 2 * num_outputs_diff * num_freq_bands ); + if ( ( hDirAC_mem->direct_responses_square = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero( hDirAC_mem->direct_responses_square, size ); + if ( hDirAC->proto_signal_decorr_on && ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) ) + { + if ( ( hDirAC_mem->frame_dec_f = (float *) malloc( sizeof( float ) * 2 * num_outputs_diff * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + } } hDirAC->h_output_synthesis_psd_state.proto_power_smooth = hDirAC_mem->proto_power_smooth; hDirAC->h_output_synthesis_psd_state.proto_power_diff_smooth = hDirAC_mem->proto_power_diff_smooth; @@ -1132,42 +1311,85 @@ static void ivas_dirac_alloc_mem( hDirAC->h_output_synthesis_psd_state.direct_responses_square = hDirAC_mem->direct_responses_square; /* Target and smoothed nrg factors/gains */ - hDirAC_mem->cy_cross_dir_smooth = (float *) malloc( sizeof( float ) * size ); + if ( ( hDirAC_mem->cy_cross_dir_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } set_zero( hDirAC_mem->cy_cross_dir_smooth, size ); + if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * size ); + if ( ( hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } set_zero( hDirAC_mem->cy_auto_diff_smooth, size ); } else { - hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands_diff ); + if ( ( hDirAC_mem->cy_auto_diff_smooth = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } set_zero( hDirAC_mem->cy_auto_diff_smooth, num_outputs_diff * num_freq_bands_diff ); } hDirAC->h_output_synthesis_psd_state.cy_cross_dir_smooth = hDirAC_mem->cy_cross_dir_smooth; hDirAC->h_output_synthesis_psd_state.cy_auto_diff_smooth = hDirAC_mem->cy_auto_diff_smooth; /*Responses (gains/factors)*/ - hDirAC_mem->direct_responses = (float *) malloc( sizeof( float ) * size ); + if ( ( hDirAC_mem->direct_responses = (float *) malloc( sizeof( float ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } set_zero( hDirAC_mem->direct_responses, size ); hDirAC->h_output_synthesis_psd_state.direct_responses = hDirAC_mem->direct_responses; /* Prototypes */ - hDirAC_mem->proto_direct_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_protos_dir * num_freq_bands ); - if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + hDirAC_mem->proto_direct_buffer_f = NULL; + hDirAC_mem->proto_diffuse_buffer_f = NULL; + if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) { - hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * size ); - } - else - { - hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_outputs_diff * num_freq_bands ); + if ( ( hDirAC_mem->proto_direct_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_protos_dir * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + + if ( hDirAC->proto_signal_decorr_on ) + { + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + if ( ( hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + } + else + { + if ( ( hDirAC_mem->proto_diffuse_buffer_f = (float *) malloc( sizeof( float ) * 2 * MAX_PARAM_SPATIAL_SUBFRAMES * num_outputs_diff * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + } + } } hDirAC->h_output_synthesis_psd_state.proto_direct_buffer_f = hDirAC_mem->proto_direct_buffer_f; hDirAC->h_output_synthesis_psd_state.proto_diffuse_buffer_f = hDirAC_mem->proto_diffuse_buffer_f; /* Gains/power factors*/ - hDirAC_mem->direct_power_factor = (float *) malloc( sizeof( float ) * num_freq_bands ); - hDirAC_mem->diffuse_power_factor = (float *) malloc( sizeof( float ) * num_freq_bands ); + hDirAC_mem->direct_power_factor = NULL; + hDirAC_mem->diffuse_power_factor = NULL; + if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( hDirAC_mem->direct_power_factor = (float *) malloc( sizeof( float ) * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + + if ( ( hDirAC_mem->diffuse_power_factor = (float *) malloc( sizeof( float ) * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + } hDirAC->h_output_synthesis_psd_state.direct_power_factor = hDirAC_mem->direct_power_factor; hDirAC->h_output_synthesis_psd_state.diffuse_power_factor = hDirAC_mem->diffuse_power_factor; @@ -1175,23 +1397,41 @@ static void ivas_dirac_alloc_mem( hDirAC_mem->onset_filter = NULL; if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ); - hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands ); + if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + if ( hDirAC->proto_signal_decorr_on ) + { + if ( ( hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * num_outputs_diff * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + } + } } else { if ( num_protos_dir > 2 ) { - hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 5 * num_freq_bands ); + if ( ( hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * 5 * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } } - else + + if ( hDirAC->proto_signal_decorr_on ) { - hDirAC_mem->reference_power = (float *) malloc( sizeof( float ) * num_freq_bands ); + if ( ( hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } } - hDirAC_mem->onset_filter = (float *) malloc( sizeof( float ) * 2 * num_freq_bands ); } - return; + return IVAS_ERR_OK; } @@ -1279,7 +1519,7 @@ void ivas_dirac_dec_read_BS( int16_t next_bit_pos_orig; *nb_bits = 0; - if ( !st->bfi && ivas_total_brate > IVAS_SID_4k4 ) + if ( !st->bfi && ivas_total_brate > IVAS_SID_5k2 ) { next_bit_pos_orig = st->next_bit_pos; st->next_bit_pos = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 ); @@ -1288,14 +1528,7 @@ void ivas_dirac_dec_read_BS( b = st->bit_stream[( st->next_bit_pos )--]; ( *nb_bits )++; - if ( sba_mode == SBA_MODE_SPAR ) - { - if ( ivas_total_brate == IVAS_SID_5k ) - { - b = 1; - } - } - else + if ( sba_mode != SBA_MODE_SPAR ) { assert( ( b == 0 ) || ( hQMetaData->q_direction[0].cfg.start_band > 0 ) ); } @@ -1342,7 +1575,6 @@ void ivas_dirac_dec_read_BS( *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT, sba_mode ); - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) { hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; @@ -1365,7 +1597,7 @@ void ivas_dirac_dec_read_BS( else { hQMetaData->sba_inactive_mode = 0; - hQMetaData->is_masa_type_format = 0; + hQMetaData->is_masa_ivas_format = 0; if ( hQMetaData->useLowerRes ) { hQMetaData->q_direction[0].cfg.nblocks = 1; @@ -1384,12 +1616,17 @@ void ivas_dirac_dec_read_BS( st->next_bit_pos = next_bit_pos_orig; } - else if ( !st->bfi && ivas_total_brate == IVAS_SID_4k4 ) + else if ( !st->bfi && ivas_total_brate == IVAS_SID_5k2 ) { next_bit_pos_orig = st->next_bit_pos; - /* subtract mode signalling bits, since bitstream was moved after mode reading */ + /* subtract mode signaling bits, since bitstream was moved after mode reading */ st->next_bit_pos = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 - SID_FORMAT_NBITS ); + /* 1 bit flag for SPAR/DirAC, already read in read format function */ + b = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits )++; + hQMetaData->sba_inactive_mode = 1; + orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; /* if we start with a SID frame, we need to init the azi/ele arrays.*/ if ( st->ini_frame == 0 ) @@ -1404,8 +1641,33 @@ void ivas_dirac_dec_read_BS( } } - *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT, SBA_MODE_DIRAC ); - *nb_bits += SID_FORMAT_NBITS; + *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT, sba_mode ); + + if ( sba_mode == SBA_MODE_SPAR ) + { + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i] = hQMetaData->q_direction[0].band_data[1].elevation[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio[0]; + } + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + for ( j = orig_dirac_bands - 2; j >= 0; j-- ) + { + hQMetaData->q_direction[0].band_data[j].azimuth[i] = hQMetaData->q_direction[0].band_data[0].azimuth[0]; + hQMetaData->q_direction[0].band_data[j].elevation[i] = hQMetaData->q_direction[0].band_data[0].elevation[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio[0]; + } + } + + hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; + } + else + { + *nb_bits += SID_FORMAT_NBITS; + } + st->next_bit_pos = next_bit_pos_orig; } @@ -1451,10 +1713,47 @@ void ivas_qmetadata_to_dirac( q_direction = &( hQMetaData->q_direction[0] ); hDirAC->numSimultaneousDirections = hQMetaData->no_directions; - if ( hMasa != NULL && ivas_total_brate > IVAS_SID_4k4 ) + if ( hMasa != NULL && ivas_total_brate > IVAS_SID_5k2 ) { +#ifdef FIX_350_MASA_DELAY_COMP + int16_t meta_write_index; band_mapping = hMasa->data.band_mapping; + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) + { + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + block ) % hDirAC->dirac_md_buffer_length; + + for ( band = 0; band < hMasa->config.numCodingBands; ++band ) + { + for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) + { + hDirAC->azimuth[meta_write_index][b] = (int16_t) q_direction->band_data[band].azimuth[block]; + hDirAC->elevation[meta_write_index][b] = (int16_t) q_direction->band_data[band].elevation[block]; + hDirAC->energy_ratio1[meta_write_index][b] = q_direction->band_data[band].energy_ratio[block]; + hDirAC->diffuseness_vector[meta_write_index][b] = 1.0f - q_direction->band_data[band].energy_ratio[block]; + + if ( q_direction->coherence_band_data != NULL ) + { + hDirAC->spreadCoherence[meta_write_index][b] = q_direction->coherence_band_data[band].spread_coherence[block] / 255.0f; + } + else + { + hDirAC->spreadCoherence[meta_write_index][b] = 0.0f; + } + + if ( hQMetaData->surcoh_band_data != NULL ) + { + hDirAC->surroundingCoherence[meta_write_index][b] = hQMetaData->surcoh_band_data[band].surround_coherence[block] / 255.0f; + } + else + { + hDirAC->surroundingCoherence[meta_write_index][b] = 0.0f; + } + } + } + } +#else + band_mapping = hMasa->data.band_mapping; for ( band = 0; band < hMasa->config.numCodingBands; ++band ) { for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) @@ -1486,10 +1785,37 @@ void ivas_qmetadata_to_dirac( } } } +#endif if ( hQMetaData->no_directions == 2 ) { q_direction = &( hQMetaData->q_direction[1] ); +#ifdef FIX_350_MASA_DELAY_COMP + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) + { + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + block ) % hDirAC->dirac_md_buffer_length; + + for ( band = 0; band < hMasa->config.numCodingBands; ++band ) + { + for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) + { + hDirAC->azimuth2[meta_write_index][b] = (int16_t) q_direction->band_data[band].azimuth[block]; + hDirAC->elevation2[meta_write_index][b] = (int16_t) q_direction->band_data[band].elevation[block]; + hDirAC->energy_ratio2[meta_write_index][b] = q_direction->band_data[band].energy_ratio[block]; + hDirAC->diffuseness_vector[meta_write_index][b] -= q_direction->band_data[band].energy_ratio[block]; + + if ( q_direction->coherence_band_data != NULL ) + { + hDirAC->spreadCoherence2[meta_write_index][b] = q_direction->coherence_band_data[band].spread_coherence[block] / 255.0f; + } + else + { + hDirAC->spreadCoherence2[meta_write_index][b] = 0.0f; + } + } + } + } +#else for ( band = 0; band < hMasa->config.numCodingBands; ++band ) { for ( b = MASA_band_grouping_24[band_mapping[band]]; b < MASA_band_grouping_24[band_mapping[band + 1]]; ++b ) @@ -1512,7 +1838,22 @@ void ivas_qmetadata_to_dirac( } } } +#endif + } +#ifdef FIX_350_MASA_DELAY_COMP + else if ( hDirAC->azimuth2 != NULL && hDirAC->elevation2 != NULL && hDirAC->energy_ratio2 != NULL && hDirAC->spreadCoherence2 != NULL ) + { + /* zero out old dir2 data */ + for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; ++block ) + { + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + block ) % hDirAC->dirac_md_buffer_length; + set_s( hDirAC->azimuth2[meta_write_index], 0, hDirAC->num_freq_bands ); + set_s( hDirAC->elevation2[meta_write_index], 0, hDirAC->num_freq_bands ); + set_zero( hDirAC->energy_ratio2[meta_write_index], hDirAC->num_freq_bands ); + set_zero( hDirAC->spreadCoherence2[meta_write_index], hDirAC->num_freq_bands ); + } } +#endif } else /* SBA mode/SID/Zero frame*/ { @@ -1527,7 +1868,7 @@ void ivas_qmetadata_to_dirac( nbands = hDirAC->band_grouping[hDirAC->hConfig->nbands]; band_grouping = hDirAC->band_grouping; - if ( ivas_total_brate <= IVAS_SID_4k4 && sba_mode != SBA_MODE_SPAR ) + if ( ivas_total_brate <= IVAS_SID_5k2 && sba_mode != SBA_MODE_SPAR ) { /* SID/zero-frame: 1 direction, 5 bands, nblocks re-generated out of SID decoder*/ start_band = 0; @@ -1623,7 +1964,7 @@ void ivas_qmetadata_to_dirac( ele = min( 90, ele ); ele = max( -90, ele ); - if ( ivas_total_brate > IVAS_SID_4k4 && q_direction->coherence_band_data != NULL ) + if ( ivas_total_brate > IVAS_SID_5k2 && q_direction->coherence_band_data != NULL ) { hDirAC->spreadCoherence[tmp_write_idx_band][b] = q_direction->coherence_band_data[qBand_idx].spread_coherence[block] / 255.0f; } @@ -1632,7 +1973,7 @@ void ivas_qmetadata_to_dirac( hDirAC->spreadCoherence[tmp_write_idx_band][b] = 0.0f; } - if ( ivas_total_brate > IVAS_SID_4k4 && q_direction->coherence_band_data != NULL ) + if ( ivas_total_brate > IVAS_SID_5k2 && q_direction->coherence_band_data != NULL ) { hDirAC->surroundingCoherence[tmp_write_idx_band][b] = hQMetaData->surcoh_band_data[qBand_idx].surround_coherence[0] / 255.0f; } @@ -1765,10 +2106,12 @@ void ivas_dirac_dec( float *reference_power, *reference_power_smooth; float *onset_filter, *onset_filter_subframe, *p_onset_filter = NULL; uint16_t coherence_flag; - wmops_sub_start( "ivas_dirac_dec" ); + + push_wmops( "ivas_dirac_dec" ); /* Initialize aux buffers */ hDirAC = st_ivas->hDirAC; + DirAC_mem = st_ivas->hDirAC->stack_mem; reference_power = DirAC_mem.reference_power; @@ -1787,9 +2130,9 @@ void ivas_dirac_dec( #ifdef DEBUG_MODE_DIRAC { - int16_t n, tmp[DIRAC_MAX_TRANS_CHANS * L_FRAME48k]; + int16_t n, tmp[IVAS_SPAR_MAX_CH * L_FRAME48k]; char file_name[50] = { 0 }; - const int16_t output_frame = st_ivas->output_Fs / FRAMES_PER_SEC; + const int16_t output_frame = st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC; for ( n = 0; n < nchan_transport; n++ ) { @@ -1827,7 +2170,7 @@ void ivas_dirac_dec( set_zero( onset_filter_subframe, hDirAC->num_freq_bands ); } - if ( ( st_ivas->hHeadTrackData ) ) + if ( st_ivas->hHeadTrackData ) { QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], st_ivas->hHeadTrackData->Rmat ); @@ -1839,6 +2182,7 @@ void ivas_dirac_dec( for ( slot_idx = 0; slot_idx < hDirAC->subframe_nbslots; slot_idx++ ) { index_slot = subframe_idx * hDirAC->subframe_nbslots + slot_idx; + /* Todo: This access to azimuth & elevation may use wrong indices as access should probably be based on hDirAC->dirac_read_idx */ rotateAziEle_DirAC( hDirAC->azimuth[index_slot], hDirAC->elevation[index_slot], num_freq_bands, hDirAC->num_freq_bands, p_Rmat ); } } @@ -1864,7 +2208,11 @@ void ivas_dirac_dec( for ( i = 0; i < hDirAC->num_freq_bands; i++ ) { dirEne = hDirAC->h_output_synthesis_psd_state.direct_power_factor[i]; +#ifdef FIX_401_DIRAC_RENDERER_META_READ_INDICES + surCohEner = hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] * hDirAC->surroundingCoherence[hDirAC->dirac_read_idx][i]; +#else surCohEner = hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] * hDirAC->surroundingCoherence[subframe_idx][i]; +#endif hDirAC->h_output_synthesis_psd_state.diffuse_power_factor[i] -= surCohEner; hDirAC->h_output_synthesis_psd_state.direct_power_factor[i] += surCohEner; @@ -1896,13 +2244,16 @@ void ivas_dirac_dec( set_zero( surCohRatio, hDirAC->num_freq_bands ); } } + if ( st_ivas->hDecoderConfig->Opt_Headrotation && st_ivas->hHeadTrackData->shd_rot_max_order == 1 ) { ivas_dirac_dec_compute_directional_responses( hDirAC, st_ivas->hVBAPdata, st_ivas->hMasa, +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES subframe_idx, subframe_idx, +#endif surCohRatio, st_ivas->hHeadTrackData->shd_rot_max_order, p_Rmat ); @@ -1912,8 +2263,10 @@ void ivas_dirac_dec( ivas_dirac_dec_compute_directional_responses( hDirAC, st_ivas->hVBAPdata, st_ivas->hMasa, +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES subframe_idx, subframe_idx, +#endif surCohRatio, 0, 0 ); @@ -1944,6 +2297,7 @@ void ivas_dirac_dec( st_ivas->cldfbAnaDec[ch] ); } } + /* CNG in DirAC, extra CLDFB ana for CNA*/ if ( st_ivas->nchan_transport == 1 && st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->sba_mode != SBA_MODE_SPAR ) { @@ -1956,7 +2310,7 @@ void ivas_dirac_dec( Cldfb_ImagBuffer[1][0], index_slot, st->cna_dirac_flag && st->flag_cna, - ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && ( st->cng_type == FD_CNG ) && st->cng_dirac_flag ); + ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && st->cng_type == FD_CNG && st->cng_sba_flag ); } /* LFE synthesis */ @@ -1984,9 +2338,7 @@ void ivas_dirac_dec( reference_power, slot_idx, nchan_transport, hDirAC->num_outputs_diff, hDirAC->num_freq_bands, - p_Rmat - - ); + p_Rmat ); } else { @@ -1996,9 +2348,7 @@ void ivas_dirac_dec( reference_power, slot_idx, nchan_transport, hDirAC->num_outputs_diff, hDirAC->num_freq_bands, - 0 - - ); + 0 ); } } else if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) @@ -2054,6 +2404,7 @@ void ivas_dirac_dec( /*-----------------------------------------------------------------* * Compute DirAC parameters at decoder side *-----------------------------------------------------------------*/ + if ( hDirAC->hConfig->dec_param_estim == TRUE ) { hDirAC->index_buffer_intensity = ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ @@ -2073,7 +2424,6 @@ void ivas_dirac_dec( hDirAC->buffer_intensity_real[1][index - 1], hDirAC->buffer_intensity_real[2][index - 1], num_freq_bands, - hDirAC->azimuth[hDirAC->dirac_estimator_idx], hDirAC->elevation[hDirAC->dirac_estimator_idx] ); @@ -2087,7 +2437,7 @@ void ivas_dirac_dec( hDirAC->dirac_estimator_idx = ( hDirAC->dirac_estimator_idx + 1 ) % hDirAC->dirac_md_buffer_length; } -#if DEBUG_MODE_DIRAC +#ifdef DEBUG_MODE_DIRAC { static FILE *fp_direction_vector = NULL, *fp_diffuseness = NULL, *fp_referencePower = NULL; @@ -2214,8 +2564,12 @@ void ivas_dirac_dec( p_Rmat, st_ivas->hVBAPdata, hDirAC->hOutSetup, - nchan_transport, - index_slot ); + nchan_transport +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES + , + index_slot +#endif + ); } else { @@ -2225,19 +2579,25 @@ void ivas_dirac_dec( 0, st_ivas->hVBAPdata, hDirAC->hOutSetup, - nchan_transport, - index_slot ); + nchan_transport +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES + , + index_slot +#endif + ); } if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { v_add( reference_power, reference_power_smooth, reference_power_smooth, hDirAC->num_freq_bands ); } + if ( hDirAC->hConfig->dec_param_estim ) { hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; } } + if ( hDirAC->hConfig->dec_param_estim == 0 ) { hDirAC->dirac_read_idx = ( hDirAC->dirac_read_idx + 1 ) % hDirAC->dirac_md_buffer_length; @@ -2284,7 +2644,6 @@ void ivas_dirac_dec( Cldfb_RealBuffer, Cldfb_ImagBuffer ); - /* Inverse CLDFB*/ for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) { @@ -2436,7 +2795,7 @@ void ivas_dirac_dec( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -2457,7 +2816,7 @@ void compute_hoa_encoder_mtx( { int16_t k, num_sh; - num_sh = ( ambisonics_order + 1 ) * ( ambisonics_order + 1 ); + num_sh = ivas_sba_get_nchan( ambisonics_order, 0 ); for ( k = 0; k < num_responses; k++ ) { @@ -2513,7 +2872,7 @@ static void initDiffuseResponses( if ( output_config == AUDIO_CONFIG_MONO ) { diffuse_response_function[0] = 1.0f; - diffuse_response_function[1] = 1.0f / sqrtf( 3.0f ); + diffuse_response_function[1] = inv_sqrt( 3.0f ); } else if ( !( output_config == AUDIO_CONFIG_FOA || output_config == AUDIO_CONFIG_HOA2 || output_config == AUDIO_CONFIG_HOA3 ) ) { @@ -2595,7 +2954,7 @@ static void initDiffuseResponses( { for ( k = 0; k < ( 2 * l + 1 ); k++ ) { - diffuse_response_function[idx++] = 1.0f / sqrtf( 2.0f * l + 1.0f ); + diffuse_response_function[idx++] = inv_sqrt( 2.0f * l + 1.0f ); } } } @@ -3173,6 +3532,7 @@ static void protoSignalComputation4( return; } + /*------------------------------------------------------------------------- * ivas_dirac_dec_compute_diffuse_proto() * @@ -3180,8 +3540,9 @@ static void protoSignalComputation4( *------------------------------------------------------------------------*/ static void ivas_dirac_dec_compute_diffuse_proto( - DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ - const int16_t slot_idx ) + DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ + const int16_t slot_idx /* i : slot index */ +) { int16_t k, l; int16_t num_freq_bands, num_freq_bands_diff; @@ -3189,7 +3550,6 @@ static void ivas_dirac_dec_compute_diffuse_proto( float *p_proto_diff, *p_power_smooth, *proto_frame_dec_f; DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; - int16_t m; float *p_hoa_enc; @@ -3301,6 +3661,7 @@ static void computeDirectionAngles( return; } + /*------------------------------------------------------------------------- * ivas_masa_init_stereotype_detection() * @@ -3463,6 +3824,7 @@ static void computeIntensityVector_dec( */ int16_t i; float real, img; + for ( i = 0; i < num_frequency_bands; ++i ) { real = Cldfb_RealBuffer[0][0][i]; @@ -3541,3 +3903,48 @@ static void ivas_lfe_synth_with_cldfb( return; } + + +/*------------------------------------------------------------------------- + * rotateAziEle_DirAC() + * + * Apply rotation to DirAC DOAs + *------------------------------------------------------------------------*/ + +static void rotateAziEle_DirAC( + int16_t *azi, /* i/o: array of azimuth values */ + int16_t *ele, /* i/o: array of elevation values */ + const int16_t band1, /* i : bands to work on (lower limit) */ + const int16_t band2, /* i : bands to work on (upper bound) */ + const float *p_Rmat /* i : pointer to real-space rotation matrix */ +) +{ + int16_t b; + float dv_0, dv_1, dv_2; + float dv_r_0, dv_r_1, dv_r_2; + float w; + + push_wmops( "rotateAziEle_DirAC" ); + + for ( b = band1; b < band2; b++ ) + { + + /*Conversion spherical to cartesian coordinates*/ + w = cosf( ele[b] * PI_OVER_180 ); + dv_0 = w * cosf( azi[b] * PI_OVER_180 ); + dv_1 = w * sinf( azi[b] * PI_OVER_180 ); + dv_2 = sinf( ele[b] * PI_OVER_180 ); + + dv_r_0 = p_Rmat[0] * dv_0 + p_Rmat[1] * dv_1 + p_Rmat[2] * dv_2; + dv_r_1 = p_Rmat[3] * dv_0 + p_Rmat[4] * dv_1 + p_Rmat[5] * dv_2; + dv_r_2 = p_Rmat[6] * dv_0 + p_Rmat[7] * dv_1 + p_Rmat[8] * dv_2; + + /*Conversion spherical to cartesian coordinates*/ + azi[b] = (int16_t) ( atan2f( dv_r_1, dv_r_0 ) * _180_OVER_PI ); + ele[b] = (int16_t) ( atan2f( dv_r_2, sqrtf( dv_r_0 * dv_r_0 + dv_r_1 * dv_r_1 ) ) * _180_OVER_PI ); + } + + pop_wmops(); + + return; +} diff --git a/lib_dec/ivas_dirac_decorr_dec.c b/lib_dec/ivas_dirac_decorr_dec.c index 437bdf8a647911cc20cd13b355e77dea657116b0..bcaa6cf2a13916ccb0b68bd275d0f243ba4df33d 100644 --- a/lib_dec/ivas_dirac_decorr_dec.c +++ b/lib_dec/ivas_dirac_decorr_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -70,10 +70,10 @@ static void lattice2allpass( const int16_t filter_length, const float *lattice_c /*------------------------------------------------------------------------- * ivas_dirac_dec_decorr_open() * - * + * Allocate and initialize TD decorrelator decoder handle *------------------------------------------------------------------------*/ -void ivas_dirac_dec_decorr_open( +ivas_error ivas_dirac_dec_decorr_open( DIRAC_DECORR_PARAMS **ph_freq_domain_decorr_ap_params, DIRAC_DECORR_STATE **ph_freq_domain_decorr_ap_state, const int16_t num_freq_bands, @@ -91,6 +91,7 @@ void ivas_dirac_dec_decorr_open( int16_t split_frequencies_bands[DIRAC_DECORR_NUM_SPLIT_BANDS + 1] = { 0, 0, 0, 23768 }; int16_t *split_freq_ptr; float cur_lattice_delta_phi, lattice_coeffs[2 * DIRAC_MAX_DECORR_FILTER_LEN]; + ivas_error error; /* pointers to structs for allocation */ DIRAC_DECORR_PARAMS *freq_domain_decorr_ap_params = NULL; @@ -101,8 +102,15 @@ void ivas_dirac_dec_decorr_open( *-----------------------------------------------------------------*/ /* allocate structs */ - freq_domain_decorr_ap_params = (DIRAC_DECORR_PARAMS *) count_malloc( sizeof( DIRAC_DECORR_PARAMS ) ); - freq_domain_decorr_ap_state = (DIRAC_DECORR_STATE *) count_malloc( sizeof( DIRAC_DECORR_STATE ) ); + if ( ( freq_domain_decorr_ap_params = (DIRAC_DECORR_PARAMS *) malloc( sizeof( DIRAC_DECORR_PARAMS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } + + if ( ( freq_domain_decorr_ap_state = (DIRAC_DECORR_STATE *) malloc( sizeof( DIRAC_DECORR_STATE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } /*-----------------------------------------------------------------* * check input parameters @@ -164,7 +172,6 @@ void ivas_dirac_dec_decorr_open( } } - /*-----------------------------------------------------------------* * open sub-modules *-----------------------------------------------------------------*/ @@ -173,21 +180,17 @@ void ivas_dirac_dec_decorr_open( if ( synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { /*Onset detector up to Nyquist and not only up to max_band_decorr*/ - ivas_dirac_dec_onset_detection_open( - num_protos_diff, - num_freq_bands, - num_freq_bands, - &freq_domain_decorr_ap_params->h_onset_detection_power_params, - &freq_domain_decorr_ap_state->h_onset_detection_power_state ); + if ( ( error = ivas_dirac_dec_onset_detection_open( num_protos_diff, num_freq_bands, num_freq_bands, &freq_domain_decorr_ap_params->h_onset_detection_power_params, &freq_domain_decorr_ap_state->h_onset_detection_power_state ) ) != IVAS_ERR_OK ) + { + return error; + } } else { - ivas_dirac_dec_onset_detection_open( - num_protos_diff, - num_freq_bands, - freq_domain_decorr_ap_params->max_band_decorr, - &freq_domain_decorr_ap_params->h_onset_detection_power_params, - &freq_domain_decorr_ap_state->h_onset_detection_power_state ); + if ( ( error = ivas_dirac_dec_onset_detection_open( num_protos_diff, num_freq_bands, freq_domain_decorr_ap_params->max_band_decorr, &freq_domain_decorr_ap_params->h_onset_detection_power_params, &freq_domain_decorr_ap_state->h_onset_detection_power_state ) ) != IVAS_ERR_OK ) + { + return error; + } } /*-----------------------------------------------------------------* @@ -215,7 +218,10 @@ void ivas_dirac_dec_decorr_open( } } - freq_domain_decorr_ap_params->split_frequency_bands = (int16_t *) count_malloc( sizeof( int16_t ) * ( freq_domain_decorr_ap_params->num_split_frequency_bands + 1 ) ); + if ( ( freq_domain_decorr_ap_params->split_frequency_bands = (int16_t *) malloc( sizeof( int16_t ) * ( freq_domain_decorr_ap_params->num_split_frequency_bands + 1 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } mvs2s( &split_frequencies_bands[0], freq_domain_decorr_ap_params->split_frequency_bands, freq_domain_decorr_ap_params->num_split_frequency_bands + 1 ); /* calc buffer size and allocate arrays */ @@ -232,18 +238,50 @@ void ivas_dirac_dec_decorr_open( if ( num_outputs_diff > 0 ) { buffer_size_decorr = ( ap_pre_delay[split_band_index_start] + ap_filter_length[split_band_index_start] ); - freq_domain_decorr_ap_state->decorr_buffer = (float *) count_malloc( sizeof( float ) * 2 * buffer_size_decorr * num_outputs_diff * freq_domain_decorr_ap_params->max_band_decorr ); + if ( ( freq_domain_decorr_ap_state->decorr_buffer = (float *) malloc( sizeof( float ) * 2 * buffer_size_decorr * num_outputs_diff * freq_domain_decorr_ap_params->max_band_decorr ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } set_f( freq_domain_decorr_ap_state->decorr_buffer, 0.0f, 2 * buffer_size_decorr * num_outputs_diff * freq_domain_decorr_ap_params->max_band_decorr ); - freq_domain_decorr_ap_params->filter_coeff_num_real = (float *) count_malloc( sizeof( float ) * ( ap_filter_length[split_band_index_start] + 1 ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); - freq_domain_decorr_ap_params->filter_coeff_den_real = (float *) count_malloc( sizeof( float ) * ( ap_filter_length[split_band_index_start] + 1 ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); - freq_domain_decorr_ap_params->phase_coeff_real = (float *) count_malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); - freq_domain_decorr_ap_params->phase_coeff_imag = (float *) count_malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); - freq_domain_decorr_ap_state->direct_energy_smooth = (float *) count_malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); - freq_domain_decorr_ap_state->reverb_energy_smooth = (float *) count_malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); + if ( ( freq_domain_decorr_ap_params->filter_coeff_num_real = (float *) malloc( sizeof( float ) * ( ap_filter_length[split_band_index_start] + 1 ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } - freq_domain_decorr_ap_params->pre_delay = (int16_t *) count_malloc( sizeof( int16_t ) * freq_domain_decorr_ap_params->num_split_frequency_bands ); - freq_domain_decorr_ap_params->filter_length = (int16_t *) count_malloc( sizeof( int16_t ) * freq_domain_decorr_ap_params->num_split_frequency_bands ); + if ( ( freq_domain_decorr_ap_params->filter_coeff_den_real = (float *) malloc( sizeof( float ) * ( ap_filter_length[split_band_index_start] + 1 ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } + + if ( ( freq_domain_decorr_ap_params->phase_coeff_real = (float *) malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } + + if ( ( freq_domain_decorr_ap_params->phase_coeff_imag = (float *) malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } + + if ( ( freq_domain_decorr_ap_state->direct_energy_smooth = (float *) malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } + + if ( ( freq_domain_decorr_ap_state->reverb_energy_smooth = (float *) malloc( sizeof( float ) * freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } + + if ( ( freq_domain_decorr_ap_params->pre_delay = (int16_t *) malloc( sizeof( int16_t ) * freq_domain_decorr_ap_params->num_split_frequency_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } + if ( ( freq_domain_decorr_ap_params->filter_length = (int16_t *) malloc( sizeof( int16_t ) * freq_domain_decorr_ap_params->num_split_frequency_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD decorrelator\n" ) ); + } set_f( freq_domain_decorr_ap_state->direct_energy_smooth, 0.0f, freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); set_f( freq_domain_decorr_ap_state->reverb_energy_smooth, 0.0f, freq_domain_decorr_ap_params->max_band_decorr * num_outputs_diff ); @@ -280,7 +318,7 @@ void ivas_dirac_dec_decorr_open( *ph_freq_domain_decorr_ap_params = freq_domain_decorr_ap_params; *ph_freq_domain_decorr_ap_state = freq_domain_decorr_ap_state; - return; + return IVAS_ERR_OK; } @@ -315,7 +353,7 @@ void ivas_dirac_dec_decorr_process( float *filter_coeff_num_real, *filter_coeff_den_real, *decorr_buffer_start_ptr, *decorr_buffer_ptr; float input_real, input_imag, filter_frame_imag, filter_frame_real; - wmops_sub_start( "dirac_decorr_process" ); + push_wmops( "dirac_decorr_process" ); /* check handles */ if ( h_freq_domain_decorr_ap_params == NULL || h_freq_domain_decorr_ap_state == NULL ) @@ -571,7 +609,7 @@ void ivas_dirac_dec_decorr_process( } /*end of decorrelator*/ - wmops_sub_end(); + pop_wmops(); return; } @@ -617,13 +655,13 @@ void ivas_dirac_dec_decorr_close( if ( dirac_onset_detection_state->onset_detector_1 != NULL ) { - count_free( dirac_onset_detection_state->onset_detector_1 ); + free( dirac_onset_detection_state->onset_detector_1 ); dirac_onset_detection_state->onset_detector_1 = NULL; } if ( dirac_onset_detection_state->onset_detector_2 != NULL ) { - count_free( dirac_onset_detection_state->onset_detector_2 ); + free( dirac_onset_detection_state->onset_detector_2 ); dirac_onset_detection_state->onset_detector_2 = NULL; } @@ -634,78 +672,78 @@ void ivas_dirac_dec_decorr_close( /* free decorrelation buffer */ if ( ( *ph_freq_domain_decorr_ap_state )->decorr_buffer != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_state )->decorr_buffer ); + free( ( *ph_freq_domain_decorr_ap_state )->decorr_buffer ); ( *ph_freq_domain_decorr_ap_state )->decorr_buffer = NULL; } /* free ducker smoothed direct energy buffer */ if ( ( *ph_freq_domain_decorr_ap_state )->direct_energy_smooth != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_state )->direct_energy_smooth ); + free( ( *ph_freq_domain_decorr_ap_state )->direct_energy_smooth ); ( *ph_freq_domain_decorr_ap_state )->direct_energy_smooth = NULL; } /* free ducker smoothed reverb energy buffer */ if ( ( *ph_freq_domain_decorr_ap_state )->reverb_energy_smooth != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_state )->reverb_energy_smooth ); + free( ( *ph_freq_domain_decorr_ap_state )->reverb_energy_smooth ); ( *ph_freq_domain_decorr_ap_state )->reverb_energy_smooth = NULL; } /* free pre-delay param buffer */ if ( ( *ph_freq_domain_decorr_ap_params )->pre_delay != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_params )->pre_delay ); + free( ( *ph_freq_domain_decorr_ap_params )->pre_delay ); ( *ph_freq_domain_decorr_ap_params )->pre_delay = NULL; } /* free filter length param buffer */ if ( ( *ph_freq_domain_decorr_ap_params )->filter_length != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_params )->filter_length ); + free( ( *ph_freq_domain_decorr_ap_params )->filter_length ); ( *ph_freq_domain_decorr_ap_params )->filter_length = NULL; } /* free filter coeff param buffers */ if ( ( *ph_freq_domain_decorr_ap_params )->filter_coeff_num_real != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_params )->filter_coeff_num_real ); + free( ( *ph_freq_domain_decorr_ap_params )->filter_coeff_num_real ); ( *ph_freq_domain_decorr_ap_params )->filter_coeff_num_real = NULL; } /* free pre-delay param buffer */ if ( ( *ph_freq_domain_decorr_ap_params )->filter_coeff_den_real != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_params )->filter_coeff_den_real ); + free( ( *ph_freq_domain_decorr_ap_params )->filter_coeff_den_real ); ( *ph_freq_domain_decorr_ap_params )->filter_coeff_den_real = NULL; } /* free pre-delay param buffer */ if ( ( *ph_freq_domain_decorr_ap_params )->phase_coeff_imag != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_params )->phase_coeff_imag ); + free( ( *ph_freq_domain_decorr_ap_params )->phase_coeff_imag ); ( *ph_freq_domain_decorr_ap_params )->phase_coeff_imag = NULL; } /* free pre-delay param buffer */ if ( ( *ph_freq_domain_decorr_ap_params )->phase_coeff_real != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_params )->phase_coeff_real ); + free( ( *ph_freq_domain_decorr_ap_params )->phase_coeff_real ); ( *ph_freq_domain_decorr_ap_params )->phase_coeff_real = NULL; } /* free pre-delay param buffer */ if ( ( *ph_freq_domain_decorr_ap_params )->split_frequency_bands != NULL ) { - count_free( ( *ph_freq_domain_decorr_ap_params )->split_frequency_bands ); + free( ( *ph_freq_domain_decorr_ap_params )->split_frequency_bands ); ( *ph_freq_domain_decorr_ap_params )->split_frequency_bands = NULL; } /* free pointers to state and parameter structs */ - count_free( *ph_freq_domain_decorr_ap_params ); + free( *ph_freq_domain_decorr_ap_params ); *ph_freq_domain_decorr_ap_params = NULL; - count_free( *ph_freq_domain_decorr_ap_state ); + free( *ph_freq_domain_decorr_ap_state ); *ph_freq_domain_decorr_ap_state = NULL; return; diff --git a/lib_dec/ivas_dirac_onsets_dec.c b/lib_dec/ivas_dirac_onsets_dec.c index 67209cc052d0b20cce4d9bebf58f5343217b90b2..c094b45ff68aa32a7770f677b3c61e70b763f127 100644 --- a/lib_dec/ivas_dirac_onsets_dec.c +++ b/lib_dec/ivas_dirac_onsets_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -51,7 +51,7 @@ * onset detection *------------------------------------------------------------------------*/ -void ivas_dirac_dec_onset_detection_open( +ivas_error ivas_dirac_dec_onset_detection_open( const int16_t num_protos_diff, const int16_t num_freq_bands, const int16_t max_band_decorr, @@ -69,14 +69,20 @@ void ivas_dirac_dec_onset_detection_open( dirac_onset_detection_params->max_band_decorr = max_band_decorr; /* memory allocation */ - dirac_onset_detection_state->onset_detector_1 = (float *) count_malloc( sizeof( float ) * num_protos_diff * dirac_onset_detection_params->max_band_decorr ); - dirac_onset_detection_state->onset_detector_2 = (float *) count_malloc( sizeof( float ) * num_protos_diff * dirac_onset_detection_params->max_band_decorr ); + if ( ( dirac_onset_detection_state->onset_detector_1 = (float *) malloc( sizeof( float ) * num_protos_diff * dirac_onset_detection_params->max_band_decorr ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for onset detection\n" ) ); + } + if ( ( dirac_onset_detection_state->onset_detector_2 = (float *) malloc( sizeof( float ) * num_protos_diff * dirac_onset_detection_params->max_band_decorr ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for onset detection\n" ) ); + } /* init to zero */ set_zero( dirac_onset_detection_state->onset_detector_1, num_protos_diff * dirac_onset_detection_params->max_band_decorr ); set_zero( dirac_onset_detection_state->onset_detector_2, num_protos_diff * dirac_onset_detection_params->max_band_decorr ); - return; + return IVAS_ERR_OK; } diff --git a/lib_dec/ivas_dirac_output_synthesis_cov.c b/lib_dec/ivas_dirac_output_synthesis_cov.c index decca3445234054923af2446157b98cd9329c2fc..a2fc9ee8210be12378d3175c808075fd88ebcd8d 100644 --- a/lib_dec/ivas_dirac_output_synthesis_cov.c +++ b/lib_dec/ivas_dirac_output_synthesis_cov.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -48,7 +48,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "rom_dec.h" @@ -58,7 +58,7 @@ * Sets up the state and parameters for the Covariance Synthesis *-------------------------------------------------------------------*/ -void ivas_dirac_dec_output_synthesis_cov_open( +ivas_error ivas_dirac_dec_output_synthesis_cov_open( DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params, /* i/o: handle for the covariance synthesis parameters */ DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state, /* i/o: hanlde for the covariance synthesis state */ const int16_t max_band_decorr, /* i : uppermost frequency band where decorrelation is applied */ @@ -80,15 +80,27 @@ void ivas_dirac_dec_output_synthesis_cov_open( /* buffer length and interpolator */ h_dirac_output_synthesis_params->alpha_synthesis = NULL; - h_dirac_output_synthesis_params->proto_matrix = (float *) count_malloc( nchan_out * nchan_in * sizeof( float ) ); + if ( ( h_dirac_output_synthesis_params->proto_matrix = (float *) malloc( nchan_out * nchan_in * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) ); + } /* cov buffers */ for ( idx = 0; idx < num_param_bands; idx++ ) { - h_dirac_output_synthesis_state->cx_old[idx] = (float *) count_malloc( nchan_in * nchan_in * sizeof( float ) ); - h_dirac_output_synthesis_state->cy_old[idx] = (float *) count_malloc( nchan_out * nchan_out * sizeof( float ) ); - h_dirac_output_synthesis_state->mixing_matrix_old[idx] = (float *) count_malloc( nchan_out * nchan_in * sizeof( float ) ); + if ( ( h_dirac_output_synthesis_state->cx_old[idx] = (float *) malloc( nchan_in * nchan_in * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) ); + } + if ( ( h_dirac_output_synthesis_state->cy_old[idx] = (float *) malloc( nchan_out * nchan_out * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) ); + } + if ( ( h_dirac_output_synthesis_state->mixing_matrix_old[idx] = (float *) malloc( nchan_out * nchan_in * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) ); + } set_zero( h_dirac_output_synthesis_state->cx_old[idx], nchan_in * nchan_in ); set_zero( h_dirac_output_synthesis_state->cy_old[idx], nchan_out * nchan_out ); set_zero( h_dirac_output_synthesis_state->mixing_matrix_old[idx], nchan_out * nchan_in ); @@ -101,7 +113,10 @@ void ivas_dirac_dec_output_synthesis_cov_open( } for ( idx = 0; idx < num_param_bands_residual; idx++ ) { - h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = (float *) count_malloc( nchan_out * nchan_out * sizeof( float ) ); + if ( ( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = (float *) malloc( nchan_out * nchan_out * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) ); + } set_zero( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx], nchan_out * nchan_out ); } for ( ; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) @@ -114,7 +129,11 @@ void ivas_dirac_dec_output_synthesis_cov_open( *-----------------------------------------------------------------*/ /* compute interpolator */ - h_dirac_output_synthesis_params->interpolator = (float *) count_malloc( interp_length * sizeof( float ) ); + if ( ( h_dirac_output_synthesis_params->interpolator = (float *) malloc( interp_length * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis covariance\n" ) ); + } + for ( idx = 1; idx <= interp_length; ++idx ) { h_dirac_output_synthesis_params->interpolator[idx - 1] = (float) idx / (float) interp_length; @@ -122,7 +141,7 @@ void ivas_dirac_dec_output_synthesis_cov_open( mvr2r( proto_matrix, h_dirac_output_synthesis_params->proto_matrix, nchan_in * nchan_out ); - return; + return IVAS_ERR_OK; } @@ -171,7 +190,6 @@ void ivas_dirac_dec_output_synthesis_cov_close( DIRAC_OUTPUT_SYNTHESIS_COV_STATE *h_dirac_output_synthesis_state /* i/o: handle for the covariance synthesis state */ ) { - int16_t idx; /*-----------------------------------------------------------------* @@ -181,21 +199,21 @@ void ivas_dirac_dec_output_synthesis_cov_close( /* free interpolator */ if ( h_dirac_output_synthesis_params->interpolator != NULL ) { - count_free( h_dirac_output_synthesis_params->interpolator ); + free( h_dirac_output_synthesis_params->interpolator ); h_dirac_output_synthesis_params->interpolator = NULL; } /* free alpha */ if ( h_dirac_output_synthesis_params->alpha_synthesis != NULL ) { - count_free( h_dirac_output_synthesis_params->alpha_synthesis ); + free( h_dirac_output_synthesis_params->alpha_synthesis ); h_dirac_output_synthesis_params->alpha_synthesis = NULL; } /* free proto_matrix */ if ( h_dirac_output_synthesis_params->proto_matrix != NULL ) { - count_free( h_dirac_output_synthesis_params->proto_matrix ); + free( h_dirac_output_synthesis_params->proto_matrix ); h_dirac_output_synthesis_params->proto_matrix = NULL; } @@ -204,25 +222,25 @@ void ivas_dirac_dec_output_synthesis_cov_close( { if ( h_dirac_output_synthesis_state->cx_old[idx] != NULL ) { - count_free( h_dirac_output_synthesis_state->cx_old[idx] ); + free( h_dirac_output_synthesis_state->cx_old[idx] ); h_dirac_output_synthesis_state->cx_old[idx] = NULL; } if ( h_dirac_output_synthesis_state->cy_old[idx] != NULL ) { - count_free( h_dirac_output_synthesis_state->cy_old[idx] ); + free( h_dirac_output_synthesis_state->cy_old[idx] ); h_dirac_output_synthesis_state->cy_old[idx] = NULL; } if ( h_dirac_output_synthesis_state->mixing_matrix_old[idx] != NULL ) { - count_free( h_dirac_output_synthesis_state->mixing_matrix_old[idx] ); + free( h_dirac_output_synthesis_state->mixing_matrix_old[idx] ); h_dirac_output_synthesis_state->mixing_matrix_old[idx] = NULL; } if ( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] != NULL ) { - count_free( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] ); + free( h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] ); h_dirac_output_synthesis_state->mixing_matrix_res_old[idx] = NULL; } } @@ -452,7 +470,7 @@ int16_t computeMixingMatrices( float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; - wmops_sub_start( "dirac_cov_mix_mat" ); + push_wmops( "dirac_cov_mix_mat" ); set_zero( svd_s_buffer, MAX_OUTPUT_CHANNELS ); for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) @@ -665,7 +683,7 @@ int16_t computeMixingMatrices( mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx ); } - wmops_sub_end(); + pop_wmops(); return out; } @@ -706,7 +724,7 @@ int16_t computeMixingMatricesResidual( float mat_mult_buffer2[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; - wmops_sub_start( "dirac_cov_mix_mat_r" ); + push_wmops( "dirac_cov_mix_mat_r" ); /*-----------------------------------------------------------------* * Decomposition of Cy @@ -864,7 +882,7 @@ int16_t computeMixingMatricesResidual( mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx ); - wmops_sub_end(); + pop_wmops(); return out; } @@ -910,7 +928,7 @@ int16_t computeMixingMatricesISM( float mat_mult_buffer3[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; int16_t nL, nC; - wmops_sub_start( "dirac_cov_mix_mat" ); + push_wmops( "dirac_cov_mix_mat" ); out = EXIT_SUCCESS; lengthCx = num_inputs; @@ -1047,7 +1065,7 @@ int16_t computeMixingMatricesISM( mvr2r( mat_mult_buffer3, mixing_matrix, lengthCy * lengthCx ); } - wmops_sub_end(); + pop_wmops(); return out; } diff --git a/lib_dec/ivas_dirac_output_synthesis_dec.c b/lib_dec/ivas_dirac_output_synthesis_dec.c index 09ef51d056e5b67548f6447a30d7635eb90072fa..d0dfe4a2948db84f50aaccd88515aab087df481f 100644 --- a/lib_dec/ivas_dirac_output_synthesis_dec.c +++ b/lib_dec/ivas_dirac_output_synthesis_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- * Local constants @@ -86,7 +86,7 @@ static void normalizePanningGains( float *direct_response, const int16_t num_cha * *------------------------------------------------------------------------*/ -void ivas_dirac_dec_output_synthesis_open( +ivas_error ivas_dirac_dec_output_synthesis_open( DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ RENDERER_TYPE renderer_type, /* i : renderer type */ const int16_t nchan_transport, /* i : number of transport channels*/ @@ -126,22 +126,34 @@ void ivas_dirac_dec_output_synthesis_open( dirac_output_synthesis_state->diffuse_responses_square = NULL; if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { - dirac_output_synthesis_state->diffuse_responses_square = (float *) count_malloc( 2 * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->diffuse_responses_square = (float *) malloc( 2 * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } else if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - dirac_output_synthesis_state->diffuse_responses_square = (float *) count_malloc( hDirAC->hOutSetup.nchan_out_woLFE * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->diffuse_responses_square = (float *) malloc( hDirAC->hOutSetup.nchan_out_woLFE * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } /* prototype power buffers */ dirac_output_synthesis_state->proto_power_smooth_prev = NULL; if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { - dirac_output_synthesis_state->proto_power_smooth_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_protos_dir * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->proto_power_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_protos_dir * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } if ( dirac_output_synthesis_params->max_band_decorr > 0 && ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) ) { - dirac_output_synthesis_state->proto_power_diff_smooth_prev = (float *) count_malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->hOutSetup.nchan_out_woLFE * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->proto_power_diff_smooth_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->hOutSetup.nchan_out_woLFE * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } else { @@ -149,41 +161,74 @@ void ivas_dirac_dec_output_synthesis_open( } /* buffer length and interpolator */ - dirac_output_synthesis_params->interpolator = (float *) count_malloc( hDirAC->subframe_nbslots * sizeof( float ) ); + if ( ( dirac_output_synthesis_params->interpolator = (float *) malloc( hDirAC->subframe_nbslots * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } /* target PSD buffers */ - dirac_output_synthesis_state->cy_cross_dir_smooth_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->cy_cross_dir_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { dirac_output_synthesis_state->cy_auto_dir_smooth_prev = NULL; - dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) count_malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } else { - dirac_output_synthesis_state->cy_auto_dir_smooth_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->cy_auto_dir_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) { - dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } else { - dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_diff * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->cy_auto_diff_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } } /* direct and diffuse gain buffers */ - dirac_output_synthesis_state->gains_dir_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->gains_dir_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } + if ( hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) { - dirac_output_synthesis_state->gains_diff_prev = (float *) count_malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } else if ( hDirAC->synthesisConf != DIRAC_SYNTHESIS_PSD_SHD && hDirAC->synthesisConf != DIRAC_SYNTHESIS_MONO ) { - dirac_output_synthesis_state->gains_diff_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_diff * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } else { - dirac_output_synthesis_state->gains_diff_prev = (float *) count_malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->gains_diff_prev = (float *) malloc( hDirAC->num_freq_bands * hDirAC->num_outputs_dir * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } } /*-----------------------------------------------------------------* @@ -194,15 +239,27 @@ void ivas_dirac_dec_output_synthesis_open( if ( !( renderer_type == RENDERER_BINAURAL_PARAMETRIC || renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) ) { computeAlphaSynthesis( temp_alpha_synthesis, DIRAC_AVG_LENGTH_SYNTH_MS, DIRAC_ALPHA_MAX, &dirac_output_synthesis_params->numAlphas, hDirAC->slot_size, hDirAC->num_freq_bands, hDirAC->frequency_axis, output_Fs ); - dirac_output_synthesis_params->alpha_synthesis = (float *) count_malloc( dirac_output_synthesis_params->numAlphas * sizeof( float ) ); + if ( ( dirac_output_synthesis_params->alpha_synthesis = (float *) malloc( dirac_output_synthesis_params->numAlphas * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } mvr2r( temp_alpha_synthesis, dirac_output_synthesis_params->alpha_synthesis, dirac_output_synthesis_params->numAlphas ); computeAlphaSynthesis( temp_alpha_synthesis, DIRAC_AVG_LENGTH_SYNTH_MS_FAST, DIRAC_ALPHA_MAX_FAST, &dirac_output_synthesis_params->numAlphasFast, hDirAC->slot_size, hDirAC->num_freq_bands, hDirAC->frequency_axis, output_Fs ); - dirac_output_synthesis_params->alpha_synthesis_fast = (float *) count_malloc( dirac_output_synthesis_params->numAlphasFast * sizeof( float ) ); + if ( ( dirac_output_synthesis_params->alpha_synthesis_fast = (float *) malloc( dirac_output_synthesis_params->numAlphasFast * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } mvr2r( temp_alpha_synthesis, dirac_output_synthesis_params->alpha_synthesis_fast, dirac_output_synthesis_params->numAlphasFast ); - dirac_output_synthesis_state->reference_power_smooth_prev = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); - dirac_output_synthesis_state->direction_smoothness_prev = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + if ( ( dirac_output_synthesis_state->reference_power_smooth_prev = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } + if ( ( dirac_output_synthesis_state->direction_smoothness_prev = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); + } set_zero( dirac_output_synthesis_state->reference_power_smooth_prev, hDirAC->num_freq_bands ); set_zero( dirac_output_synthesis_state->direction_smoothness_prev, hDirAC->num_freq_bands ); } @@ -276,7 +333,7 @@ void ivas_dirac_dec_output_synthesis_open( dirac_output_synthesis_params->diffuse_compensation_factor_decorr = 0.f; } - return; + return IVAS_ERR_OK; } @@ -367,79 +424,79 @@ void ivas_dirac_dec_output_synthesis_close( /* free interpolator */ if ( ( dirac_output_synthesis_params )->interpolator != NULL ) { - count_free( ( dirac_output_synthesis_params )->interpolator ); + free( ( dirac_output_synthesis_params )->interpolator ); ( dirac_output_synthesis_params )->interpolator = NULL; } /* free alpha */ if ( ( dirac_output_synthesis_params )->alpha_synthesis != NULL ) { - count_free( ( dirac_output_synthesis_params )->alpha_synthesis ); + free( ( dirac_output_synthesis_params )->alpha_synthesis ); ( dirac_output_synthesis_params )->alpha_synthesis = NULL; } if ( ( dirac_output_synthesis_params )->alpha_synthesis_fast != NULL ) { - count_free( ( dirac_output_synthesis_params )->alpha_synthesis_fast ); + free( ( dirac_output_synthesis_params )->alpha_synthesis_fast ); ( dirac_output_synthesis_params )->alpha_synthesis_fast = NULL; } if ( ( dirac_output_synthesis_state )->reference_power_smooth_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->reference_power_smooth_prev ); + free( ( dirac_output_synthesis_state )->reference_power_smooth_prev ); ( dirac_output_synthesis_state )->reference_power_smooth_prev = NULL; } if ( ( dirac_output_synthesis_state )->direction_smoothness_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->direction_smoothness_prev ); + free( ( dirac_output_synthesis_state )->direction_smoothness_prev ); ( dirac_output_synthesis_state )->direction_smoothness_prev = NULL; } if ( ( dirac_output_synthesis_state )->diffuse_responses_square != NULL ) { - count_free( ( dirac_output_synthesis_state )->diffuse_responses_square ); + free( ( dirac_output_synthesis_state )->diffuse_responses_square ); ( dirac_output_synthesis_state )->diffuse_responses_square = NULL; } /* free power buffers */ if ( ( dirac_output_synthesis_state )->proto_power_smooth_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->proto_power_smooth_prev ); + free( ( dirac_output_synthesis_state )->proto_power_smooth_prev ); ( dirac_output_synthesis_state )->proto_power_smooth_prev = NULL; } if ( ( dirac_output_synthesis_state )->proto_power_diff_smooth_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->proto_power_diff_smooth_prev ); + free( ( dirac_output_synthesis_state )->proto_power_diff_smooth_prev ); ( dirac_output_synthesis_state )->proto_power_diff_smooth_prev = NULL; } /* free target power buffers */ if ( ( dirac_output_synthesis_state )->cy_auto_dir_smooth_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->cy_auto_dir_smooth_prev ); + free( ( dirac_output_synthesis_state )->cy_auto_dir_smooth_prev ); ( dirac_output_synthesis_state )->cy_auto_dir_smooth_prev = NULL; } if ( ( dirac_output_synthesis_state )->cy_cross_dir_smooth_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->cy_cross_dir_smooth_prev ); + free( ( dirac_output_synthesis_state )->cy_cross_dir_smooth_prev ); ( dirac_output_synthesis_state )->cy_cross_dir_smooth_prev = NULL; } if ( ( dirac_output_synthesis_state )->cy_auto_diff_smooth_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->cy_auto_diff_smooth_prev ); + free( ( dirac_output_synthesis_state )->cy_auto_diff_smooth_prev ); ( dirac_output_synthesis_state )->cy_auto_diff_smooth_prev = NULL; } /* free gain buffers */ if ( ( dirac_output_synthesis_state )->gains_dir_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->gains_dir_prev ); + free( ( dirac_output_synthesis_state )->gains_dir_prev ); ( dirac_output_synthesis_state )->gains_dir_prev = NULL; } if ( ( dirac_output_synthesis_state )->gains_diff_prev != NULL ) { - count_free( ( dirac_output_synthesis_state )->gains_diff_prev ); + free( ( dirac_output_synthesis_state )->gains_diff_prev ); ( dirac_output_synthesis_state )->gains_diff_prev = NULL; } @@ -460,8 +517,12 @@ void ivas_dirac_dec_output_synthesis_process_slot( const float *p_Rmat, /* i : rotation matrix */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ - const int16_t nchan_transport, /* i : number of transport channels*/ - const int16_t index_slot ) + const int16_t nchan_transport /* i : number of transport channels*/ +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES + , + const int16_t index_slot +#endif +) { int16_t num_freq_bands, num_channels_dir; int16_t num_freq_bands_diff, num_channels_diff; @@ -499,8 +560,11 @@ void ivas_dirac_dec_output_synthesis_process_slot( ivas_dirac_dec_compute_directional_responses( hDirAC, hVBAPdata, NULL, +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES index_slot, - index_slot / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, + index_slot / MAX_PARAM_SPATIAL_SUBFRAMES, +#endif + NULL, 2, p_Rmat ); @@ -729,8 +793,8 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( g1 = 0.3679f + onset_filter[l] * ( 0.1175f - 0.3679f ); g2 = ( 1.f - g1 ) * *( p_gains_dir ); g2 += g1 * ( *( p_cy_cross_dir_smooth++ ) ); - g2 = max( g2, 0.5f ); - g2 = min( g2, 2.f ); + g2 = max( g2, 0.85f ); + g2 = min( g2, 1.15f ); *( p_gains_dir++ ) = g2; } } @@ -945,7 +1009,7 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( int16_t alphaMaxBin; int16_t alphaMaxBinFast; - wmops_sub_start( "dirac_out_synth_sfr" ); + push_wmops( "dirac_out_synth_sfr" ); h_dirac_output_synthesis_params = &( hDirAC->h_output_synthesis_psd_params ); h_dirac_output_synthesis_state = &( hDirAC->h_output_synthesis_psd_state ); @@ -1248,7 +1312,7 @@ void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( set_zero( h_dirac_output_synthesis_state->cy_cross_dir_smooth, num_freq_bands * nchan_out_woLFE ); set_zero( h_dirac_output_synthesis_state->cy_auto_diff_smooth, num_freq_bands * nchan_out_woLFE ); - wmops_sub_end(); + pop_wmops(); return; } @@ -1277,7 +1341,7 @@ static void ivas_dirac_dec_get_response_split_order( float dv_0, dv_1, dv_2, dv_r_0, dv_r_1, dv_r_2; float w; - wmops_sub_start( "ivas_dirac_dec_get_response_split_order" ); + push_wmops( "ivas_dirac_dec_get_response_split_order" ); index_azimuth = ( azimuth + 180 ) % 360; index_elevation = elevation + 90; @@ -1411,7 +1475,7 @@ static void ivas_dirac_dec_get_response_split_order( response[b] = c; } - wmops_sub_end(); + pop_wmops(); return; } @@ -1427,8 +1491,10 @@ void ivas_dirac_dec_compute_directional_responses( DIRAC_DEC_HANDLE hDirAC, /* i/o: DirAC handle */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ - const int16_t direction_idx, /* i : index for direction (azi and ele), can slot index (>2TCs) or subrame index (<=2TCs) */ - const int16_t subframe_idx, /* i : subframe index */ +#ifndef FIX_401_DIRAC_RENDERER_META_READ_INDICES + const int16_t direction_idx, /* i : index for direction (azi and ele), can slot index (>2TCs) or subrame index (<=2TCs) */ + const int16_t subframe_idx, /* i : subframe index */ +#endif const float *surCohRatio, const int16_t shd_rot_max_order, /* i : split-order rotation method */ const float *p_Rmat /* i : rotation matrix */ @@ -1465,8 +1531,8 @@ void ivas_dirac_dec_compute_directional_responses( elevation = hDirAC->elevation[hDirAC->dirac_read_idx]; if ( hDirAC->numSimultaneousDirections == 2 ) { - azimuth2 = hDirAC->azimuth2[direction_idx]; - elevation2 = hDirAC->elevation2[direction_idx]; + azimuth2 = hDirAC->azimuth2[hDirAC->dirac_read_idx]; + elevation2 = hDirAC->elevation2[hDirAC->dirac_read_idx]; } codingBand = -1; @@ -1518,17 +1584,32 @@ void ivas_dirac_dec_compute_directional_responses( hDirAC->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirAC->synthesisConf == DIRAC_SYNTHESIS_MONO ) { /* Synthesize the first direction */ +#ifdef FIX_401_DIRAC_RENDERER_META_READ_INDICES + spreadCoherencePanningHoa( azimuth[k], elevation[k], hDirAC->spreadCoherence[hDirAC->dirac_read_idx][k], direct_response_hoa, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); +#else spreadCoherencePanningHoa( azimuth[k], elevation[k], hDirAC->spreadCoherence[subframe_idx][k], direct_response_hoa, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); +#endif /* Synthesize the second direction and combine the gains */ if ( hDirAC->numSimultaneousDirections == 2 ) { +#ifdef FIX_401_DIRAC_RENDERER_META_READ_INDICES + spreadCoherencePanningHoa( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[hDirAC->dirac_read_idx][k], direct_response_dir2, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); +#else spreadCoherencePanningHoa( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[subframe_idx][k], direct_response_dir2, num_channels_dir, hDirAC->hOutSetup.ambisonics_order ); +#endif /* Combine gains from the two directions */ +#ifdef FIX_401_DIRAC_RENDERER_META_READ_INDICES + totalDirect = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] + hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] + EPSILON; + directRatio[0] = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] / totalDirect; + directRatio[1] = hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] / totalDirect; +#else totalDirect = hDirAC->energy_ratio1[subframe_idx][k] + hDirAC->energy_ratio2[subframe_idx][k] + EPSILON; directRatio[0] = hDirAC->energy_ratio1[subframe_idx][k] / totalDirect; directRatio[1] = hDirAC->energy_ratio2[subframe_idx][k] / totalDirect; +#endif + for ( l = 0; l < num_channels_dir; l++ ) { direct_response_hoa[l] *= directRatio[0]; @@ -1576,20 +1657,34 @@ void ivas_dirac_dec_compute_directional_responses( else if ( hDirAC->panningConf == DIRAC_PANNING_VBAP ) /*VBAP*/ { /* Synthesize the first direction */ +#ifdef FIX_401_DIRAC_RENDERER_META_READ_INDICES + spreadCoherencePanningVbap( azimuth[k], elevation[k], hDirAC->spreadCoherence[hDirAC->dirac_read_idx][k], direct_response_ls, num_channels_dir, hVBAPdata ); +#else spreadCoherencePanningVbap( azimuth[k], elevation[k], hDirAC->spreadCoherence[subframe_idx][k], direct_response_ls, num_channels_dir, hVBAPdata ); +#endif normalizePanningGains( direct_response_ls, num_channels_dir ); /* Synthesize the second direction and combine the gains */ if ( hDirAC->numSimultaneousDirections == 2 ) { +#ifdef FIX_401_DIRAC_RENDERER_META_READ_INDICES + spreadCoherencePanningVbap( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[hDirAC->dirac_read_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata ); +#else spreadCoherencePanningVbap( azimuth2[k], elevation2[k], hDirAC->spreadCoherence2[subframe_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata ); +#endif normalizePanningGains( direct_response_dir2, num_channels_dir ); /* Combine gains from the two directions */ +#ifdef FIX_401_DIRAC_RENDERER_META_READ_INDICES + totalDirect = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] + hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] + EPSILON; + directRatio[0] = hDirAC->energy_ratio1[hDirAC->dirac_read_idx][k] / totalDirect; + directRatio[1] = hDirAC->energy_ratio2[hDirAC->dirac_read_idx][k] / totalDirect; +#else totalDirect = hDirAC->energy_ratio1[subframe_idx][k] + hDirAC->energy_ratio2[subframe_idx][k] + EPSILON; directRatio[0] = hDirAC->energy_ratio1[subframe_idx][k] / totalDirect; directRatio[1] = hDirAC->energy_ratio2[subframe_idx][k] / totalDirect; +#endif for ( l = 0; l < num_channels_dir; l++ ) { direct_response_ls[l] *= directRatio[0]; @@ -2078,7 +2173,8 @@ static void spreadCoherencePanningVbap( if ( hVBAPdata == NULL ) { /* Distribute signal to all channels if VBAP is not properly initialized. */ - set_f( direct_response, 1.0f / sqrtf( num_channels_dir ), num_channels_dir ); + set_f( direct_response, inv_sqrt( num_channels_dir ), num_channels_dir ); + return; } diff --git a/lib_dec/ivas_entropy_decoder.c b/lib_dec/ivas_entropy_decoder.c index 52eadafc2a44e9ae3a5e062b2635cd1a26b5d543..2f8e9bc3bf5d31c0742fd91cd9d9e5eff04062ff 100644 --- a/lib_dec/ivas_entropy_decoder.c +++ b/lib_dec/ivas_entropy_decoder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #endif #include "ivas_rom_com.h" #include -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -50,50 +50,6 @@ static int16_t ivas_huffman_code_bits_present( const int16_t *codebook, const int16_t code, const int16_t bits, const int16_t len ); -/*-----------------------------------------------------------------------------------------* - * Function ivas_arith_dec_init() - * - * arith decoder init - *-----------------------------------------------------------------------------------------*/ - -static void ivas_arith_dec_init( - ivas_arith_t *pArith, - const ivas_freq_models_t *pFreq_models, - ivas_arith_t *pArith_diff, - const int16_t q_levels ) -{ - int16_t i; - - pArith->vals = pFreq_models->vals; - pArith->range = q_levels; - pArith->num_models = pFreq_models->num_models; - pArith->dyn_model_bits = ivas_get_bits_to_encode( pArith->num_models - 1 ); - pArith->pFreq_model = pFreq_models->freq_model[0]; - ivas_get_cum_freq_model( pArith->pFreq_model, pArith->range, pArith->cum_freq[0] ); - - for ( i = 0; i < pArith->num_models - 1; i++ ) - { - pArith->pAlt_freq_models[i] = pFreq_models->freq_model[i + 1]; - ivas_get_cum_freq_model( pArith->pAlt_freq_models[i], pArith->range, pArith->cum_freq[i + 1] ); - } - - pArith_diff->vals = pFreq_models->diff_vals; - pArith_diff->range = q_levels; - pArith_diff->num_models = pFreq_models->diff_num_models; - pArith_diff->dyn_model_bits = ivas_get_bits_to_encode( pArith_diff->num_models - 1 ); - pArith_diff->pFreq_model = pFreq_models->diff_freq_model[0]; - ivas_get_cum_freq_model( pArith_diff->pFreq_model, pArith_diff->range, pArith_diff->cum_freq[0] ); - - for ( i = 0; i < pArith_diff->num_models - 1; i++ ) - { - pArith_diff->pAlt_freq_models[i] = pFreq_models->diff_freq_model[i + 1]; - ivas_get_cum_freq_model( pArith_diff->pAlt_freq_models[i], pArith_diff->range, pArith_diff->cum_freq[i + 1] ); - } - - return; -} - - /*-----------------------------------------------------------------------------------------* * Function ivas_arith_decode_array() * @@ -192,40 +148,6 @@ static void ivas_arithCoder_decode_array_diff( } -/*-----------------------------------------------------------------------------------------* - * Function ivas_huffman_dec_init_min_max_len() - * - * Find min and max length in codebook and finalize initialization of ivas_huffman_cfg_t. - *-----------------------------------------------------------------------------------------*/ -static void ivas_huffman_dec_init_min_max_len( - ivas_huffman_cfg_t *p_huff_cfg ) -{ - int16_t i, code_len; - const int16_t *codebook; - - codebook = p_huff_cfg->codebook; - - p_huff_cfg->min_len = p_huff_cfg->sym_len; - p_huff_cfg->max_len = 0; - - for ( i = 0; i < p_huff_cfg->sym_len; i++ ) - { - code_len = codebook[1]; - if ( p_huff_cfg->min_len > code_len ) - { - p_huff_cfg->min_len = code_len; - } - if ( p_huff_cfg->max_len < code_len ) - { - p_huff_cfg->max_len = code_len; - } - codebook = codebook + 3; - } - - return; -} - - /*-----------------------------------------------------------------------------------------* * Function ivas_huffman_code_bits_present() * @@ -494,67 +416,3 @@ void ivas_arith_decode_cmplx_cell_array( return; } - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_arith_coeffs_dec_init() - * - * Init for Arith. decoding - *-----------------------------------------------------------------------------------------*/ - -void ivas_arith_coeffs_dec_init( - ivas_arith_coeffs_t *pArith_coeffs, - ivas_spar_foa_md_com_cfg *pSpar_cfg, - const int16_t table_idx ) -{ - int16_t i; - for ( i = 0; i < MAX_QUANT_STRATS; i++ ) - { - - ivas_arith_dec_init( &pArith_coeffs->pred_arith_re[i], &ivas_arith_consts[table_idx][i].pred_r, - &pArith_coeffs->pred_arith_re_diff[i], pSpar_cfg->quant_strat[i].PR.q_levels[0] ); - - ivas_arith_dec_init( &pArith_coeffs->drct_arith_re[i], &ivas_arith_consts[table_idx][i].drct_r, - &pArith_coeffs->drct_arith_re_diff[i], pSpar_cfg->quant_strat[i].C.q_levels[0] ); - - ivas_arith_dec_init( &pArith_coeffs->decd_arith_re[i], &ivas_arith_consts[table_idx][i].decd_r, - &pArith_coeffs->decd_arith_re_diff[i], pSpar_cfg->quant_strat[i].P_r.q_levels[0] ); - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_huff_coeffs_dec_init() - * - * Init for Huffman decoding - *-----------------------------------------------------------------------------------------*/ - -void ivas_huff_coeffs_dec_init( - ivas_huff_coeffs_t *pHuff_coeffs, - ivas_spar_foa_md_com_cfg *pSpar_cfg, - const int16_t table_idx ) -{ - int16_t i; - ivas_huffman_cfg_t *p_huff_cfg; - for ( i = 0; i < MAX_QUANT_STRATS; i++ ) - { - p_huff_cfg = &pHuff_coeffs->pred_huff_re[i]; - p_huff_cfg->codebook = &ivas_huff_const[table_idx][i].pred_r.code_book[0][0]; - p_huff_cfg->sym_len = pSpar_cfg->quant_strat[i].PR.q_levels[0]; - ivas_huffman_dec_init_min_max_len( p_huff_cfg ); - - p_huff_cfg = &pHuff_coeffs->drct_huff_re[i]; - p_huff_cfg->codebook = &ivas_huff_const[table_idx][i].drct_r.code_book[0][0]; - p_huff_cfg->sym_len = pSpar_cfg->quant_strat[i].C.q_levels[0]; - ivas_huffman_dec_init_min_max_len( p_huff_cfg ); - - p_huff_cfg = &pHuff_coeffs->decd_huff_re[i]; - p_huff_cfg->codebook = &ivas_huff_const[table_idx][i].decd_r.code_book[0][0]; - p_huff_cfg->sym_len = pSpar_cfg->quant_strat[i].P_r.q_levels[0]; - ivas_huffman_dec_init_min_max_len( p_huff_cfg ); - } - - return; -} diff --git a/lib_dec/ivas_hrtf.c b/lib_dec/ivas_hrtf.c deleted file mode 100644 index eebe3b037f1a86f6ed7378b3e8cc3c09db8e55f1..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_hrtf.c +++ /dev/null @@ -1,261 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include "hrtf_file_reader.h" -#include "prot.h" -#include "ivas_prot.h" -#include "lib_dec.h" -#include "string.h" -#include "assert.h" -#include "ivas_rom_TdBinauralRenderer.h" -#include "ivas_error.h" -#include "wmops.h" - - -/*-------------------------------------------------------------------* - * Local constants - *-------------------------------------------------------------------*/ - -#define RESAMPLE_FACTOR_16_48 ( 16.0f / 48.0f ) -#define RESAMPLE_FACTOR_32_48 ( 32.0f / 48.0f ) - - -/*-------------------------------------------------------------------* - * BSplineModelEvalAlloc() - * - * Allocate the B Spline HR Filter model. - --------------------------------------------------------------------*/ - -void BSplineModelEvalAlloc( - ModelParams_t *model, /* i : Model parameters */ - ModelEval_t *modelEval /* i/o: Model evaluation structure */ -) -{ - modelEval->hrfModL = (float *) count_malloc( model->K * sizeof( float ) ); - modelEval->hrfModR = (float *) count_malloc( model->K * sizeof( float ) ); - - return; -} - - -/*-------------------------------------------------------------------* - * DefaultBSplineModel() - * - * Init default HRTF model - --------------------------------------------------------------------*/ - -ivas_error DefaultBSplineModel( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* o : Loaded HR filter set */ - const int32_t output_Fs /* i : Output sampling rate */ -) -{ - ModelParams_t *model; - ModelParamsITD_t *modelITD; - int16_t i, j; - - HrFiltSet_p->FilterMethod = TDREND_HRFILT_Method_BSplineModel; - model = &( HrFiltSet_p->ModelParams ); - modelITD = &( HrFiltSet_p->ModelParamsITD ); - - /* Set ROM flag for correct deallocation */ - model->modelROM = TRUE; - - /* int16_t parameters */ - model->UseItdModel = 1; - model->SplineDegree = 4; - model->elevDim2 = 20; - model->elevDim3 = 18; - model->AlphaN = 578; - model->num_unique_azim_splines = 1; - model->elevSegSamples = 3; - model->elevBsLen[0] = 4; - model->elevBsLen[1] = 7; - model->elevBsLen[2] = 10; - model->elevBsLen[3] = 7; - model->elevBsStart[0] = 0; - model->elevBsStart[1] = 4; - model->elevBsStart[2] = 11; - model->elevBsStart[3] = 21; - - model->azimDim2 = orange53_rom_azimDim2; - model->azimDim3 = orange53_rom_azimDim3; - model->azim_start_idx = orange53_rom_azim_start_idx; - model->azimSegSamples = orange53_rom_azimSegSamples; - model->azimShapeIdx = orange53_rom_azimShapeIdx; - model->azimShapeSampFactor = orange53_rom_azimShapeSampFactor; - - /* float parameters */ - model->elevKSeq = (const float *) orange53_rom_elevKSeq; - model->elevBsShape = (const float *) orange53_rom_elevBsShape; - - model->azimBsShape = (const float **) count_malloc( model->num_unique_azim_splines * sizeof( float * ) ); - model->azimBsShape[0] = (const float *) orange53_rom_azimBsShape; - model->azimKSeq = (float **) count_malloc( 18 * sizeof( float * ) ); - model->azimKSeq[0] = (float *) count_malloc( 2 * sizeof( float * ) ); - model->azimKSeq[17] = (float *) count_malloc( 2 * sizeof( float * ) ); - model->azimKSeq[0][0] = 0.0f; - model->azimKSeq[17][0] = 0.0f; - model->azimKSeq[0][1] = 360.0f; - model->azimKSeq[17][1] = 360.0f; - - for ( i = 1; i < 17; i++ ) - { - model->azimKSeq[i] = (float *) count_malloc( model->azimDim2[i] * sizeof( float * ) ); /* azimDim2[i] = 91, i=2..15 */ - for ( j = 0; j < model->azimDim2[i]; j++ ) - { - model->azimKSeq[i][j] = (float) orange53_rom_azimSegSamples[0] * j; - } - } - - switch ( output_Fs ) - { - case 48000: - model->AlphaL = (const float *) orange53_rom_AlphaL48; - model->AlphaR = (const float *) orange53_rom_AlphaR48; - model->EL = (const float *) orange53_rom_EL48; - model->ER = (const float *) orange53_rom_ER48; - model->K = 128; - if ( HrFiltSet_p->ModelParams.UseItdModel ) - { - modelITD->resamp_factor = 1.0f; - } - break; - case 32000: - model->AlphaL = (const float *) orange53_rom_AlphaL32; - model->AlphaR = (const float *) orange53_rom_AlphaR32; - model->EL = (const float *) orange53_rom_EL32; - model->ER = (const float *) orange53_rom_ER32; - model->K = 86; - if ( HrFiltSet_p->ModelParams.UseItdModel ) - { - modelITD->resamp_factor = RESAMPLE_FACTOR_32_48; - } - break; - case 16000: - model->AlphaL = (const float *) orange53_rom_AlphaL16; - model->AlphaR = (const float *) orange53_rom_AlphaR16; - model->EL = (const float *) orange53_rom_EL16; - model->ER = (const float *) orange53_rom_ER16; - model->K = 43; - if ( HrFiltSet_p->ModelParams.UseItdModel ) - { - modelITD->resamp_factor = RESAMPLE_FACTOR_16_48; - } - break; - default: - break; - } - - modelITD->N = 4; - modelITD->elevDim2 = 20; - modelITD->elevDim3 = 18; - modelITD->azimDim2 = 41; - modelITD->azimDim3 = 41; - modelITD->elevSegSamples = 3; - modelITD->elevBsLen[0] = 4; - modelITD->elevBsLen[1] = 7; - modelITD->elevBsLen[2] = 10; - modelITD->elevBsLen[3] = 7; - modelITD->elevBsStart[0] = 0; - modelITD->elevBsStart[1] = 4; - modelITD->elevBsStart[2] = 11; - modelITD->elevBsStart[3] = 21; - - modelITD->elevKSeq = model->elevKSeq; - - modelITD->azimBsLen[0] = 11; - modelITD->azimBsLen[1] = 21; - modelITD->azimBsLen[2] = 31; - modelITD->azimBsLen[3] = 21; - modelITD->azimBsStart[0] = 0; - modelITD->azimBsStart[1] = 11; - modelITD->azimBsStart[2] = 32; - modelITD->azimBsStart[3] = 63; - - modelITD->azimSegSamples = 10; - - modelITD->azimKSeq = orange53_rom_ITD_azimKSeq; - modelITD->W = (const float *) orange53_rom_ITD_W; - modelITD->azimBsShape = (const float *) orange53_rom_ITD_azimBsShape; - modelITD->elevBsShape = (const float *) orange53_rom_ITD_elevBsShape; - - HRTF_model_precalc( model ); - - HrFiltSet_p->SampleRate = output_Fs; - HrFiltSet_p->FiltLength = HrFiltSet_p->ModelParams.K; - BSplineModelEvalAlloc( &HrFiltSet_p->ModelParams, &HrFiltSet_p->ModelEval ); - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------* - * ivas_HRTF_binary_open() - * - * Allocate HRTF binary handle - *-----------------------------------------------------------------------*/ - -ivas_error ivas_HRTF_binary_open( - TDREND_HRFILT_FiltSet_t **hHrtfTD ) -{ - /* Allocate HR filter set for headphones configuration */ - *hHrtfTD = (TDREND_HRFILT_FiltSet_t *) count_malloc( sizeof( TDREND_HRFILT_FiltSet_t ) ); - if ( *hHrtfTD == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF binary!" ); - } - - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * ivas_HRTF_binary_close() - * - * Close HRTF binary handle - *-------------------------------------------------------------------*/ - -void ivas_HRTF_binary_close( - TDREND_HRFILT_FiltSet_t **hHrtfTD ) -{ - if ( hHrtfTD == NULL || *hHrtfTD == NULL ) - { - return; - } - - count_free( *hHrtfTD ); - *hHrtfTD = NULL; - - return; -} diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 72372691062f163ad7a9289253a2f77624f529be..7e05a875dc51d5dff7bb48d798aca54bd2d1741c 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,9 +33,9 @@ #include "options.h" #include "ivas_cnst.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_rom_com.h" #include "ivas_stat_enc.h" -#include "lib_dec.h" #include "prot.h" #include #include @@ -43,7 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -51,6 +51,7 @@ *-------------------------------------------------------------------*/ static ivas_error ivas_read_format( Decoder_Struct *st_ivas, int16_t *num_bits_read ); + static ivas_error doSanityChecks_IVAS( Decoder_Struct *st_ivas ); @@ -65,11 +66,10 @@ ivas_error ivas_dec_setup( ) { int16_t k, idx, num_bits_read; - int16_t num_obj, element_mode_flag; + int16_t nchan_ism, element_mode_flag; Decoder_State *st; int32_t ivas_total_brate; ivas_error error; - error = IVAS_ERR_OK; num_bits_read = 0; @@ -87,7 +87,7 @@ ivas_error ivas_dec_setup( if ( is_DTXrate( ivas_total_brate ) == 0 ) { /*-------------------------------------------------------------------* - * Read IVAS format related signalling: + * Read IVAS format related signaling: * - in ISM : read number of objects * - in SBA : read SBA planar flag and SBA order * - in MASA : read number of TC @@ -102,36 +102,50 @@ ivas_error ivas_dec_setup( { /* read the number of objects */ st_ivas->nchan_transport = 1; - num_obj = 1; + nchan_ism = 1; k = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC ) - 1 ); - while ( st_ivas->bit_stream[k] && num_obj < MAX_NUM_OBJECTS ) + while ( st_ivas->bit_stream[k] && nchan_ism < MAX_NUM_OBJECTS ) { - num_obj++; + nchan_ism++; k--; } - ivas_ism_dec_config( st_ivas, num_obj ); +#ifdef NCHAN_ISM_PARAMETER + st_ivas->nchan_ism = nchan_ism; +#endif + +#ifdef DISCRETE_ISM_DTX_CNG +#ifdef NCHAN_ISM_PARAMETER + if ( ( error = ivas_ism_dec_config( st_ivas, st_ivas->ism_mode ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_dec_config( st_ivas, st_ivas->ism_mode, nchan_ism ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } +#else +#ifdef NCHAN_ISM_PARAMETER + ivas_ism_dec_config( st_ivas ); +#else + ivas_ism_dec_config( st_ivas, nchan_ism ); +#endif +#endif } else if ( st_ivas->ivas_format == SBA_FORMAT ) { - if ( st_ivas->sba_mode == SBA_MODE_DIRAC || ivas_total_brate >= IVAS_256k ) - { - /* read Ambisonic (SBA) planar flag */ - st_ivas->sba_planar = st_ivas->bit_stream[num_bits_read]; - num_bits_read += SBA_PLANAR_BITS; + /* read Ambisonic (SBA) planar flag */ + st_ivas->sba_planar = st_ivas->bit_stream[num_bits_read]; + num_bits_read += SBA_PLANAR_BITS; - /* read Ambisonic (SBA) order */ - st_ivas->sba_order = st_ivas->bit_stream[num_bits_read + 1]; - st_ivas->sba_order += 2 * st_ivas->bit_stream[num_bits_read]; - num_bits_read += SBA_ORDER_BITS; - } - else - { - st_ivas->sba_planar = 0; - st_ivas->sba_order = 1; - } + /* read Ambisonic (SBA) order */ + st_ivas->sba_order = st_ivas->bit_stream[num_bits_read + 1]; + st_ivas->sba_order += 2 * st_ivas->bit_stream[num_bits_read]; + + /* set Ambisonic (SBA) order used for analysis and coding */ + st_ivas->sba_analysis_order = ivas_sba_get_analysis_order( ivas_total_brate, st_ivas->sba_order ); - if ( st_ivas->ini_frame > 0 && ( ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) && ( ivas_total_brate > IVAS_SID_4k4 ) ) + num_bits_read += SBA_ORDER_BITS; + if ( st_ivas->ini_frame > 0 && ivas_total_brate != st_ivas->last_active_ivas_total_brate && ivas_total_brate > IVAS_SID_5k2 ) { if ( ( error = ivas_sba_dec_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) { @@ -140,7 +154,7 @@ ivas_error ivas_dec_setup( } else { - ivas_sba_config( ivas_total_brate, st_ivas->sba_order, -1, &( st_ivas->nchan_transport ), st_ivas->sba_planar, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, st_ivas->sba_mode ); + ivas_sba_config( ivas_total_brate, st_ivas->sba_analysis_order, -1, &( st_ivas->nchan_transport ), st_ivas->sba_planar, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init ); } } else if ( st_ivas->ivas_format == MASA_FORMAT ) @@ -159,7 +173,7 @@ ivas_error ivas_dec_setup( if ( st_ivas->ini_frame > 0 ) { /* reconfigure in case a change of operation mode is detected */ - if ( ( ivas_total_brate > IVAS_SID_4k4 && ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) || ( st_ivas->ini_active_frame == 0 ) ) + if ( ( ivas_total_brate > IVAS_SID_5k2 && ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) || ( st_ivas->ini_active_frame == 0 ) ) { if ( st_ivas->ini_active_frame == 0 && ivas_total_brate != FRAME_NO_DATA && ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->nCPE == 1 ) { @@ -218,7 +232,7 @@ ivas_error ivas_dec_setup( } } } - else if ( ivas_total_brate == IVAS_SID_4k4 || ivas_total_brate == IVAS_SID_5k ) + else if ( ivas_total_brate == IVAS_SID_5k2 ) { switch ( st_ivas->sid_format ) { @@ -228,6 +242,11 @@ ivas_error ivas_dec_setup( case SID_MDCT_STEREO: st_ivas->element_mode_init = IVAS_CPE_MDCT; break; +#ifdef DISCRETE_ISM_DTX_CNG + case SID_ISM: + st_ivas->element_mode_init = IVAS_SCE; + break; +#endif case SID_MASA_1TC: st_ivas->element_mode_init = IVAS_SCE; st_ivas->nchan_transport = 1; @@ -250,6 +269,42 @@ ivas_error ivas_dec_setup( st_ivas->element_mode_init = IVAS_CPE_MDCT; break; } + + if ( st_ivas->ini_frame > 0 && st_ivas->ivas_format == SBA_FORMAT ) + { + int16_t nchan_transport_old, nchan_transport; + SBA_MODE sba_mode_old; + int32_t last_ivas_total_brate; + + last_ivas_total_brate = st_ivas->last_active_ivas_total_brate; +#ifndef LBR_SBA + sba_mode_old = ivas_sba_mode_select( last_ivas_total_brate ); +#else + sba_mode_old = ivas_sba_mode_select( ); +#endif + nchan_transport_old = st_ivas->nchan_transport; + nchan_transport = ( st_ivas->sid_format == SID_SBA_2TC ) ? 2 : 1; + + if ( ( nchan_transport_old != nchan_transport ) || ( sba_mode_old != st_ivas->sba_mode ) ) + { + /*Setting the default bitrate for the reconfig function*/ + if ( st_ivas->sid_format == SID_SBA_2TC ) + { + st_ivas->hDecoderConfig->ivas_total_brate = IVAS_48k; + } + else + { + st_ivas->hDecoderConfig->ivas_total_brate = ( st_ivas->sba_mode == SBA_MODE_SPAR ) ? IVAS_24k4 : IVAS_13k2; + } + + if ( ( error = ivas_sba_dec_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + st_ivas->last_active_ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + st_ivas->hDecoderConfig->ivas_total_brate = ivas_total_brate; + } + } } /*-------------------------------------------------------------------* @@ -261,7 +316,7 @@ ivas_error ivas_dec_setup( { if ( ( error = doSanityChecks_IVAS( st_ivas ) ) != IVAS_ERR_OK ) { - return IVAS_ERROR( error, "Sanitiy checks failed" ); + return IVAS_ERROR( error, "Sanity checks failed" ); } if ( ( error = ivas_init_decoder( st_ivas ) ) != IVAS_ERR_OK ) @@ -285,6 +340,7 @@ ivas_error ivas_dec_setup( st->next_bit_pos = num_bits_read; st->total_brate = ACELP_8k00; /* only temporary initialization - this is needed for get_next_indice() in the frame following NO_DATA frame */ } + return error; } @@ -297,7 +353,7 @@ ivas_error ivas_dec_setup( static ivas_error ivas_read_format( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - int16_t *num_bits_read /* o : number of IVAS signalling bits read from the bitstream */ + int16_t *num_bits_read /* o : number of IVAS signaling bits read from the bitstream */ ) { int16_t k, idx; @@ -347,14 +403,17 @@ static ivas_error ivas_read_format( else { st_ivas->ivas_format = SBA_FORMAT; - +#ifndef LBR_SBA st_ivas->sba_mode = ivas_sba_mode_select( ivas_total_brate ); +#else + st_ivas->sba_mode = ivas_sba_mode_select( ); +#endif } ( *num_bits_read )++; break; } } - else if ( !st_ivas->bfi && ivas_total_brate == IVAS_SID_4k4 ) + else if ( !st_ivas->bfi && ivas_total_brate == IVAS_SID_5k2 ) { /* read IVAS format in SID frame */ idx = 0; @@ -374,7 +433,27 @@ static ivas_error ivas_read_format( break; case SID_ISM: st_ivas->ivas_format = ISM_FORMAT; - ivas_ism_dec_config( st_ivas, 1 ); /* currently DTX supported for 1ISM only */ +#ifndef DISCRETE_ISM_DTX_CNG + if ( st_ivas->ism_mode == ISM_MODE_DISC ) + { + ivas_ism_dec_config( st_ivas +#ifndef NCHAN_ISM_PARAMETER + , + 1 +#endif + ); /* currently DTX supported for 1 ISM when ISM Mode is DISC_ISM */ + } + + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + ivas_ism_dec_config( st_ivas +#ifndef NCHAN_ISM_PARAMETER + , + st_ivas->nSCE +#endif + ); /* for Param-ISM, we need to generate 2 TCs */ + } +#endif break; case SID_MULTICHANNEL: st_ivas->ivas_format = MC_FORMAT; @@ -407,35 +486,30 @@ static ivas_error ivas_read_format( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Invalid value %c found in SID format field.", st_ivas->sid_format ); } + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + int16_t tc_mode_offset; + tc_mode_offset = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 ); + idx = st_ivas->bit_stream[tc_mode_offset]; + // TBD: needs more work for HOA + if ( st_ivas->sba_analysis_order == 0 ) + { + st_ivas->sba_analysis_order = SBA_FOA_ORDER; + } + if ( idx == 1 ) + { + st_ivas->sba_mode = SBA_MODE_SPAR; + } + else + { + st_ivas->sba_mode = SBA_MODE_DIRAC; + } + } + /* reset bitstream handle to avoid BER detection after reading the 2400 kbps for ch0 */ st_ivas->bit_stream += ( *num_bits_read ); ( *num_bits_read ) = 0; } - else if ( !st_ivas->bfi && ivas_total_brate == IVAS_SID_5k ) - { - int16_t tc_mode_offset; - tc_mode_offset = (int16_t) ( ivas_total_brate / FRAMES_PER_SEC - 1 ); - idx = st_ivas->bit_stream[tc_mode_offset]; - // TBD: needs more work for HOA - if ( st_ivas->sba_order == 0 ) - { - st_ivas->sba_order = 1; - } - if ( idx == 0 ) - { - st_ivas->sid_format = SID_SBA_1TC; - st_ivas->ivas_format = SBA_FORMAT; - st_ivas->sba_mode = SBA_MODE_SPAR; - st_ivas->element_mode_init = IVAS_SCE; - } - else - { - st_ivas->sid_format = SID_SBA_2TC; - st_ivas->ivas_format = SBA_FORMAT; - st_ivas->sba_mode = SBA_MODE_SPAR; - st_ivas->element_mode_init = IVAS_CPE_MDCT; - } - } else { /* In SID/NO_DATA frames, use the previous frame IVAS format */ @@ -465,10 +539,28 @@ int16_t getNumChanSynthesis( { n = CPE_CHANNELS; } +#ifdef SBA_HPF_TUNING_DEC + else if ( st_ivas->ivas_format == SBA_FORMAT ) + { + if ( st_ivas->sba_analysis_order > 1 ) + { + n = 0; + } + else + { + n = st_ivas->nchan_transport; + } + } + else if ( st_ivas->hMCT != NULL ) + { + n = st_ivas->nchan_transport; + } +#else else if ( st_ivas->hMCT != NULL || st_ivas->ivas_format == SBA_FORMAT ) { n = st_ivas->nchan_transport; } +#endif return n; } @@ -514,29 +606,6 @@ ivas_error ivas_init_decoder_front( error = IVAS_ERR_OK; -#ifdef DEBUGGING - st_ivas->noClipping = 0; -#endif - - /* Custom loudspeaker layout structure */ - st_ivas->hLsSetupCustom = NULL; - - /* TD renderer HRTF data structure */ - st_ivas->hHrtfTD = NULL; - - /* Head track data structure */ - st_ivas->hHeadTrackData = NULL; - - /* Renderer configuration structure */ - st_ivas->hRenderConfig = NULL; - - /* HRTF binauralization latency in ns */ - st_ivas->binaural_latency_ns = 0; - -#ifdef DEBUGGING - st_ivas->hDecoderConfig->force_rend = -1; -#endif - /*-----------------------------------------------------------------* * Resets *-----------------------------------------------------------------*/ @@ -549,9 +618,16 @@ ivas_error ivas_init_decoder_front( st_ivas->mc_mode = MC_MODE_NONE; st_ivas->sba_mode = SBA_MODE_NONE; - st_ivas->hLimiter = NULL; - st_ivas->hoa_dec_mtx = NULL; + st_ivas->sba_dirac_stereo_flag = 0; + /* HRTF binauralization latency in ns */ + st_ivas->binaural_latency_ns = 0; + +#ifdef DEBUGGING + st_ivas->noClipping = 0; + + st_ivas->hDecoderConfig->force_rend = -1; +#endif /*-------------------------------------------------------------------* * Allocate and initialize Custom loudspeaker layout handle @@ -587,6 +663,20 @@ ivas_error ivas_init_decoder_front( { return error; } + if ( ( error = ivas_HRTF_CRend_binary_open( &( st_ivas->hSetOfHRTF ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_HRTF_fastconv_binary_open( &st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_HRTF_parambin_binary_open( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } } /*-------------------------------------------------------------------* @@ -600,9 +690,9 @@ ivas_error ivas_init_decoder_front( return error; } - if ( ivas_render_config_init_from_rom( &st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_BINAURAL_ROOM ) != IVAS_ERR_OK ) + if ( ( error = ivas_render_config_init_from_rom( &st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) != IVAS_ERR_OK ) { - return IVAS_ERR_INTERNAL_FATAL; + return error; } } @@ -622,9 +712,9 @@ ivas_error ivas_init_decoder( { int16_t i, k, n; int16_t sce_id, cpe_id; - int16_t numCldfbAnalyses; - int16_t numCldfbSyntheses; + int16_t numCldfbAnalyses, numCldfbSyntheses; int32_t output_Fs, ivas_total_brate; + int32_t binauralization_delay_ns; AUDIO_CONFIG output_config; DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; @@ -637,6 +727,7 @@ ivas_error ivas_init_decoder( ivas_total_brate = hDecoderConfig->ivas_total_brate; hDecoderConfig->last_ivas_total_brate = ivas_total_brate; + st_ivas->last_active_ivas_total_brate = ivas_total_brate; if ( output_config == AUDIO_CONFIG_EXTERNAL ) { @@ -664,6 +755,7 @@ ivas_error ivas_init_decoder( if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) { ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->element_mode_init ), ivas_total_brate ); + ivas_mcmasa_set_separate_channel_mode( &( st_ivas->hOutSetup.separateChannelEnabled ), &( st_ivas->hOutSetup.separateChannelIndex ), ivas_total_brate ); } @@ -671,7 +763,10 @@ ivas_error ivas_init_decoder( if ( output_config == AUDIO_CONFIG_LS_CUSTOM ) { - ivas_ls_custom_output_init( st_ivas ); + if ( ( error = ivas_ls_custom_output_init( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } } ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); @@ -679,6 +774,7 @@ ivas_error ivas_init_decoder( if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) { ivas_mcmasa_set_separate_channel_mode( &( st_ivas->hIntSetup.separateChannelEnabled ), &( st_ivas->hIntSetup.separateChannelIndex ), ivas_total_brate ); + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.separateChannelEnabled ) { st_ivas->hLsSetupCustom->separate_ch_found = 0; @@ -699,59 +795,54 @@ ivas_error ivas_init_decoder( } /*-----------------------------------------------------------------* - * Dummy pointers to decoder handles + * Set head/orientation tracking *-----------------------------------------------------------------*/ - for ( i = 0; i < MAX_SCE; i++ ) - { - st_ivas->hSCE[i] = NULL; - } - - for ( i = 0; i < MAX_CPE; i++ ) - { - st_ivas->hCPE[i] = NULL; - } - - /* ISm metadata handles */ - for ( n = 0; n < MAX_NUM_OBJECTS; n++ ) + if ( st_ivas->hDecoderConfig->Opt_Headrotation ) { - st_ivas->hIsmMetaData[n] = NULL; + if ( st_ivas->hDecoderConfig->orientation_tracking == IVAS_ORIENT_TRK_NONE ) + { + if ( ( error = ivas_orient_trk_SetTrackingType( st_ivas->hHeadTrackData->OrientationTracker, OTR_TRACKING_NONE ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDecoderConfig->orientation_tracking == IVAS_ORIENT_TRK_AVG ) + { + if ( ( error = ivas_orient_trk_SetTrackingType( st_ivas->hHeadTrackData->OrientationTracker, OTR_TRACKING_AVG_ORIENT ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDecoderConfig->orientation_tracking == IVAS_ORIENT_TRK_REF ) + { + if ( ( error = ivas_orient_trk_SetTrackingType( st_ivas->hHeadTrackData->OrientationTracker, OTR_TRACKING_REF_ORIENT ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDecoderConfig->orientation_tracking == IVAS_ORIENT_TRK_REF_VEC ) + { + if ( ( error = ivas_orient_trk_SetTrackingType( st_ivas->hHeadTrackData->OrientationTracker, OTR_TRACKING_REF_VEC ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDecoderConfig->orientation_tracking == IVAS_ORIENT_TRK_REF_VEC_LEV ) + { + if ( ( error = ivas_orient_trk_SetTrackingType( st_ivas->hHeadTrackData->OrientationTracker, OTR_TRACKING_REF_VEC_LEV ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + return IVAS_ERR_WRONG_MODE; + } } - /* DirAC handle */ - st_ivas->hDirAC = NULL; - st_ivas->sba_dirac_stereo_flag = 0; - - /* SPAR handle */ - st_ivas->hSpar = NULL; - - /* MASA decoder structure */ - st_ivas->hMasa = NULL; - - /* Q metadata handle */ - st_ivas->hQMetaData = NULL; - - /* MCT handles */ - st_ivas->hMCT = NULL; - st_ivas->hParamMC = NULL; - - /* LFE handle */ - st_ivas->hLFE = NULL; - - /* renderers handles */ - st_ivas->hBinRenderer = NULL; /* fastconf binaural renderer */ - st_ivas->hDiracDecBin = NULL; /* parametric binaural renderer */ - st_ivas->hLsSetUpConversion = NULL; /* MC converter */ - st_ivas->hEFAPdata = NULL; /* EFAP handle */ - st_ivas->hVBAPdata = NULL; /* VBAP handle */ - st_ivas->hIsmRendererData = NULL; /* ISm renderer */ - st_ivas->hBinRendererTd = NULL; /* TD ISm binaural renderer */ - st_ivas->hMonoDmxRenderer = NULL; /* Mono downmix renderer */ - st_ivas->hHrtf = NULL; /* Crend hrtf data */ - st_ivas->hCrend = NULL; /* Crend renderer */ - /*-----------------------------------------------------------------* - * Allocate and initalize SCE/CPE and other handles + * Allocate and initialize SCE/CPE and other handles *-----------------------------------------------------------------*/ if ( st_ivas->ivas_format == MONO_FORMAT ) @@ -786,6 +877,7 @@ ivas_error ivas_init_decoder( { reset_indices_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); } + /* init EFAP for custom LS output and set hTransSetup */ if ( output_config == AUDIO_CONFIG_LS_CUSTOM ) { @@ -803,11 +895,15 @@ ivas_error ivas_init_decoder( st_ivas->nSCE = st_ivas->nchan_transport; /* "st_ivas->nchan_transport" is known from ivas_dec_setup */ st_ivas->nCPE = 0; +#ifdef FIX_379_EXT_METADATA + st_ivas->ism_extmeta_active = -1; + st_ivas->ism_extmeta_cnt = 0; +#endif if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { - st_ivas->nchan_transport = 2; - st_ivas->nSCE = 2; + st_ivas->nchan_transport = MAX_PARAM_ISM_WAVE; + st_ivas->nSCE = MAX_PARAM_ISM_WAVE; if ( ( error = ivas_param_ism_dec_open( st_ivas ) ) != IVAS_ERR_OK ) { @@ -815,7 +911,7 @@ ivas_error ivas_init_decoder( } } - if ( ( error = create_ism_metadata_dec( st_ivas, st_ivas->nSCE, element_brate_tmp ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_ism_metadata_dec_create( st_ivas, st_ivas->nSCE, element_brate_tmp ) ) != IVAS_ERR_OK ) { return error; } @@ -828,15 +924,23 @@ ivas_error ivas_init_decoder( } reset_indices_dec( st_ivas->hSCE[sce_id]->hCoreCoder[0] ); + +#ifdef DISCRETE_ISM_DTX_CNG + st_ivas->hSCE[sce_id]->hCoreCoder[0]->is_ism_format = 1; +#endif + } + + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + st_ivas->hSCE[1]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed3 = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed2; } } else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) { + + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) { - if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } if ( st_ivas->ivas_format == MASA_FORMAT ) @@ -850,10 +954,11 @@ ivas_error ivas_init_decoder( { if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - if ( ( error = ivas_spar_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_spar_dec_open( st_ivas, 0 ) ) != IVAS_ERR_OK ) { return error; } + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->hOutSetup.is_loudspeaker_setup ) { if ( ( error = ivas_sba_get_hoa_dec_matrix( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) @@ -861,69 +966,52 @@ ivas_error ivas_init_decoder( return error; } } - if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_order, st_ivas->sba_planar, - st_ivas->sba_mode, IVAS_MAX_NUM_BANDS - SPAR_DIRAC_SPLIT_START_BAND ) ) != IVAS_ERR_OK ) + + if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_analysis_order, st_ivas->sba_mode, IVAS_MAX_NUM_BANDS - SPAR_DIRAC_SPLIT_START_BAND ) ) != IVAS_ERR_OK ) { return error; } - if ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA ) + + if ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_STEREO && st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_MONO ) { if ( ( error = ivas_dirac_dec_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } + for ( k = 0; k < DIRAC_MAX_NBANDS; k++ ) { - st_ivas->hSpar->hSparFoa->dirac_to_spar_md_bands[k] = st_ivas->hDirAC->dirac_to_spar_md_bands[k]; + st_ivas->hSpar->dirac_to_spar_md_bands[k] = st_ivas->hDirAC->dirac_to_spar_md_bands[k]; } - st_ivas->hSpar->hSparFoa->enc_param_start_band = st_ivas->hDirAC->hConfig->enc_param_start_band; + st_ivas->hSpar->enc_param_start_band = st_ivas->hDirAC->hConfig->enc_param_start_band; } else { int16_t band_grouping[IVAS_MAX_NUM_BANDS + 1]; - st_ivas->hSpar->hSparFoa->enc_param_start_band = min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); + st_ivas->hSpar->enc_param_start_band = min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); - ivas_dirac_config_bands( - band_grouping, - IVAS_MAX_NUM_BANDS, - (int16_t) ( st_ivas->hDecoderConfig->output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ), - st_ivas->hSpar->hSparFoa->dirac_to_spar_md_bands, - st_ivas->hQMetaData->useLowerBandRes, - st_ivas->hSpar->hSparFoa->enc_param_start_band, - 0 ); + ivas_dirac_config_bands( band_grouping, IVAS_MAX_NUM_BANDS, (int16_t) ( st_ivas->hDecoderConfig->output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ), + st_ivas->hSpar->dirac_to_spar_md_bands, st_ivas->hQMetaData->useLowerBandRes, st_ivas->hSpar->enc_param_start_band, 0 ); } +#ifdef SBA2MONO + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#else + st_ivas->sba_dirac_stereo_flag = ( output_config == AUDIO_CONFIG_STEREO ); +#endif } - else + else /* SBA_MODE_DIRAC */ { - if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_order, st_ivas->sba_planar, st_ivas->sba_mode, -1 ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_analysis_order, st_ivas->sba_mode, -1 ) ) != IVAS_ERR_OK ) { return error; } +#ifdef SBA2MONO + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#else st_ivas->sba_dirac_stereo_flag = ( st_ivas->nchan_transport == 1 && output_config == AUDIO_CONFIG_STEREO ); - - if ( ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) && st_ivas->hOutSetup.is_loudspeaker_setup ) - { - int16_t ambisonics_order; - - ambisonics_order = ivas_sba_get_order_transport( st_ivas->nchan_transport ); // VE: is it needed ? - - if ( ( error = ivas_sba_get_hoa_dec_matrix( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, ambisonics_order ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) && !st_ivas->hIntSetup.is_loudspeaker_setup ) - { - IVAS_OUTPUT_SETUP out_setup; - - ivas_output_init( &out_setup, AUDIO_CONFIG_7_1_4 ); - if ( ( error = ivas_sba_get_hoa_dec_matrix( out_setup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) - { - return error; - } - } +#endif } } @@ -942,6 +1030,7 @@ ivas_error ivas_init_decoder( { return error; } + reset_indices_dec( st_ivas->hSCE[sce_id]->hCoreCoder[0] ); } @@ -952,7 +1041,6 @@ ivas_error ivas_init_decoder( return error; } - for ( n = 0; n < CPE_CHANNELS; n++ ) { reset_indices_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); @@ -960,7 +1048,11 @@ ivas_error ivas_init_decoder( } /* create CPE element for DFT Stereo like upmix */ - if ( st_ivas->sba_dirac_stereo_flag ) +#ifdef SBA2MONO + if ( st_ivas->sba_dirac_stereo_flag && st_ivas->nCPE == 0 ) +#else + if ( st_ivas->sba_dirac_stereo_flag && st_ivas->nchan_transport == 1 ) +#endif { if ( ( error = create_cpe_dec( st_ivas, cpe_id, ivas_total_brate / ( st_ivas->nSCE + st_ivas->nCPE ) ) ) != IVAS_ERR_OK ) { @@ -968,6 +1060,7 @@ ivas_error ivas_init_decoder( } st_ivas->hCPE[0]->hCoreCoder[0] = st_ivas->hSCE[0]->hCoreCoder[0]; /* don't allocate unnecessary core coder, simply point to core coder of SCE element */ + st_ivas->hCPE[0]->hCoreCoder[1] = NULL; } if ( st_ivas->nCPE > 1 ) @@ -979,48 +1072,28 @@ ivas_error ivas_init_decoder( } /* set CNA/CNG flags */ +#ifdef FIX_386_CORECODER_RECONFIG + ivas_sba_set_cna_cng_flag( st_ivas ); +#else if ( st_ivas->sba_mode == SBA_MODE_SPAR && st_ivas->nchan_transport == 1 ) - { - st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 0; - st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag = 0; - } - else if ( st_ivas->nchan_transport == 1 && st_ivas->sba_mode == SBA_MODE_SPAR && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 0; /* Todo: Check if these can be enabled */ - st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag = 0; + st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 0; } else if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) ) { st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 1; - st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag = 1; + st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 1; } else if ( st_ivas->nchan_transport == 2 ) { - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) - { - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) - { - st_ivas->hCPE[0]->hCoreCoder[n]->cna_dirac_flag = 0; /* Todo: Check if these can be enabled */ - st_ivas->hCPE[0]->hCoreCoder[n]->cng_dirac_flag = 0; - } - else - { - st_ivas->hCPE[0]->hCoreCoder[n]->cng_dirac_flag = 1; - st_ivas->hCPE[0]->hCoreCoder[n]->cng_spar_flag = 1; - } - } - } - else + for ( n = 0; n < CPE_CHANNELS; n++ ) { - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - st_ivas->hCPE[0]->hCoreCoder[n]->cna_dirac_flag = 0; - st_ivas->hCPE[0]->hCoreCoder[n]->cng_dirac_flag = 1; - } + st_ivas->hCPE[0]->hCoreCoder[n]->cna_dirac_flag = 0; /* Todo: Check if these can be enabled */ + st_ivas->hCPE[0]->hCoreCoder[n]->cng_sba_flag = 1; } } +#endif } else if ( st_ivas->ivas_format == MC_FORMAT ) { @@ -1034,6 +1107,7 @@ ivas_error ivas_init_decoder( return error; } } + st_ivas->nchan_transport = ivas_mc_ls_setup_get_num_channels( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ) ); st_ivas->nSCE = 0; st_ivas->nCPE = st_ivas->nchan_transport / 2; @@ -1047,7 +1121,6 @@ ivas_error ivas_init_decoder( return error; } - for ( n = 0; n < CPE_CHANNELS; n++ ) { reset_indices_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); @@ -1069,12 +1142,12 @@ ivas_error ivas_init_decoder( return error; } } + if ( ( error = ivas_param_mc_dec_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } - for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { if ( ( error = create_cpe_dec( st_ivas, cpe_id, ivas_total_brate / ( st_ivas->nSCE + st_ivas->nCPE ) ) ) != IVAS_ERR_OK ) @@ -1082,7 +1155,6 @@ ivas_error ivas_init_decoder( return error; } - for ( n = 0; n < CPE_CHANNELS; n++ ) { reset_indices_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); @@ -1099,6 +1171,8 @@ ivas_error ivas_init_decoder( } else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { + int32_t brate_sce, brate_cpe; + ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->element_mode_init ), ivas_total_brate ); if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) @@ -1111,8 +1185,11 @@ ivas_error ivas_init_decoder( return error; } - +#ifdef SBA2MONO + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#else st_ivas->sba_dirac_stereo_flag = ( st_ivas->nchan_transport == 1 && output_config == AUDIO_CONFIG_STEREO ); +#endif if ( st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_MCMASA_MONO_STEREO ) { @@ -1128,7 +1205,7 @@ ivas_error ivas_init_decoder( if ( st_ivas->hVBAPdata == NULL ) { /* Distribute signal to all channels if VBAP is not properly initialized. */ - set_f( st_ivas->hLsSetupCustom->separate_ch_gains, 1 / sqrtf( st_ivas->hLsSetupCustom->num_spk ), st_ivas->hLsSetupCustom->num_spk ); + set_f( st_ivas->hLsSetupCustom->separate_ch_gains, inv_sqrt( st_ivas->hLsSetupCustom->num_spk ), st_ivas->hLsSetupCustom->num_spk ); } else { @@ -1136,43 +1213,27 @@ ivas_error ivas_init_decoder( } } + ivas_mcmasa_split_brate( st_ivas->hOutSetup.separateChannelEnabled, ivas_total_brate, st_ivas->nSCE, st_ivas->nCPE, &brate_sce, &brate_cpe ); + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) { - if ( st_ivas->hOutSetup.separateChannelEnabled ) - { - if ( ( error = create_sce_dec( st_ivas, sce_id, ivas_mcmasa_mono_brate( ivas_total_brate ) ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else + if ( ( error = create_sce_dec( st_ivas, sce_id, brate_sce ) ) != IVAS_ERR_OK ) { - if ( ( error = create_sce_dec( st_ivas, sce_id, ivas_total_brate / ( st_ivas->nSCE + st_ivas->nCPE ) ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } + reset_indices_dec( st_ivas->hSCE[sce_id]->hCoreCoder[0] ); } for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { - if ( st_ivas->hOutSetup.separateChannelEnabled ) - { - st_ivas->element_mode_init = IVAS_CPE_MDCT; - if ( ( error = create_cpe_dec( st_ivas, cpe_id, ivas_total_brate - st_ivas->hSCE[0]->element_brate ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else + st_ivas->element_mode_init = IVAS_CPE_MDCT; /* element_mode_init was IVAS_SCE for SCE initialization */ + + if ( ( error = create_cpe_dec( st_ivas, cpe_id, brate_cpe ) ) != IVAS_ERR_OK ) { - st_ivas->element_mode_init = IVAS_CPE_MDCT; - if ( ( error = create_cpe_dec( st_ivas, cpe_id, ivas_total_brate / ( st_ivas->nSCE + st_ivas->nCPE ) ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } + for ( n = 0; n < CPE_CHANNELS; n++ ) { reset_indices_dec( st_ivas->hCPE[cpe_id]->hCoreCoder[n] ); @@ -1188,13 +1249,14 @@ ivas_error ivas_init_decoder( } st_ivas->hCPE[0]->hCoreCoder[0] = st_ivas->hSCE[0]->hCoreCoder[0]; /* don't allocate unnecessary core coder, simply point to core coder of SCE element */ + st_ivas->hCPE[0]->hCoreCoder[1] = NULL; } /* set CNA/CNG flags */ if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) { st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 1; - st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag = 1; + st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 1; } } } @@ -1215,7 +1277,7 @@ ivas_error ivas_init_decoder( if ( n > 0 ) { - if ( ( st_ivas->mem_hp20_out = (float **) count_malloc( n * sizeof( float * ) ) ) == NULL ) + if ( ( st_ivas->mem_hp20_out = (float **) malloc( n * sizeof( float * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); } @@ -1227,7 +1289,7 @@ ivas_error ivas_init_decoder( for ( i = 0; i < n; i++ ) { - if ( ( st_ivas->mem_hp20_out[i] = (float *) count_malloc( L_HP20_MEM * sizeof( float ) ) ) == NULL ) + if ( ( st_ivas->mem_hp20_out[i] = (float *) malloc( L_HP20_MEM * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); } @@ -1249,7 +1311,15 @@ ivas_error ivas_init_decoder( } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) { return error; } @@ -1260,11 +1330,12 @@ ivas_error ivas_init_decoder( { return error; } + if ( st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) { - if ( ( st_ivas->hCrend = (CREND_HANDLE) count_malloc( sizeof( CREND_DATA ) ) ) == NULL ) + if ( ( error = ivas_reverb_open( &st_ivas->hReverb, st_ivas->hDecoderConfig->output_config, NULL, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR Crend\n" ); + return error; } } } @@ -1284,10 +1355,21 @@ ivas_error ivas_init_decoder( } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - if ( ivas_crend_open( st_ivas ) != IVAS_ERR_OK ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT && st_ivas->hDecoderConfig->Opt_Headrotation ) { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "ivas_crend_open failed" ); + if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hDecoderConfig->output_config, + st_ivas->hRenderConfig, st_ivas->hSetOfHRTF, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; } + + st_ivas->binaural_latency_ns = st_ivas->hCrendWrapper->binaural_latency_ns; } if ( st_ivas->ivas_format == ISM_FORMAT && @@ -1310,18 +1392,33 @@ ivas_error ivas_init_decoder( if ( st_ivas->mc_mode == MC_MODE_MCT ) { - if ( ( error = ivas_create_lfe_dec( &st_ivas->hLFE, output_Fs, st_ivas->hHrtf != NULL ? st_ivas->hHrtf->latency_s : 0 ) ) != IVAS_ERR_OK ) + binauralization_delay_ns = st_ivas->binaural_latency_ns; + if ( st_ivas->hBinRenderer != NULL ) + { + if ( st_ivas->hBinRenderer->render_lfe ) + { + /* Account for filterbank delay */ + binauralization_delay_ns += IVAS_FB_DEC_DELAY_NS; + } + else + { + binauralization_delay_ns = 0; + } + } + + if ( ( error = ivas_create_lfe_dec( &st_ivas->hLFE, output_Fs, binauralization_delay_ns ) ) != IVAS_ERR_OK ) { return error; } +#ifndef ISSUE_24_CLEANUP_MCT_LFE /* reuse core-coder buffers for LFE decoder */ cpe_id = LFE_CHANNEL / CPE_CHANNELS; n = LFE_CHANNEL % CPE_CHANNELS; st_ivas->hLFE->prevsynth_buf = &st_ivas->hCPE[cpe_id]->hCoreCoder[n]->old_synth_sw[0]; st_ivas->hLFE->prior_out_buffer = &st_ivas->hCPE[cpe_id]->hCoreCoder[n]->previoussynth[0]; - +#endif set_zero( st_ivas->hLFE->prevsynth_buf, LFE_PLC_BUFLEN ); set_zero( st_ivas->hLFE->prior_out_buffer, L_FRAME48k ); } @@ -1357,17 +1454,22 @@ ivas_error ivas_init_decoder( } /* CLDFB Interpolation weights */ - if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) +#ifdef SBA2MONO + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR && !st_ivas->sba_dirac_stereo_flag && st_ivas->hDecoderConfig->nchan_out != 1 ) +#else + if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR && !st_ivas->sba_dirac_stereo_flag ) +#endif { - ivas_spar_get_cldfb_gains( st_ivas->hSpar->hSparFoa, st_ivas->cldfbAnaDec[0], st_ivas->cldfbSynDec[0], hDecoderConfig ); + ivas_spar_get_cldfb_gains( st_ivas->hSpar, st_ivas->cldfbAnaDec[0], st_ivas->cldfbSynDec[0], hDecoderConfig ); } /*-----------------------------------------------------------------* * Allocate and initialize limiter struct *-----------------------------------------------------------------*/ + if ( ( st_ivas->hLimiter = ivas_limiter_open( hDecoderConfig->nchan_out, output_Fs ) ) == NULL ) { - st_ivas->hLimiter = ivas_limiter_open( hDecoderConfig->nchan_out, output_Fs ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to open limiter handle" ); } return error; @@ -1384,131 +1486,135 @@ void destroy_core_dec( DEC_CORE_HANDLE hCoreCoder /* i/o: core decoder structure */ ) { - destroy_decoder( hCoreCoder ); + destroy_cldfb_decoder( hCoreCoder ); if ( hCoreCoder->hGSCDec != NULL ) { - count_free( hCoreCoder->hGSCDec ); + free( hCoreCoder->hGSCDec ); hCoreCoder->hGSCDec = NULL; } if ( hCoreCoder->hPFstat != NULL ) { - count_free( hCoreCoder->hPFstat ); + free( hCoreCoder->hPFstat ); hCoreCoder->hPFstat = NULL; } if ( hCoreCoder->hMusicPF != NULL ) { - count_free( hCoreCoder->hMusicPF ); + free( hCoreCoder->hMusicPF ); hCoreCoder->hMusicPF = NULL; } if ( hCoreCoder->hBPF != NULL ) { - count_free( hCoreCoder->hBPF ); + free( hCoreCoder->hBPF ); hCoreCoder->hBPF = NULL; } if ( hCoreCoder->hBWE_zero != NULL ) { - count_free( hCoreCoder->hBWE_zero ); + free( hCoreCoder->hBWE_zero ); hCoreCoder->hBWE_zero = NULL; } if ( hCoreCoder->hTdCngDec != NULL ) { - count_free( hCoreCoder->hTdCngDec ); + free( hCoreCoder->hTdCngDec ); hCoreCoder->hTdCngDec = NULL; } if ( hCoreCoder->hSC_VBR != NULL ) { - count_free( hCoreCoder->hSC_VBR ); + free( hCoreCoder->hSC_VBR ); hCoreCoder->hSC_VBR = NULL; } if ( hCoreCoder->hAmrwb_IO != NULL ) { - count_free( hCoreCoder->hAmrwb_IO ); + free( hCoreCoder->hAmrwb_IO ); hCoreCoder->hAmrwb_IO = NULL; } if ( hCoreCoder->hBWE_TD != NULL ) { - count_free( hCoreCoder->hBWE_TD ); + free( hCoreCoder->hBWE_TD ); hCoreCoder->hBWE_TD = NULL; } if ( hCoreCoder->hBWE_FD != NULL ) { - count_free( hCoreCoder->hBWE_FD ); + free( hCoreCoder->hBWE_FD ); hCoreCoder->hBWE_FD = NULL; } if ( hCoreCoder->hBWE_FD_HR != NULL ) { - count_free( hCoreCoder->hBWE_FD_HR ); + free( hCoreCoder->hBWE_FD_HR ); hCoreCoder->hBWE_FD_HR = NULL; } if ( hCoreCoder->hWIDec != NULL ) { - count_free( hCoreCoder->hWIDec ); + free( hCoreCoder->hWIDec ); hCoreCoder->hWIDec = NULL; } if ( hCoreCoder->hTECDec != NULL ) { - count_free( hCoreCoder->hTECDec ); + free( hCoreCoder->hTECDec ); hCoreCoder->hTECDec = NULL; } if ( hCoreCoder->hTcxLtpDec != NULL ) { - count_free( hCoreCoder->hTcxLtpDec ); + free( hCoreCoder->hTcxLtpDec ); hCoreCoder->hTcxLtpDec = NULL; } if ( hCoreCoder->hTcxDec != NULL ) { - count_free( hCoreCoder->hTcxDec ); + free( hCoreCoder->hTcxDec ); hCoreCoder->hTcxDec = NULL; } - if ( hCoreCoder->hTcxCfg != NULL && hCoreCoder->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( hCoreCoder->hTcxCfg != NULL +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && hCoreCoder->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { - count_free( hCoreCoder->hTcxCfg ); + free( hCoreCoder->hTcxCfg ); hCoreCoder->hTcxCfg = NULL; } if ( hCoreCoder->hTonalMDCTConc != NULL ) { - count_free( hCoreCoder->hTonalMDCTConc ); + free( hCoreCoder->hTonalMDCTConc ); hCoreCoder->hTonalMDCTConc = NULL; } if ( hCoreCoder->hIGFDec != NULL ) { - count_free( hCoreCoder->hIGFDec ); + free( hCoreCoder->hIGFDec ); hCoreCoder->hIGFDec = NULL; } if ( hCoreCoder->hPlcInfo != NULL ) { - count_free( hCoreCoder->hPlcInfo ); + free( hCoreCoder->hPlcInfo ); hCoreCoder->hPlcInfo = NULL; } if ( hCoreCoder->hHQ_core != NULL ) { - count_free( hCoreCoder->hHQ_core ); + free( hCoreCoder->hHQ_core ); hCoreCoder->hHQ_core = NULL; } if ( hCoreCoder->hHQ_nbfec != NULL ) { - count_free( hCoreCoder->hHQ_nbfec ); + free( hCoreCoder->hHQ_nbfec ); hCoreCoder->hHQ_nbfec = NULL; } @@ -1550,9 +1656,9 @@ void ivas_initialize_handles_dec( st_ivas->hCPE[i] = NULL; } - st_ivas->nSCE = 0; - st_ivas->nCPE = 0; + st_ivas->bit_stream = NULL; st_ivas->mem_hp20_out = NULL; + st_ivas->hLimiter = NULL; /* ISM metadata handles */ for ( i = 0; i < MAX_NUM_OBJECTS; i++ ) @@ -1561,7 +1667,6 @@ void ivas_initialize_handles_dec( } /* spatial coding handles */ - st_ivas->hIsmRendererData = NULL; st_ivas->hDirAC = NULL; st_ivas->hSpar = NULL; st_ivas->hMasa = NULL; @@ -1579,13 +1684,17 @@ void ivas_initialize_handles_dec( st_ivas->hIsmRendererData = NULL; st_ivas->hBinRendererTd = NULL; st_ivas->hMonoDmxRenderer = NULL; - st_ivas->hCrend = NULL; - st_ivas->hHrtf = NULL; + st_ivas->hCrendWrapper = NULL; + st_ivas->hReverb = NULL; + st_ivas->hSetOfHRTF = NULL; + st_ivas->hHrtfFastConv = NULL; + st_ivas->hHrtfParambin = NULL; + st_ivas->hoa_dec_mtx = NULL; st_ivas->hHeadTrackData = NULL; st_ivas->hHrtfTD = NULL; - st_ivas->hLimiter = NULL; st_ivas->hLsSetupCustom = NULL; + st_ivas->hRenderConfig = NULL; return; } @@ -1601,7 +1710,7 @@ void ivas_destroy_dec( Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ ) { - int16_t i, n; + int16_t i; /* CLDFB handles */ for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) @@ -1609,7 +1718,6 @@ void ivas_destroy_dec( if ( st_ivas->cldfbAnaDec[i] != NULL ) { deleteCldfb( &( st_ivas->cldfbAnaDec[i] ) ); - st_ivas->cldfbAnaDec[i] = NULL; } } @@ -1618,7 +1726,6 @@ void ivas_destroy_dec( if ( st_ivas->cldfbSynDec[i] != NULL ) { deleteCldfb( &( st_ivas->cldfbSynDec[i] ) ); - st_ivas->cldfbSynDec[i] = NULL; } } @@ -1638,7 +1745,7 @@ void ivas_destroy_dec( if ( st_ivas->hCPE[i] != NULL ) { /* set pointer to NULL as core coder already deallocated in destroy_sce_dec() */ - if ( st_ivas->sba_dirac_stereo_flag ) + if ( st_ivas->sba_dirac_stereo_flag && st_ivas->nchan_transport == 1 ) { st_ivas->hCPE[i]->hCoreCoder[0] = NULL; st_ivas->hCPE[i]->hCoreCoder[1] = NULL; @@ -1648,76 +1755,60 @@ void ivas_destroy_dec( } } - /* LFE handle */ - if ( st_ivas->hLFE != NULL ) - { - ivas_lfe_dec_close( st_ivas->hLFE ); - st_ivas->hLFE = NULL; - } - /* HP20 filter handles */ if ( st_ivas->mem_hp20_out != NULL ) { for ( i = 0; i < getNumChanSynthesis( st_ivas ); i++ ) { - count_free( st_ivas->mem_hp20_out[i] ); + free( st_ivas->mem_hp20_out[i] ); st_ivas->mem_hp20_out[i] = NULL; } - count_free( st_ivas->mem_hp20_out ); + free( st_ivas->mem_hp20_out ); st_ivas->mem_hp20_out = NULL; } /* ISM metadata handles */ - for ( n = 0; n < MAX_NUM_OBJECTS; n++ ) - { - if ( st_ivas->hIsmMetaData[n] != NULL ) - { - count_free( st_ivas->hIsmMetaData[n] ); - st_ivas->hIsmMetaData[n] = NULL; - } - } + ivas_ism_metadata_close( st_ivas->hIsmMetaData ); - /* ISm renderer handle */ + /* ISM renderer handle */ if ( st_ivas->hIsmRendererData != NULL ) { - count_free( st_ivas->hIsmRendererData ); + free( st_ivas->hIsmRendererData ); st_ivas->hIsmRendererData = NULL; } /* DirAC handle */ - if ( st_ivas->hDirAC != NULL ) + if ( st_ivas->ivas_format == ISM_FORMAT ) { - if ( st_ivas->ivas_format == ISM_FORMAT ) - { - ivas_param_ism_dec_close( st_ivas->hDirAC, st_ivas->hDecoderConfig->output_config ); - } - else - { - ivas_dirac_dec_close( st_ivas->hDirAC ); - } - st_ivas->hDirAC = NULL; + ivas_param_ism_dec_close( &( st_ivas->hDirAC ), st_ivas->hDecoderConfig->output_config ); } - - /* Spar handle */ - if ( st_ivas->hSpar != NULL ) + else { - ivas_spar_dec_close( st_ivas->hSpar, st_ivas->hDecoderConfig->output_Fs ); - st_ivas->hSpar = NULL; + ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); } + /* SPAR handle */ + ivas_spar_dec_close( &( st_ivas->hSpar ), st_ivas->hDecoderConfig->output_Fs, 0 ); + /* HOA decoder matrix */ if ( st_ivas->hoa_dec_mtx != NULL ) { - count_free( st_ivas->hoa_dec_mtx ); + free( st_ivas->hoa_dec_mtx ); st_ivas->hoa_dec_mtx = NULL; } + /* MASA decoder structure */ + ivas_masa_dec_close( &( st_ivas->hMasa ) ); + /* Qmetadata handle */ ivas_qmetadata_close( &st_ivas->hQMetaData ); /* MCT handle */ ivas_mct_dec_close( &st_ivas->hMCT ); + /* LFE handle */ + ivas_lfe_dec_close( &( st_ivas->hLFE ) ); + /* Parametric MC handle */ ivas_param_mc_dec_close( &st_ivas->hParamMC ); @@ -1734,7 +1825,10 @@ void ivas_destroy_dec( ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); /* Crend handle */ - ivas_crend_close( st_ivas ); + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); + + /* Reverb handle */ + ivas_reverb_close( &st_ivas->hReverb ); /* LS config converter handle */ ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion ); @@ -1742,30 +1836,19 @@ void ivas_destroy_dec( /* Custom LS configuration handle */ if ( st_ivas->hLsSetupCustom != NULL ) { - count_free( st_ivas->hLsSetupCustom ); + free( st_ivas->hLsSetupCustom ); st_ivas->hLsSetupCustom = NULL; } - /* MASA decoder structure */ - if ( st_ivas->hMasa != NULL ) - { - ivas_masa_dec_close( st_ivas->hMasa ); - st_ivas->hMasa = NULL; - } - /* Downmix structure */ if ( st_ivas->hMonoDmxRenderer != NULL ) { - count_free( st_ivas->hMonoDmxRenderer ); + free( st_ivas->hMonoDmxRenderer ); st_ivas->hMonoDmxRenderer = NULL; } /* Head track data handle */ - if ( st_ivas->hHeadTrackData != NULL ) - { - count_free( st_ivas->hHeadTrackData ); - st_ivas->hHeadTrackData = NULL; - } + ivas_headTrack_close( &st_ivas->hHeadTrackData ); /* Time Domain binaural renderer handle */ if ( st_ivas->hBinRendererTd != NULL ) @@ -1774,17 +1857,20 @@ void ivas_destroy_dec( } else if ( st_ivas->hHrtfTD != NULL ) { - /* Case when HRTF filter is mistakenly specified but TD renderer was not active */ - if ( st_ivas->hHrtfTD->ModelParams.UseItdModel && !st_ivas->hHrtfTD->ModelParams.modelROM ) - { - BSplineModelEvalITDDealloc( &st_ivas->hHrtfTD->ModelParamsITD ); - } - BSplineModelEvalDealloc( &st_ivas->hHrtfTD->ModelParams, &st_ivas->hHrtfTD->ModelEval ); ivas_HRTF_binary_close( &st_ivas->hHrtfTD ); } + /* CRend binaural renderer handle */ + ivas_HRTF_CRend_binary_close( &st_ivas->hSetOfHRTF ); + + /* Fastconv HRTF filters */ + ivas_HRTF_fastconv_binary_close( &st_ivas->hHrtfFastConv ); + + /* Parametric binauralizer HRTF filters */ + ivas_HRTF_parambin_binary_close( &st_ivas->hHrtfParambin ); + /* Config. Renderer */ ivas_render_config_close( &( st_ivas->hRenderConfig ) ); @@ -1793,12 +1879,12 @@ void ivas_destroy_dec( if ( st_ivas->hDecoderConfig != NULL ) { - count_free( st_ivas->hDecoderConfig ); + free( st_ivas->hDecoderConfig ); st_ivas->hDecoderConfig = NULL; } /* main IVAS handle */ - count_free( st_ivas ); + free( st_ivas ); return; } @@ -1851,8 +1937,7 @@ void ivas_init_dec_get_num_cldfb_instances( case RENDERER_DIRAC: if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - *numCldfbAnalyses = st_ivas->hSpar->hSparFoa->hFbMixer->fb_cfg->num_in_chans; - + *numCldfbAnalyses = st_ivas->hSpar->hFbMixer->fb_cfg->num_in_chans; if ( st_ivas->hOutSetup.is_loudspeaker_setup && st_ivas->renderer_type == RENDERER_DIRAC ) { @@ -1860,7 +1945,7 @@ void ivas_init_dec_get_num_cldfb_instances( } else if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_FOA ) { - *numCldfbSyntheses = st_ivas->hSpar->hSparFoa->hFbMixer->fb_cfg->num_out_chans; + *numCldfbSyntheses = st_ivas->hSpar->hFbMixer->fb_cfg->num_out_chans; } else { @@ -1910,19 +1995,27 @@ void ivas_init_dec_get_num_cldfb_instances( case RENDERER_BINAURAL_FASTCONV_ROOM: if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - *numCldfbAnalyses = st_ivas->hSpar->hSparFoa->hFbMixer->fb_cfg->num_in_chans; - - if ( st_ivas->hOutSetup.is_loudspeaker_setup && st_ivas->renderer_type == RENDERER_DIRAC ) - { - *numCldfbSyntheses = st_ivas->hOutSetup.nchan_out_woLFE; - } - else if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_FOA ) + if ( st_ivas->sba_dirac_stereo_flag ) { - *numCldfbSyntheses = st_ivas->hSpar->hSparFoa->hFbMixer->fb_cfg->num_out_chans; + *numCldfbAnalyses = 0; + *numCldfbSyntheses = 0; } else { - *numCldfbSyntheses = MAX_OUTPUT_CHANNELS; + *numCldfbAnalyses = st_ivas->hSpar->hFbMixer->fb_cfg->num_in_chans; + + if ( st_ivas->hOutSetup.is_loudspeaker_setup && st_ivas->renderer_type == RENDERER_DIRAC ) + { + *numCldfbSyntheses = st_ivas->hOutSetup.nchan_out_woLFE; + } + else if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_FOA ) + { + *numCldfbSyntheses = st_ivas->hSpar->hFbMixer->fb_cfg->num_out_chans; + } + else + { + *numCldfbSyntheses = MAX_OUTPUT_CHANNELS; + } } } else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) @@ -2007,7 +2100,7 @@ static ivas_error doSanityChecks_IVAS( /* Verify ISM output configuration */ if ( output_config == AUDIO_CONFIG_INVALID ) { - return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified for ISm" ); + return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified for ISM" ); } } else if ( st_ivas->ivas_format == SBA_FORMAT ) @@ -2036,39 +2129,18 @@ static ivas_error doSanityChecks_IVAS( if ( st_ivas->hDecoderConfig->Opt_Headrotation ) { - if ( !( output_config == AUDIO_CONFIG_BINAURAL || - output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) + if ( !( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) { return IVAS_ERROR( IVAS_ERR_HEAD_ROTATION_NOT_SUPPORTED, "Wrong set-up: Head-rotation not supported in this configuration" ); } } #ifdef DEBUGGING - if ( st_ivas->hDecoderConfig->forceSubframeBinauralization ) - { - /* Note about resolution of Binaural Renderers: * - * - Parametric Binaural Renderer: 20 ms by default, can be forced to subframe (5 ms) resolution * - * - FastConv Binaural Renderer: 5 ms by default * - * - TD objects Binaural Renderer: 20 ms by default */ - - if ( !( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM ) || !( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MC_FORMAT || st_ivas->ivas_format == ISM_FORMAT ) ) - { - return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Wrong set-up: Forced subframe resolution parametric binauralization activated for non-binaural output." ); - } - } -#endif - -#ifdef DEBUGGING - if ( ( st_ivas->hHrtfTD != NULL || st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode != MC_MODE_MCT ) ) ) -#else - if ( st_ivas->hHrtfTD != NULL && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) ) ) -#endif - + if ( ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode != MC_MODE_MCT ) ) ) { return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration: Time Domain object renderer not supported in this configuration" ); } -#ifdef DEBUGGING if ( ( st_ivas->hHrtfTD != NULL && st_ivas->hDecoderConfig->force_rend == FORCE_CLDFB_RENDERER ) ) { return IVAS_ERROR( IVAS_ERR_INVALID_FORCE_MODE, "Incorrect debug configuration: Cannot force CLDFB renderer in combination with TD renderer HRTF file" ); diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c new file mode 100644 index 0000000000000000000000000000000000000000..e6571e83d9370369c73086286d6f7e0b145a9255 --- /dev/null +++ b/lib_dec/ivas_ism_dec.c @@ -0,0 +1,402 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------------* + * ivas_ism_bitrate_switching() + * + * + *-------------------------------------------------------------------------*/ + +static ivas_error ivas_ism_bitrate_switching( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nchan_transport_old, /* i : last number of transport channels */ + const ISM_MODE last_ism_mode /* i : last ISM mode */ +#ifndef NCHAN_ISM_PARAMETER + , + const int16_t num_obj /* i : number of objects in the bitstream */ +#endif +) +{ + ivas_error error; + int32_t element_brate_tmp[MAX_NUM_OBJECTS]; + int16_t nSCE_old, nCPE_old; + + error = IVAS_ERR_OK; + + nCPE_old = st_ivas->nCPE; + nSCE_old = st_ivas->nSCE; + +#ifdef NCHAN_ISM_PARAMETER + if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->nchan_ism, NULL, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, num_obj, NULL, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + + st_ivas->nSCE = st_ivas->nchan_transport; + + /*-----------------------------------------------------------------* + * Allocate, initialize, and configure SCE/CPE/MCT handles + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_corecoder_dec_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, 0, st_ivas->hDecoderConfig->ivas_total_brate / st_ivas->nchan_transport, ( st_ivas->hDecoderConfig->ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*-----------------------------------------------------------------* + * HP20 memories + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_hp20_dec_reconfig( st_ivas, nchan_transport_old ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*-----------------------------------------------------------------* + * Initialize the needed renderer struct and destroy the unnecessary renderer struct + *-----------------------------------------------------------------*/ + + /* select the renderer */ + ivas_renderer_select( st_ivas ); + ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); + if ( ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->ism_mode == ISM_MODE_DISC ) ) + { + ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->hDecoderConfig->output_config ); + } + + if ( st_ivas->ism_mode != last_ism_mode ) + { + /* EFAP handle */ + efap_free_data( &st_ivas->hEFAPdata ); + } + + /*-----------------------------------------------------------------* + * Switching between ParamISM and DiscISM + *-----------------------------------------------------------------*/ + + /* switching from ParamISM to DiscISM */ + if ( st_ivas->ism_mode == ISM_MODE_DISC && last_ism_mode == ISM_MODE_PARAM ) + { + /* Deallocate the ParamISM struct */ + ivas_param_ism_dec_close( &( st_ivas->hDirAC ), st_ivas->hDecoderConfig->output_config ); + + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL ) + { + /* close the parametric binaural renderer */ + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + + /* Open the TD Binaural renderer */ + if ( ( error = ivas_td_binaural_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + /* close the ISM renderer and reinitialize */ + if ( st_ivas->hIsmRendererData != NULL ) + { + free( st_ivas->hIsmRendererData ); + st_ivas->hIsmRendererData = NULL; + } + + if ( ( error = ivas_ism_renderer_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM ) + { + /* close the parametric binaural renderer */ + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + + /* Open Crend Binaural renderer */ + if ( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), + st_ivas->intern_config, + st_ivas->hOutSetup.output_config, + st_ivas->hRenderConfig, + st_ivas->hSetOfHRTF, + st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + + st_ivas->binaural_latency_ns = st_ivas->hCrendWrapper->binaural_latency_ns; + } + } + + /* switching from Discrete ISM to ParamISM */ + if ( st_ivas->ism_mode == ISM_MODE_PARAM && last_ism_mode == ISM_MODE_DISC ) + { + /* Allocate and initialize the ParamISM struct */ + if ( ( error = ivas_param_ism_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL ) + { + /* open the parametric binaural renderer */ + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Close the TD Binaural renderer */ + if ( st_ivas->hBinRendererTd != NULL ) + { + ivas_td_binaural_close( &st_ivas->hBinRendererTd ); + } + + if ( st_ivas->hHrtfTD != NULL ) + { + st_ivas->hHrtfTD = NULL; + } + } + else + { + /* Close the ISM renderer */ + if ( st_ivas->hIsmRendererData != NULL ) + { + free( st_ivas->hIsmRendererData ); + st_ivas->hIsmRendererData = NULL; + } + } + + if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM ) + { + /* open the parametric binaural renderer */ + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* close the crend binaural renderer */ + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); + } + } + + return error; +} + + +/*------------------------------------------------------------------------- + * ivas_ism_dec_config() + * + * - select ISM format mode + * - reconfigure the ISM format decoder + *-------------------------------------------------------------------------*/ + +ivas_error ivas_ism_dec_config( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +#ifdef DISCRETE_ISM_DTX_CNG + , + const ISM_MODE last_ism_mode /* i/o: last ISM mode */ +#endif +#ifndef NCHAN_ISM_PARAMETER + , + const int16_t num_obj /* i : number of objects in the bitstream */ +#endif +) +{ + int32_t ivas_total_brate; +#ifndef DISCRETE_ISM_DTX_CNG + ISM_MODE last_ism_mode; +#endif + ivas_error error; + int16_t nchan_transport_old; + + error = IVAS_ERR_OK; + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + +#ifndef DISCRETE_ISM_DTX_CNG + /* store last frame ISM mode */ + last_ism_mode = st_ivas->ism_mode; +#endif + + /* Assumes that num of input objects are constant */ +#ifdef NCHAN_ISM_PARAMETER + nchan_transport_old = st_ivas->nchan_ism; +#else + nchan_transport_old = num_obj; +#endif + + if ( last_ism_mode == ISM_MODE_PARAM ) + { + nchan_transport_old = MAX_PARAM_ISM_WAVE; + } + + if ( !st_ivas->bfi && ivas_total_brate != IVAS_SID_5k2 && ivas_total_brate != FRAME_NO_DATA ) + { + /* select ISM format mode */ +#ifdef NCHAN_ISM_PARAMETER + st_ivas->ism_mode = ivas_ism_mode_select( st_ivas->nchan_ism, ivas_total_brate ); + + st_ivas->nchan_transport = st_ivas->nchan_ism; +#else + st_ivas->ism_mode = ivas_ism_mode_select( num_obj, ivas_total_brate ); + + st_ivas->nchan_transport = num_obj; +#endif + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + st_ivas->nchan_transport = MAX_PARAM_ISM_WAVE; + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) + { +#ifdef NCHAN_ISM_PARAMETER + st_ivas->hDecoderConfig->nchan_out = st_ivas->nchan_ism; +#else + st_ivas->hDecoderConfig->nchan_out = num_obj; +#endif + } + } + + if ( st_ivas->ini_active_frame != 0 ) + { + /* ISM bit-rate switching */ +#ifndef DISCRETE_ISM_DTX_CNG + if ( st_ivas->hDecoderConfig->last_ivas_total_brate != IVAS_SID_5k2 && st_ivas->hDecoderConfig->last_ivas_total_brate != FRAME_NO_DATA ) +#endif + { + if ( ( st_ivas->ism_mode != last_ism_mode ) || ( st_ivas->hDecoderConfig->ivas_total_brate != st_ivas->hDecoderConfig->last_ivas_total_brate ) ) + { +#ifdef NCHAN_ISM_PARAMETER + if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode, num_obj ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + } + } + } + } + else if ( !st_ivas->bfi && ivas_total_brate == IVAS_SID_5k2 ) + { +#ifdef DISCRETE_ISM_DTX_CNG +#ifdef NCHAN_ISM_PARAMETER + st_ivas->nchan_transport = st_ivas->nchan_ism; +#else + st_ivas->nchan_transport = num_obj; +#endif + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + st_ivas->nchan_transport = MAX_PARAM_ISM_WAVE; + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) + { +#ifdef NCHAN_ISM_PARAMETER + st_ivas->hDecoderConfig->nchan_out = st_ivas->nchan_ism; +#else + st_ivas->hDecoderConfig->nchan_out = num_obj; +#endif + } + } + + /* ISM mode switching */ + if ( st_ivas->ism_mode != last_ism_mode ) + { +#ifdef NCHAN_ISM_PARAMETER + if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_bitrate_switching( st_ivas, nchan_transport_old, last_ism_mode, num_obj ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + } +#else + if ( last_ism_mode == ISM_MODE_PARAM ) + { + nchan_transport_old = MAX_PARAM_ISM_WAVE; + } + else + { +#ifdef NCHAN_ISM_PARAMETER + st_ivas->nchan_transport = st_ivas->nchan_ism; +#else + st_ivas->nchan_transport = num_obj; +#endif + } +#endif + } + +#ifdef NCHAN_ISM_PARAMETER + switch ( st_ivas->nchan_ism ) +#else + switch ( num_obj ) +#endif + { + case 1: + st_ivas->transport_config = AUDIO_CONFIG_ISM1; + break; + case 2: + st_ivas->transport_config = AUDIO_CONFIG_ISM2; + break; + case 3: + st_ivas->transport_config = AUDIO_CONFIG_ISM3; + break; + case 4: + st_ivas->transport_config = AUDIO_CONFIG_ISM4; + break; + default: + st_ivas->transport_config = AUDIO_CONFIG_INVALID; + break; + } + + return error; +} diff --git a/lib_dec/ivas_ism_dtx_dec.c b/lib_dec/ivas_ism_dtx_dec.c new file mode 100644 index 0000000000000000000000000000000000000000..ef52c082b7330adf6f3b478ca4f0d98f8ef314a1 --- /dev/null +++ b/lib_dec/ivas_ism_dtx_dec.c @@ -0,0 +1,270 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "ivas_prot.h" +#include "prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * ivas_ism_preprocessing() + * + * + *-------------------------------------------------------------------*/ + +static void ivas_ism_preprocessing( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t sce_id /* i : SCE # identifier */ +) +{ +#ifndef DISCRETE_ISM_DTX_CNG + int32_t ivas_total_brate; +#endif + Decoder_State *st; + + st = st_ivas->hSCE[sce_id]->hCoreCoder[0]; + +#ifndef DISCRETE_ISM_DTX_CNG + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + if ( ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) ) +#endif + { + /* reset the bitstream to at least read the cng type and bandwidth for non transmitted SCE */ + st->bit_stream = st_ivas->hSCE[0]->hCoreCoder[0]->bit_stream; +#ifdef DISCRETE_ISM_DTX_CNG + st->next_bit_pos = 0; /* note: needed in paramISM -> discISM switching */ +#endif + + if ( sce_id == st_ivas->hISMDTX.sce_id_dtx ) + { + st->read_sid_info = 1; /* read the sid info from bitstream */ + } + else + { + st->read_sid_info = 0; /* do not read the sid info from bitstream but use the estimated noise */ + } + + st->cng_ism_flag = 1; + } +#ifndef DISCRETE_ISM_DTX_CNG + else + { + st->cng_ism_flag = 0; + } +#endif + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_ism_dtx_dec() + * + * ISM DTX Metadata decoding routine + *-------------------------------------------------------------------*/ + +ivas_error ivas_ism_dtx_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + int16_t *nb_bits_metadata /* o : number of metadata bits */ +) +{ + int16_t ch, pos, nchan_ism, nchan_ism_prev; + int32_t ivas_total_brate; +#ifdef DISCRETE_ISM_DTX_CNG + int16_t md_diff_flag[MAX_NUM_OBJECTS]; + int16_t idx, flag_noisy_speech, sce_id_dtx; + ISM_MODE last_ism_mode, ism_mode_bstr; + ivas_error error; +#endif + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + +#ifndef DISCRETE_ISM_DTX_CNG + if ( st_ivas->nchan_transport == 1 ) + { + nb_bits_metadata[0] = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; + + return IVAS_ERR_OK; + } +#endif + +#ifdef NCHAN_ISM_PARAMETER + nchan_ism_prev = st_ivas->nchan_ism; +#else + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + nchan_ism_prev = st_ivas->hDirAC->hParamIsm->num_obj; + } + else /* ism_mode == ISM_MODE_DISC */ + { + nchan_ism_prev = st_ivas->nchan_transport; + } +#endif + + if ( !st_ivas->bfi && ivas_total_brate == IVAS_SID_5k2 ) + { + /* read number of objects */ + nchan_ism = 1; + pos = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC ) - 1 - SID_FORMAT_NBITS ); + + while ( get_indice( st_ivas->hSCE[0]->hCoreCoder[0], pos, 1 ) == 1 && nchan_ism < MAX_NUM_OBJECTS ) + { + ( nchan_ism )++; + pos--; + } +#ifdef NCHAN_ISM_PARAMETER + st_ivas->nchan_ism = nchan_ism; +#endif +#ifdef DISCRETE_ISM_DTX_CNG + pos--; +#endif + + if ( nchan_ism != nchan_ism_prev ) + { + /* IVAS_fmToDo: more work needed when the number of transported objects is not constant */ + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "wrong number of objects signalled!" ); + } + +#ifdef DISCRETE_ISM_DTX_CNG + last_ism_mode = st_ivas->ism_mode; + + /* read ism_mode */ + if ( nchan_ism > 2 ) + { + pos -= nchan_ism; /* SID metadata flags */ + + idx = get_indice( st_ivas->hSCE[0]->hCoreCoder[0], pos, 1 ); + ism_mode_bstr = (ISM_MODE) ( idx + 1 ); + st_ivas->ism_mode = ism_mode_bstr; + } + +#ifdef NCHAN_ISM_PARAMETER + if ( ( error = ivas_ism_dec_config( st_ivas, last_ism_mode ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_ism_dec_config( st_ivas, last_ism_mode, nchan_ism ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } +#else +#ifdef NCHAN_ISM_PARAMETER + ivas_ism_dec_config( st_ivas ); +#else + ivas_ism_dec_config( st_ivas, nchan_ism ); +#endif + + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { +#ifdef NCHAN_ISM_PARAMETER + st_ivas->nchan_transport = 2; +#else + st_ivas->hDirAC->hParamIsm->num_obj = nchan_ism; +#endif + } + else /* ism_mode == ISM_MODE_DISC */ + { + st_ivas->nchan_transport = nchan_ism; + } +#endif + } + else + { + nchan_ism = nchan_ism_prev; + } + + /* Metadata decoding and dequantization */ +#ifdef DISCRETE_ISM_DTX_CNG + ivas_ism_metadata_sid_dec( st_ivas->hSCE, ivas_total_brate, st_ivas->bfi, nchan_ism, st_ivas->nchan_transport, st_ivas->ism_mode, + &flag_noisy_speech, &sce_id_dtx, st_ivas->hIsmMetaData, nb_bits_metadata ); + + if ( ivas_total_brate == IVAS_SID_5k2 && !st_ivas->bfi ) + { + if ( st_ivas->hDirAC != NULL ) + { + st_ivas->hDirAC->hParamIsm->flag_noisy_speech = flag_noisy_speech; + } + + st_ivas->hISMDTX.sce_id_dtx = sce_id_dtx; + } +#else + ivas_param_ism_metadata_dtx_dec( st_ivas ); +#endif + +#ifdef DISCRETE_ISM_DTX_CNG + set_s( md_diff_flag, 1, nchan_ism ); + + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + for ( ch = 0; ch < nchan_ism; ch++ ) + { + st_ivas->hDirAC->azimuth_values[ch] = st_ivas->hIsmMetaData[ch]->azimuth; + st_ivas->hDirAC->elevation_values[ch] = st_ivas->hIsmMetaData[ch]->elevation; + } + } + + update_last_metadata( nchan_ism, st_ivas->hIsmMetaData, md_diff_flag ); + + st_ivas->hISMDTX.ism_dtx_hangover_cnt = 0; +#endif + + if ( ivas_total_brate == IVAS_SID_5k2 && !st_ivas->bfi ) + { + for ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { +#ifdef DISCRETE_ISM_DTX_CNG + nb_bits_metadata[ch] = nb_bits_metadata[sce_id_dtx]; +#else + nb_bits_metadata[ch] = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; +#endif + } + } + +#ifdef DISCRETE_ISM_DTX_CNG + if ( !st_ivas->bfi ) +#else + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) +#endif + { + for ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + ivas_ism_preprocessing( st_ivas, ch ); // VE: after the acceptance of switches, replace the function call by its content + } + } + + return IVAS_ERR_OK; +} diff --git a/lib_dec/ivas_ism_metadata_dec.c b/lib_dec/ivas_ism_metadata_dec.c index 6b36447e306c820e9794a592ff4e1c3aff6bc028..feccbc9766a28230619be030a1710d57607d6613 100644 --- a/lib_dec/ivas_ism_metadata_dec.c +++ b/lib_dec/ivas_ism_metadata_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,48 +37,172 @@ #include "ivas_rom_com.h" #include "prot.h" #include "ivas_stat_enc.h" +#ifdef DISCRETE_ISM_DTX_CNG +#include +#endif #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" + + +/*-----------------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------------*/ + +static void decode_angle_indices( DEC_CORE_HANDLE st0, ISM_METADATA_ANGLE_HANDLE angle, int16_t *flag_abs_azimuth ); + +static int16_t decode_radius( DEC_CORE_HANDLE st0, int16_t *last_radius_idx, int16_t *flag_abs_radius ); + +#ifdef DISCRETE_ISM_DTX_CNG +/*-------------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------------*/ + +#define IVAS_ISM_DTX_HO_MAX 5 + +#define CNG_MD_MAX_DIFF_AZIMUTH 5 +#define CNG_MD_MAX_DIFF_ELEVATION 5 + + +/*-------------------------------------------------------------------* + * ism_metadata_smooth() + * + * Smooth the metadata evolution + *-------------------------------------------------------------------*/ + +static void ism_metadata_smooth( + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + const int32_t ism_total_brate, /* i : ISms total bitrate */ + const int16_t nchan_ism /* i : number of objects */ +) +{ + ISM_METADATA_HANDLE hIsmMetaData; + int16_t ch; + float diff; + + for ( ch = 0; ch < nchan_ism; ch++ ) + { + hIsmMetaData = hIsmMeta[ch]; + + /* smooth azimuth */ + diff = hIsmMetaData->last_true_azimuth - hIsmMetaData->last_azimuth; + + if ( diff > ISM_AZIMUTH_MAX ) + { + diff -= ( ISM_AZIMUTH_MAX - ISM_AZIMUTH_MIN ); + hIsmMetaData->last_azimuth += ( ISM_AZIMUTH_MAX - ISM_AZIMUTH_MIN ); + } + else if ( diff < ISM_AZIMUTH_MIN ) + { + diff += ( ISM_AZIMUTH_MAX - ISM_AZIMUTH_MIN ); + } + + if ( ism_total_brate > IVAS_SID_5k2 && fabsf( diff ) > IVAS_ISM_DTX_HO_MAX * CNG_MD_MAX_DIFF_AZIMUTH ) + { + /* skip the smoothing */ + } + else if ( fabsf( diff ) > CNG_MD_MAX_DIFF_AZIMUTH ) + { + hIsmMetaData->azimuth = hIsmMetaData->last_azimuth + sign( diff ) * CNG_MD_MAX_DIFF_AZIMUTH; + } + else if ( diff != 0 ) + { + hIsmMetaData->azimuth = hIsmMetaData->last_true_azimuth; + } + + if ( hIsmMetaData->azimuth > ISM_AZIMUTH_MAX ) + { + hIsmMetaData->azimuth -= ( ISM_AZIMUTH_MAX - ISM_AZIMUTH_MIN ); + } + + /* smooth elevation */ + diff = hIsmMetaData->last_true_elevation - hIsmMetaData->last_elevation; + + if ( ism_total_brate > IVAS_SID_5k2 && diff > IVAS_ISM_DTX_HO_MAX * CNG_MD_MAX_DIFF_ELEVATION ) + { + /* skip the smoothing */ + } + else if ( fabsf( diff ) > CNG_MD_MAX_DIFF_ELEVATION ) + { + hIsmMetaData->elevation = hIsmMetaData->last_elevation + sign( diff ) * CNG_MD_MAX_DIFF_ELEVATION; + } + } + + return; +} +#endif /*-------------------------------------------------------------------------* * ivas_ism_metadata_dec() * - * decode and dequantize ISm metadata + * decode and dequantize ISM metadata *-------------------------------------------------------------------------*/ ivas_error ivas_ism_metadata_dec( - const int32_t ism_total_brate, /* i : ISms total bitrate */ - int16_t *nchan_transport, /* o : number of transport channels */ - ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ - SCE_DEC_HANDLE hSCE[], /* i/o: SCE decoder handles */ - const int16_t bfi, /* i : bfi flag */ - int16_t nb_bits_metadata[], /* o : number of metadata bits */ - ISM_MODE ism_mode, /* i : ISM mode */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ +#ifdef NCHAN_ISM_PARAMETER + const int16_t nchan_ism, /* i : number of ISM channels */ +#endif + int16_t *nchan_transport, /* o : number of transport channels */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + SCE_DEC_HANDLE hSCE[], /* i/o: SCE decoder handles */ + const int16_t bfi, /* i : bfi flag */ + int16_t nb_bits_metadata[], /* o : number of metadata bits */ + ISM_MODE ism_mode, /* i : ISM mode */ +#ifdef DISCRETE_ISM_DTX_CNG + ISM_DTX_DATA_DEC hISMDTX, /* i/o: ISM DTX structure */ +#endif +#ifdef FIX_379_EXT_METADATA + const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Config Handle */ + int16_t *ism_extmeta_active, /* i/o: Extended metadata active in renderer*/ + int16_t *ism_extmeta_cnt /* i/o: Number of change frames observed*/ +#else const PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Config Handle */ +#endif ) { - int16_t ch, nb_bits_start = 0, last_bit_pos, sgn, diff; + int16_t ch, nb_bits_start = 0, last_bit_pos; + int16_t idx_radius; int32_t element_brate[MAX_NUM_OBJECTS], total_brate[MAX_NUM_OBJECTS]; DEC_CORE_HANDLE st0; - int16_t idx_azimuth, nbits_diff_azimuth, flag_abs_azimuth; - int16_t idx_elevation, nbits_diff_elevation; +#ifdef FIX_379_EXT_METADATA + int16_t ism_extmeta_bitstream; + float yaw, pitch, radius; +#else + int16_t ism_extended_metadata_flag; +#endif + int16_t flag_abs_radius; + int16_t flag_abs_orientation; +#ifdef FIX_379_ANGLE + int16_t flag_abs_position; + int16_t idx_angle1; + int16_t idx_angle2; +#else + int16_t idx_azimuth, flag_abs_azimuth; + int16_t idx_elevation; +#endif int16_t next_bit_pos_orig; uint16_t i, bstr_meta[MAX_BITS_METADATA], *bstr_orig; ISM_METADATA_HANDLE hIsmMetaData; int16_t nchan_transport_prev, ism_metadata_flag_global; int16_t localVAD[MAX_NUM_OBJECTS]; int16_t ism_imp[MAX_NUM_OBJECTS]; - int16_t num_obj = 0, nbands, nblocks; +#ifdef NCHAN_ISM_PARAMETER + int16_t nbands, nblocks; +#else + int16_t nchan_ism = 0, nbands, nblocks; +#endif +#ifdef DISCRETE_ISM_DTX_CNG + int16_t md_diff_flag[MAX_NUM_OBJECTS]; +#endif ivas_error error; - error = IVAS_ERR_OK; - - wmops_sub_start( "ism_meta_dec" ); + push_wmops( "ism_meta_dec" ); - if ( ism_total_brate == IVAS_SID_4k4 || ism_total_brate == FRAME_NO_DATA ) +#ifndef DISCRETE_ISM_DTX_CNG + if ( ism_total_brate == IVAS_SID_5k2 || ism_total_brate == FRAME_NO_DATA ) { /* no metadata decoding in CNG */ for ( ch = 0; ch < *nchan_transport; ch++ ) @@ -87,7 +211,7 @@ ivas_error ivas_ism_metadata_dec( } /* set padding bits as metadata bits to keep later bitrate checks valid */ - nb_bits_metadata[0] = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC; + nb_bits_metadata[0] = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; #ifdef DEBUGGING /* sanity check */ @@ -97,9 +221,10 @@ ivas_error ivas_ism_metadata_dec( } #endif - wmops_sub_end(); - return error; + pop_wmops(); + return IVAS_ERR_OK; } +#endif /* initialization */ st0 = hSCE[0]->hCoreCoder[0]; @@ -110,6 +235,11 @@ ivas_error ivas_ism_metadata_dec( bstr_orig = st0->bit_stream; next_bit_pos_orig = st0->next_bit_pos; st0->next_bit_pos = 0; +#ifdef FIX_379_EXT_METADATA + ism_extmeta_bitstream = 0; +#else + ism_extended_metadata_flag = 0; +#endif /* reverse the bitstream for easier reading of indices */ for ( i = 0; i < min( MAX_BITS_METADATA, last_bit_pos ); i++ ) @@ -122,25 +252,34 @@ ivas_error ivas_ism_metadata_dec( if ( !bfi ) { /*----------------------------------------------------------------* - * Read ISm common signalling + * Read ISM common signaling *----------------------------------------------------------------*/ +#ifdef NCHAN_ISM_PARAMETER + /* number of objects was read in ivas_dec_setup() */ + st0->next_bit_pos += nchan_ism; +#else /* read number of objects */ - num_obj = 1; - while ( get_next_indice( st0, 1 ) == 1 && num_obj < MAX_NUM_OBJECTS ) + nchan_ism = 1; + while ( get_next_indice( st0, 1 ) == 1 && nchan_ism < MAX_NUM_OBJECTS ) { - ( num_obj )++; + ( nchan_ism )++; } +#endif - ism_mode = ivas_ism_mode_select( num_obj, ism_total_brate ); + ism_mode = ivas_ism_mode_select( nchan_ism, ism_total_brate ); if ( ism_mode == ISM_MODE_PARAM ) { - hParamIsm->num_obj = num_obj; +#ifdef NCHAN_ISM_PARAMETER + *nchan_transport = MAX_PARAM_ISM_WAVE; +#else + hParamIsm->num_obj = nchan_ism; +#endif } else if ( ism_mode == ISM_MODE_DISC ) { - *nchan_transport = num_obj; + *nchan_transport = nchan_ism; } if ( *nchan_transport != nchan_transport_prev ) @@ -149,7 +288,34 @@ ivas_error ivas_ism_metadata_dec( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "wrong number of objects signalled!" ); } - /* Read ISm present flags (one per object) */ + /* read extended metadata presence flag */ + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) + { +#ifdef FIX_379_EXT_METADATA + ism_extmeta_bitstream = get_next_indice( st0, ISM_EXTENDED_METADATA_BITS ); +#else + ism_extended_metadata_flag = get_next_indice( st0, ISM_EXTENDED_METADATA_BITS ); +#endif + } +#ifdef FIX_379_EXT_METADATA + /* Apply hysteresis in case rate switching causes fluctuation in presence of extended metadata */ + if ( *ism_extmeta_active == -1 || *ism_extmeta_active == ism_extmeta_bitstream ) /* If first frame or bitstream matches internal state */ + { + *ism_extmeta_active = ism_extmeta_bitstream; + *ism_extmeta_cnt = 0; + } + else + { + ( *ism_extmeta_cnt )++; + if ( *ism_extmeta_cnt == ISM_METADATA_RS_MAX_FRAMES ) /* ISM_METADATA_RS_MAX_FRAMES change frames observed - update state */ + { + *ism_extmeta_active = ism_extmeta_bitstream; + *ism_extmeta_cnt = 0; + } + } +#endif + + /* Read ISM present flags (one per object) */ for ( ch = 0; ch < *nchan_transport; ch++ ) { ism_imp[ch] = get_next_indice( st0, ISM_METADATA_FLAG_BITS ); @@ -166,7 +332,7 @@ ivas_error ivas_ism_metadata_dec( ism_metadata_flag_global |= hIsmMeta[ch]->ism_metadata_flag; } - for ( ; ch < num_obj; ch++ ) + for ( ; ch < nchan_ism; ch++ ) { hIsmMeta[ch]->ism_metadata_flag = 1; ism_metadata_flag_global |= hIsmMeta[ch]->ism_metadata_flag; @@ -199,166 +365,116 @@ ivas_error ivas_ism_metadata_dec( nb_bits_start = st0->next_bit_pos; } - for ( ch = 0; ch < num_obj; ch++ ) + for ( ch = 0; ch < nchan_ism; ch++ ) { hIsmMetaData = hIsmMeta[ch]; if ( ism_mode == ISM_MODE_DISC ) { nb_bits_start = st0->next_bit_pos; } - +#ifdef FIX_379_ANGLE + flag_abs_position = 0; +#else flag_abs_azimuth = 0; +#endif + flag_abs_orientation = 0; + flag_abs_radius = 0; if ( hIsmMeta[ch]->ism_metadata_flag ) { - /*----------------------------------------------------------------* - * Azimuth decoding and dequantization - *----------------------------------------------------------------*/ - - /* Decode azimuth index */ - if ( get_next_indice( st0, 1 ) == 1 ) /* azimuth_abs_flag */ - { - idx_azimuth = get_next_indice( st0, ISM_AZIMUTH_NBITS ); - flag_abs_azimuth = 1; - } - else - { - diff = 0; - sgn = 1; - - if ( get_next_indice( st0, 1 ) == 0 ) - { - nbits_diff_azimuth = 1; - } - else - { - nbits_diff_azimuth = 1; - - if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ - { - sgn = -1; - } - - nbits_diff_azimuth++; - - /* read until the stop bit */ - while ( ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) && ( get_next_indice( st0, 1 ) == 1 ) ) - { - diff++; - nbits_diff_azimuth++; - } - - if ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) - { - /* count stop bit */ - nbits_diff_azimuth++; - } - } - - idx_azimuth = hIsmMetaData->last_azimuth_idx + sgn * diff; - } - - /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ - if ( idx_azimuth > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - { - idx_azimuth -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* +180° -> -180° */ - } - else if ( idx_azimuth < 0 ) - { - idx_azimuth += ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* -180° -> +180° */ - } - - /* +180° == -180° */ - if ( idx_azimuth == ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - { - idx_azimuth = 0; - } - - /* sanity check in case of FER or BER */ - if ( idx_azimuth < 0 || idx_azimuth > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - { - idx_azimuth = hIsmMetaData->last_azimuth_idx; - } - - /* Azimuth dequantization */ +#ifdef FIX_379_ANGLE + decode_angle_indices( st0, &( hIsmMetaData->position_angle ), &flag_abs_position ); + idx_angle1 = hIsmMetaData->position_angle.last_angle1_idx; + idx_angle2 = hIsmMetaData->position_angle.last_angle2_idx; +#else + decode_angle_indices( st0, &( hIsmMetaData->angle[0] ), &flag_abs_azimuth ); + idx_azimuth = hIsmMetaData->angle[0].last_azimuth_idx; + idx_elevation = hIsmMetaData->angle[0].last_elevation_idx; +#endif + /* Azimuth/Elevation dequantization */ if ( ism_mode == ISM_MODE_PARAM ) { +#ifdef FIX_379_ANGLE + hParamIsm->azi_index[ch] = idx_angle1; + hParamIsm->ele_index[ch] = idx_angle2; +#else hParamIsm->azi_index[ch] = idx_azimuth; + hParamIsm->ele_index[ch] = idx_elevation; +#endif } else /* ISM_MODE_DISC */ { - hIsmMetaData->azimuth = ism_dequant_meta( idx_azimuth, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); - } - - /*----------------------------------------------------------------* - * Elevation decoding and dequantization - *----------------------------------------------------------------*/ - - /* Decode elevation index */ - if ( flag_abs_azimuth == 0 && get_next_indice( st0, 1 ) == 1 ) /* elevation_abs_flag */ - { - idx_elevation = get_next_indice( st0, ISM_ELEVATION_NBITS ); - } - else - { - diff = 0; - sgn = 1; +#ifdef FIX_379_ANGLE + hIsmMetaData->azimuth = ism_dequant_meta( idx_angle1, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + hIsmMetaData->elevation = ism_dequant_meta( idx_angle2, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#else + hIsmMetaData->azimuth = ism_dequant_meta( idx_azimuth, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + hIsmMetaData->elevation = ism_dequant_meta( idx_elevation, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#endif - if ( get_next_indice( st0, 1 ) == 0 ) - { - nbits_diff_elevation = 1; - } - else + /* radius/raw/pitch dequantization */ +#ifdef FIX_379_EXT_METADATA + if ( ism_extmeta_bitstream ) +#else + if ( ism_extended_metadata_flag ) +#endif { - nbits_diff_elevation = 1; - - if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ - { - sgn = -1; - } - - nbits_diff_elevation++; +#ifdef FIX_379_ANGLE + decode_angle_indices( st0, &( hIsmMetaData->orientation_angle ), &flag_abs_orientation ); + idx_angle1 = hIsmMetaData->orientation_angle.last_angle1_idx; + idx_angle2 = hIsmMetaData->orientation_angle.last_angle2_idx; +#else + decode_angle_indices( st0, &( hIsmMetaData->angle[1] ), &flag_abs_orientation ); + idx_azimuth = hIsmMetaData->angle[1].last_azimuth_idx; + idx_elevation = hIsmMetaData->angle[1].last_elevation_idx; +#endif +#ifdef FIX_379_EXT_METADATA +#ifdef FIX_379_ANGLE + yaw = ism_dequant_meta( idx_angle1, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + pitch = ism_dequant_meta( idx_angle2, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#else + yaw = ism_dequant_meta( idx_azimuth, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + pitch = ism_dequant_meta( idx_elevation, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#endif +#else + hIsmMetaData->yaw = ism_dequant_meta( idx_azimuth, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + hIsmMetaData->pitch = ism_dequant_meta( idx_elevation, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#endif - /* read until the stop bit */ - while ( ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) && ( get_next_indice( st0, 1 ) == 1 ) ) + idx_radius = decode_radius( st0, &hIsmMetaData->last_radius_idx, &flag_abs_radius ); +#ifdef FIX_379_EXT_METADATA + radius = usdequant( idx_radius, ISM_RADIUS_MIN, ISM_RADIUS_DELTA ); +#else + hIsmMetaData->radius = usdequant( idx_radius, ISM_RADIUS_MIN, ISM_RADIUS_DELTA ); +#endif +#ifdef FIX_379_EXT_METADATA + if ( *ism_extmeta_active == 1 ) { - diff++; - nbits_diff_elevation++; + hIsmMetaData->yaw = yaw; + hIsmMetaData->pitch = pitch; + hIsmMetaData->radius = radius; } - - if ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) +#endif + } + else + { +#ifdef FIX_379_EXT_METADATA + if ( *ism_extmeta_active == 0 ) { - /* count stop bit */ - nbits_diff_elevation++; + hIsmMetaData->yaw = 0.0f; + hIsmMetaData->pitch = 0.0f; + hIsmMetaData->radius = 1.0f; } +#else + hIsmMetaData->radius = 1.0f; +#endif } - - idx_elevation = hIsmMetaData->last_elevation_idx + sgn * diff; - } - - /* sanity check in case of FER or BER */ - if ( idx_elevation < 0 || idx_elevation > ( 1 << ISM_ELEVATION_NBITS ) - 1 ) - { - idx_elevation = hIsmMetaData->last_elevation_idx; } - - /* Elevation dequantization */ - if ( ism_mode == ISM_MODE_PARAM ) - { - hParamIsm->ele_index[ch] = idx_elevation; - } - else /* ISM_MODE_DISC */ - { - hIsmMetaData->elevation = ism_dequant_meta( idx_elevation, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); - } - - /*----------------------------------------------------------------* - * Final updates - *----------------------------------------------------------------*/ - - /* updates */ - hIsmMetaData->last_azimuth_idx = idx_azimuth; - hIsmMetaData->last_elevation_idx = idx_elevation; +#ifdef DISCRETE_ISM_DTX_CNG + /* save for smoothing metadata evolution */ + hIsmMetaData->last_true_azimuth = hIsmMetaData->azimuth; + hIsmMetaData->last_true_elevation = hIsmMetaData->elevation; +#endif } /* save number of metadata bits read */ @@ -421,12 +537,18 @@ ivas_error ivas_ism_metadata_dec( } else /* BFI */ { - /* "*nISms", "hIsmMeta->azimuth" and "hIsmMeta->elevation" are recycled from the last frame */ - for ( ch = 0; ch < *nchan_transport; ch++ ) +#ifndef NCHAN_ISM_PARAMETER + /* "nchan_ism", "hIsmMeta->azimuth" and "hIsmMeta->elevation" are recycled from the last frame */ + if ( ism_mode == ISM_MODE_PARAM ) { - hIsmMeta[ch]->ism_metadata_flag = hIsmMeta[ch]->last_ism_metadata_flag; + nchan_ism = hParamIsm->num_obj; } - for ( ; ch < num_obj; ch++ ) + else if ( ism_mode == ISM_MODE_DISC ) + { + nchan_ism = *nchan_transport; + } +#endif + for ( ch = 0; ch < nchan_ism; ch++ ) { hIsmMeta[ch]->last_ism_metadata_flag = hIsmMeta[ch]->ism_metadata_flag; } @@ -435,27 +557,39 @@ ivas_error ivas_ism_metadata_dec( if ( ism_mode == ISM_MODE_PARAM ) { - for ( ch = 0; ch < num_obj; ch++ ) + for ( ch = 0; ch < nchan_ism; ch++ ) { hParamIsm->azi_index[ch] = hParamIsm->azi_index[ch] + hParamIsm->last_az_sgn[ch] * hParamIsm->last_az_diff[ch]; - /*hParamIsm->azi_index[ch] = hParamIsm->azi_index[ch] % hParamIsm->az_alpha[ch];*/ - hParamIsm->azi_index[ch] = hParamIsm->azi_index[ch]; hParamIsm->ele_index[ch] = hParamIsm->ele_index[ch] + hParamIsm->last_el_sgn[ch] * hParamIsm->last_el_diff[ch]; - /*hParamIsm->ele_index[ch] = hParamIsm->ele_index[ch] % hParamIsm->ele_alpha;*/ - hParamIsm->ele_index[ch] = hParamIsm->ele_index[ch]; - hIsmMeta[ch]->last_azimuth_idx = hParamIsm->azi_index[ch]; - hIsmMeta[ch]->last_elevation_idx = hParamIsm->ele_index[ch]; +#ifdef FIX_379_ANGLE + hIsmMeta[ch]->position_angle.last_angle1_idx = hParamIsm->azi_index[ch]; + hIsmMeta[ch]->position_angle.last_angle2_idx = hParamIsm->ele_index[ch]; +#else + hIsmMeta[ch]->angle[0].last_azimuth_idx = hParamIsm->azi_index[ch]; + hIsmMeta[ch]->angle[0].last_elevation_idx = hParamIsm->ele_index[ch]; +#endif } } } +#ifdef DISCRETE_ISM_DTX_CNG + if ( hISMDTX.ism_dtx_hangover_cnt < IVAS_ISM_DTX_HO_MAX ) + { + ism_metadata_smooth( hIsmMeta, ism_total_brate, nchan_ism ); + hISMDTX.ism_dtx_hangover_cnt += 1; + } +#endif + /*----------------------------------------------------------------* * Configuration and decision about bitrates per channel *----------------------------------------------------------------*/ if ( !bfi ) { - ivas_ism_config( ism_total_brate, *nchan_transport, num_obj, hIsmMeta, localVAD, ism_imp, element_brate, total_brate, nb_bits_metadata ); + if ( ( error = ivas_ism_config( ism_total_brate, *nchan_transport, nchan_ism, hIsmMeta, localVAD, ism_imp, element_brate, total_brate, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } for ( ch = 0; ch < *nchan_transport; ch++ ) { @@ -474,7 +608,7 @@ ivas_error ivas_ism_metadata_dec( hSCE[ch]->hCoreCoder[0]->total_brate = total_brate[ch]; } - for ( ; ch < num_obj; ch++ ) + for ( ; ch < nchan_ism; ch++ ) { hIsmMeta[ch]->last_ism_metadata_flag = hIsmMeta[ch]->ism_metadata_flag; } @@ -483,58 +617,647 @@ ivas_error ivas_ism_metadata_dec( { for ( ch = 0; ch < *nchan_transport; ch++ ) { - hSCE[ch]->element_brate = hSCE[ch]->last_element_brate; hSCE[ch]->hCoreCoder[0]->total_brate = hSCE[ch]->hCoreCoder[0]->last_total_brate; } } + /*----------------------------------------------------------------* + * Set bitsream pointers + *----------------------------------------------------------------*/ + /* set the bitstream pointer to its original position */ st0->bit_stream = bstr_orig; st0->next_bit_pos = next_bit_pos_orig; - /* set bitstream pointers for each ISm */ + /* set bitstream pointers for each ISM */ for ( ch = 1; ch < *nchan_transport; ch++ ) { hSCE[ch]->hCoreCoder[0]->bit_stream = hSCE[ch - 1]->hCoreCoder[0]->bit_stream + ( hSCE[ch - 1]->hCoreCoder[0]->total_brate / FRAMES_PER_SEC ); } - wmops_sub_end(); +#ifdef DISCRETE_ISM_DTX_CNG + /*----------------------------------------------------------------* + * Updates + *----------------------------------------------------------------*/ + + set_s( md_diff_flag, 1, nchan_ism ); + + update_last_metadata( nchan_ism, hIsmMeta, md_diff_flag ); +#endif + + for ( ch = 0; ch < *nchan_transport; ch++ ) + { + hSCE[ch]->hCoreCoder[0]->cng_ism_flag = 0; + } + + pop_wmops(); - return error; + return IVAS_ERR_OK; } /*------------------------------------------------------------------------- - * create_ism_metadata_dec() + * ivas_ism_metadata_dec_create() * - * Create, allocate, initialize and configure IVAS decoder ISM handles + * Create, allocate, initialize and configure IVAS decoder ISM metadata handles *-------------------------------------------------------------------------*/ -ivas_error create_ism_metadata_dec( +ivas_error ivas_ism_metadata_dec_create( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t n_ISms, /* i : number of objects */ int32_t element_brate_tmp[] /* o : element bitrate per object */ ) { int16_t ch; + ivas_error error; - /* allocate ISm metadata handles */ + /* allocate ISM metadata handles */ for ( ch = 0; ch < MAX_NUM_OBJECTS; ch++ ) { - if ( ( st_ivas->hIsmMetaData[ch] = (ISM_METADATA_HANDLE) count_malloc( sizeof( ISM_METADATA_FRAME ) ) ) == NULL ) + if ( ( st_ivas->hIsmMetaData[ch] = (ISM_METADATA_HANDLE) malloc( sizeof( ISM_METADATA_FRAME ) ) ) == NULL ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISm MetaData\n" ) ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM MetaData\n" ) ); } st_ivas->hIsmMetaData[ch]->last_ism_metadata_flag = 0; - st_ivas->hIsmMetaData[ch]->last_azimuth_idx = 0; - st_ivas->hIsmMetaData[ch]->last_elevation_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); +#ifdef FIX_379_ANGLE + st_ivas->hIsmMetaData[ch]->position_angle.last_angle1_idx = 0; + st_ivas->hIsmMetaData[ch]->position_angle.last_angle2_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); + st_ivas->hIsmMetaData[ch]->orientation_angle.last_angle1_idx = 0; + st_ivas->hIsmMetaData[ch]->orientation_angle.last_angle2_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); +#else + st_ivas->hIsmMetaData[ch]->angle[0].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[0].last_elevation_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); + st_ivas->hIsmMetaData[ch]->angle[1].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[1].last_elevation_idx = 1 << ( ISM_ELEVATION_NBITS - 1 ); +#endif + st_ivas->hIsmMetaData[ch]->last_radius_idx = 8; /* Init to radius 1.0 */ + +#ifdef DISCRETE_ISM_DTX_CNG + st_ivas->hIsmMetaData[ch]->last_true_azimuth = 0; + st_ivas->hIsmMetaData[ch]->last_true_elevation = 0; +#endif ivas_ism_reset_metadata( st_ivas->hIsmMetaData[ch] ); } - ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, n_ISms, n_ISms, NULL, NULL, NULL, element_brate_tmp, NULL, NULL ); + if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, n_ISms, n_ISms, NULL, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + +#ifdef DISCRETE_ISM_DTX_CNG + st_ivas->hISMDTX.ism_dtx_hangover_cnt = IVAS_ISM_DTX_HO_MAX; +#endif return IVAS_ERR_OK; } + + +/*------------------------------------------------------------------------- + * decode_angle_indices() + * + * Decoding of an angle + *-------------------------------------------------------------------------*/ +#ifdef FIX_379_ANGLE + +static void decode_angle_indices( + DEC_CORE_HANDLE st0, /* i/o: bitstream handle */ + ISM_METADATA_ANGLE_HANDLE angle, /* i/o: angle handle */ + int16_t *flag_abs_angle1 /* o : Azimuth/yaw encoding mode */ +) +{ + int16_t idx_angle1, nbits_diff_angle1, diff, sgn; + int16_t idx_angle2, nbits_diff_angle2; + + /*----------------------------------------------------------------* + * Azimuth/yaw decoding and dequantization + *----------------------------------------------------------------*/ + + /* Decode azimuth/yaw index */ + if ( get_next_indice( st0, 1 ) == 1 ) /* azimuth_abs_flag */ + { + idx_angle1 = get_next_indice( st0, ISM_AZIMUTH_NBITS ); + *flag_abs_angle1 = 1; + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_angle1 = 1; + } + else + { + nbits_diff_angle1 = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_angle1++; + + /* read until the stop bit */ + while ( ( nbits_diff_angle1 < ISM_AZIMUTH_NBITS - 1 ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_angle1++; + } + + if ( nbits_diff_angle1 < ISM_AZIMUTH_NBITS - 1 ) + { + /* count stop bit */ + nbits_diff_angle1++; + } + } + idx_angle1 = angle->last_angle1_idx + sgn * diff; + } + + /* azimuth/yaw is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ + if ( idx_angle1 > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_angle1 -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* +180° -> -180° */ + } + else if ( idx_angle1 < 0 ) + { + idx_angle1 += ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* -180° -> +180° */ + } + + /* +180° == -180° */ + if ( idx_angle1 == ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_angle1 = 0; + } + + /* sanity check in case of FER or BER */ + if ( idx_angle1 < 0 || idx_angle1 > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_angle1 = angle->last_angle1_idx; + } + + /*----------------------------------------------------------------* + * Elevation/pitch decoding and dequantization + *----------------------------------------------------------------*/ + + /* Decode elevation/pitch index */ + if ( *flag_abs_angle1 == 0 && get_next_indice( st0, 1 ) == 1 ) /* elevation_abs_flag */ + { + idx_angle2 = get_next_indice( st0, ISM_ELEVATION_NBITS ); + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_angle2 = 1; + } + else + { + nbits_diff_angle2 = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_angle2++; + + /* read until the stop bit */ + while ( ( nbits_diff_angle2 < ISM_ELEVATION_NBITS ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_angle2++; + } + + if ( nbits_diff_angle2 < ISM_ELEVATION_NBITS ) + { + /* count stop bit */ + nbits_diff_angle2++; + } + } + + idx_angle2 = angle->last_angle2_idx + sgn * diff; + } + + /* sanity check in case of FER or BER */ + if ( idx_angle2 < 0 || idx_angle2 > ( 1 << ISM_ELEVATION_NBITS ) - 1 ) + { + idx_angle2 = angle->last_angle2_idx; + } + + /*----------------------------------------------------------------* + * Final updates + *----------------------------------------------------------------*/ + + angle->last_angle1_idx = idx_angle1; + angle->last_angle2_idx = idx_angle2; + + return; +} + +#else + +static void decode_angle_indices( + DEC_CORE_HANDLE st0, /* i/o: bitstream handle */ + ISM_METADATA_ANGLE_HANDLE angle, /* i/o: angle handle */ + int16_t *flag_abs_azimuth /* o : Azimuth encoding mode */ +) +{ + int16_t idx_azimuth, nbits_diff_azimuth, diff, sgn; + int16_t idx_elevation, nbits_diff_elevation; + + /*----------------------------------------------------------------* + * Azimuth decoding and dequantization + *----------------------------------------------------------------*/ + + /* Decode azimuth index */ + if ( get_next_indice( st0, 1 ) == 1 ) /* azimuth_abs_flag */ + { + idx_azimuth = get_next_indice( st0, ISM_AZIMUTH_NBITS ); + *flag_abs_azimuth = 1; + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_azimuth = 1; + } + else + { + nbits_diff_azimuth = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_azimuth++; + + /* read until the stop bit */ + while ( ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_azimuth++; + } + + if ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) + { + /* count stop bit */ + nbits_diff_azimuth++; + } + } + idx_azimuth = angle->last_azimuth_idx + sgn * diff; + } + + /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ + if ( idx_azimuth > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_azimuth -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* +180° -> -180° */ + } + else if ( idx_azimuth < 0 ) + { + idx_azimuth += ( 1 << ISM_AZIMUTH_NBITS ) - 1; /* -180° -> +180° */ + } + + /* +180° == -180° */ + if ( idx_azimuth == ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_azimuth = 0; + } + + /* sanity check in case of FER or BER */ + if ( idx_azimuth < 0 || idx_azimuth > ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) + { + idx_azimuth = angle->last_azimuth_idx; + } + + /*----------------------------------------------------------------* + * Elevation decoding and dequantization + *----------------------------------------------------------------*/ + + /* Decode elevation index */ + if ( *flag_abs_azimuth == 0 && get_next_indice( st0, 1 ) == 1 ) /* elevation_abs_flag */ + { + idx_elevation = get_next_indice( st0, ISM_ELEVATION_NBITS ); + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_elevation = 1; + } + else + { + nbits_diff_elevation = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_elevation++; + + /* read until the stop bit */ + while ( ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_elevation++; + } + + if ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) + { + /* count stop bit */ + nbits_diff_elevation++; + } + } + + idx_elevation = angle->last_elevation_idx + sgn * diff; + } + + /* sanity check in case of FER or BER */ + if ( idx_elevation < 0 || idx_elevation > ( 1 << ISM_ELEVATION_NBITS ) - 1 ) + { + idx_elevation = angle->last_elevation_idx; + } + + /*----------------------------------------------------------------* + * Final updates + *----------------------------------------------------------------*/ + + angle->last_azimuth_idx = idx_azimuth; + angle->last_elevation_idx = idx_elevation; + + return; +} + +#endif + + +/*------------------------------------------------------------------------- + * decode_radius() + * + * Radius decoding and dequantization + *-------------------------------------------------------------------------*/ + +static int16_t decode_radius( + DEC_CORE_HANDLE st0, /* i/o: bitstream handle */ + int16_t *last_radius_idx, /* i/o: last radius index */ + int16_t *flag_abs_radius /* o : Radius encoding mode */ +) +{ + int16_t idx_radius, nbits_diff_radius, diff, sgn; + + /* Decode radius index */ + if ( get_next_indice( st0, 1 ) == 1 ) /* elevation_abs_flag */ + { + *flag_abs_radius = 1; + idx_radius = get_next_indice( st0, ISM_RADIUS_NBITS ); + } + else + { + diff = 0; + sgn = 1; + + if ( get_next_indice( st0, 1 ) == 0 ) + { + nbits_diff_radius = 1; + } + else + { + nbits_diff_radius = 1; + + if ( get_next_indice( st0, 1 ) == 1 ) /* negative sign */ + { + sgn = -1; + } + + nbits_diff_radius++; + + /* read until the stop bit */ + while ( ( nbits_diff_radius < ISM_RADIUS_NBITS ) && ( get_next_indice( st0, 1 ) == 1 ) ) + { + diff++; + nbits_diff_radius++; + } + + if ( nbits_diff_radius < ISM_RADIUS_NBITS ) + { + /* count stop bit */ + nbits_diff_radius++; + } + } + idx_radius = *last_radius_idx + sgn * diff; + } + + /* sanity check in case of FER or BER */ + if ( idx_radius < 0 || idx_radius > ( 1 << ISM_RADIUS_NBITS ) - 1 ) + { + idx_radius = *last_radius_idx; + } + + /* Final updates */ + *last_radius_idx = idx_radius; + + return idx_radius; +} + + +#ifdef DISCRETE_ISM_DTX_CNG +/*-------------------------------------------------------------------* + * ivas_ism_metadata_sid_dec() + * + * Decode ISM metadata in SID frame + *-------------------------------------------------------------------*/ + +void ivas_ism_metadata_sid_dec( + SCE_DEC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int32_t ism_total_brate, /* i : ISms total bitrate */ + const int16_t bfi, /* i : bfi flag */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t nchan_transport, /* i : number of transport channels*/ + const ISM_MODE ism_mode, /* i : ISM mode */ + int16_t *flag_noisy_speech, /* o : noisy speech flag */ + int16_t *sce_id_dtx, /* o : SCE DTX ID */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + int16_t nb_bits_metadata[] /* o : number of metadata bits */ +) +{ + int16_t i, ch, last_bit_pos; + float q_step, q_step_border; + int16_t idx, idx_azimuth, idx_elevation; + int16_t nBits_azimuth, nBits_elevation, nBits_coh, nBits_sce_id; + int16_t md_diff_flag[MAX_NUM_OBJECTS]; + ISM_MODE ism_mode_bstr; + DEC_CORE_HANDLE st0; + ISM_METADATA_HANDLE hIsmMetaData; + int16_t next_bit_pos_orig; + uint16_t bstr_meta[IVAS_SID_5k2 / FRAMES_PER_SEC], *bstr_orig; + + if ( ism_total_brate == FRAME_NO_DATA ) + { + ism_metadata_smooth( hIsmMeta, ism_total_brate, nchan_ism ); + + return; + } + + /* initialization */ + st0 = hSCE[0]->hCoreCoder[0]; + + last_bit_pos = (int16_t) ( ( ism_total_brate / FRAMES_PER_SEC ) - 1 - SID_FORMAT_NBITS ); + bstr_orig = st0->bit_stream; + next_bit_pos_orig = st0->next_bit_pos; + st0->next_bit_pos = 0; + + /* reverse the bitstream for easier reading of indices */ + for ( i = 0; i < min( MAX_BITS_METADATA, last_bit_pos ); i++ ) + { + bstr_meta[i] = st0->bit_stream[last_bit_pos - i]; + } + st0->bit_stream = bstr_meta; + st0->total_brate = ism_total_brate; /* needed for BER detection in get_next_indice() */ + + if ( !bfi ) + { + /*----------------------------------------------------------------* + * ISm common signaling + *----------------------------------------------------------------*/ + + /* number of objects was already read in ivas_ism_get_dtx_dec() */ + /* update the position in the bitstream */ + st0->next_bit_pos += nchan_ism; + + /* read SID metadata flag( one per object ) */ + for ( ch = 0; ch < nchan_ism; ch++ ) + { + md_diff_flag[ch] = get_next_indice( st0, 1 ); + } + + /*----------------------------------------------------------------* + * Set quantization bits based on the number of coded objects + *----------------------------------------------------------------*/ + + ivas_get_ism_sid_quan_bitbudget( nchan_ism, &nBits_azimuth, &nBits_elevation, &q_step, &q_step_border, &nBits_coh, &nBits_sce_id ); + + /*----------------------------------------------------------------* + * Spatial parameters, loop over TCs - 1 + *----------------------------------------------------------------*/ + + *flag_noisy_speech = 0; + *sce_id_dtx = 0; + + /* write ISM mode flag to explicitly signal number of spatial parameters */ + if ( nchan_ism > 2 ) + { + idx = get_next_indice( st0, 1 ); + ism_mode_bstr = (ISM_MODE) ( idx + 1 ); + /* note: ISM mode was already read and used for configuration in in ivas_ism_dtx_dec() */ + + if ( ism_mode_bstr == ISM_MODE_PARAM ) + { + /* read noisy speech flag */ + *flag_noisy_speech = get_next_indice( st0, 1 ); + nBits_sce_id = 1; + } + } + + if ( nchan_transport > 1 ) + { + /* read sce id */ + *sce_id_dtx = get_next_indice( st0, nBits_sce_id ); + + /* decode the coherence */ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + if ( ch == *sce_id_dtx ) + { + hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence = 1.0f; + continue; + } + + idx = get_next_indice( st0, nBits_coh ); + hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence = (float) ( idx ) / (float) ( ( 1 << nBits_coh ) - 1 ); + } + } + else + { + *sce_id_dtx = 0; + } + + if ( ism_mode == ISM_MODE_PARAM ) + { + hSCE[*sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence = hSCE[!*sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence; + } + + /*----------------------------------------------------------------* + * Metadata decoding and dequantization, loop over all objects + *----------------------------------------------------------------*/ + + for ( ch = 0; ch < nchan_ism; ch++ ) + { + hIsmMetaData = hIsmMeta[ch]; + + if ( md_diff_flag[ch] == 1 ) + { + /* Azimuth decoding */ + idx_azimuth = get_next_indice( st0, nBits_azimuth ); + hIsmMetaData->azimuth = ism_dequant_meta( idx_azimuth, ism_azimuth_borders, q_step, q_step_border, 1 << nBits_azimuth ); + + /* Elevation decoding */ + idx_elevation = get_next_indice( st0, nBits_elevation ); + hIsmMetaData->elevation = ism_dequant_meta( idx_elevation, ism_elevation_borders, q_step, q_step_border, 1 << nBits_elevation ); + + /* update last indexes to correspond to active frames coding */ + if ( nBits_azimuth > ISM_AZIMUTH_NBITS ) + { +#ifdef FIX_379_ANGLE + hIsmMetaData->position_angle.last_angle1_idx = idx_azimuth >> ( nBits_azimuth - ISM_AZIMUTH_NBITS ); + hIsmMetaData->position_angle.last_angle2_idx = idx_elevation >> ( nBits_elevation - ISM_ELEVATION_NBITS ); +#else + hIsmMetaData->angle[0].last_azimuth_idx = idx_azimuth >> ( nBits_azimuth - ISM_AZIMUTH_NBITS ); + hIsmMetaData->angle[0].last_elevation_idx = idx_elevation >> ( nBits_elevation - ISM_ELEVATION_NBITS ); +#endif + } + else + { +#ifdef FIX_379_ANGLE + hIsmMetaData->position_angle.last_angle1_idx = idx_azimuth << ( ISM_AZIMUTH_NBITS - nBits_azimuth ); + hIsmMetaData->position_angle.last_angle2_idx = idx_elevation << ( ISM_ELEVATION_NBITS - nBits_elevation ); +#else + hIsmMetaData->angle[0].last_azimuth_idx = idx_azimuth << ( ISM_AZIMUTH_NBITS - nBits_azimuth ); + hIsmMetaData->angle[0].last_elevation_idx = idx_elevation << ( ISM_ELEVATION_NBITS - nBits_elevation ); + +#endif + } + + /* save for smoothing metadata evolution */ + hIsmMetaData->last_true_azimuth = hIsmMetaData->azimuth; + hIsmMetaData->last_true_elevation = hIsmMetaData->elevation; + } + } + + /* take into account padding bits as metadata bits to keep later bitrate checks valid */ + nb_bits_metadata[*sce_id_dtx] = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; + + /* set the bitstream pointer to its original position */ + st0->bit_stream = bstr_orig; + st0->next_bit_pos = next_bit_pos_orig; + } + + /* smooth the metadata evolution */ + ism_metadata_smooth( hIsmMeta, ism_total_brate, nchan_ism ); + + return; +} +#endif diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index 406a4890cfe4ad04f31d736eb14c6526d2eb1307..f66323d8a4f038b0a054d6678302cc758603f7cd 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,13 +35,14 @@ #include #include "options.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "prot.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -50,6 +51,10 @@ static void ivas_param_ism_dec_dequant_DOA( DIRAC_DEC_HANDLE hDirAC /* i/o: decoder DirAC handle */ +#ifdef NCHAN_ISM_PARAMETER + , + const int16_t nchan_ism /* i : number of ISM channels */ +#endif ) { int16_t i; @@ -57,13 +62,21 @@ static void ivas_param_ism_dec_dequant_DOA( hParamIsm = hDirAC->hParamIsm; +#ifdef NCHAN_ISM_PARAMETER + assert( nchan_ism <= MAX_NUM_OBJECTS ); +#else assert( hParamIsm->num_obj <= MAX_NUM_OBJECTS ); +#endif /* Get the azimuth and elevation values */ +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_ism; i++ ) +#else for ( i = 0; i < hParamIsm->num_obj; i++ ) +#endif { - hDirAC->azimuth_values[i] = ism_dequant_meta( hParamIsm->azi_index[i], ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); - hDirAC->elevation_values[i] = ism_dequant_meta( hParamIsm->ele_index[i], ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); + hDirAC->azimuth_values[i] = ism_dequant_meta( hParamIsm->azi_index[i], ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + hDirAC->elevation_values[i] = ism_dequant_meta( hParamIsm->ele_index[i], ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); } return; @@ -156,7 +169,11 @@ static void ivas_ism_get_proto_matrix( static void ivas_param_ism_compute_mixing_matrix( - DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ +#ifdef NCHAN_ISM_PARAMETER + const int16_t nchan_ism, /* i : number of ISM channels */ +#endif + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + ISM_DTX_DATA_DEC hISMDTX, /* i : ISM DTX handle */ float Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer_in[PARAM_ISM_MAX_DMX][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float direct_response[MAX_NUM_OBJECTS][PARAM_ISM_MAX_CHAN], @@ -181,12 +198,20 @@ static void ivas_param_ism_compute_mixing_matrix( proto_matrix = hDirAC->hParamIsmRendering->proto_matrix; +#ifdef NCHAN_ISM_PARAMETER + assert( ( nchan_ism == 3 ) || ( nchan_ism == 4 ) ); +#else assert( ( hDirAC->hParamIsm->num_obj == 3 ) || ( hDirAC->hParamIsm->num_obj == 4 ) ); +#endif assert( nchan_transport == 2 ); - if ( hDirAC->hParamIsm->flag_noisy_speech ) + if ( hDirAC->hParamIsm->flag_noisy_speech || hISMDTX.dtx_flag ) { +#ifdef NCHAN_ISM_PARAMETER + num_wave = nchan_ism; +#else num_wave = hDirAC->hParamIsm->num_obj; +#endif } else { @@ -206,7 +231,7 @@ static void ivas_param_ism_compute_mixing_matrix( { set_zero( cy_diag_tmp[w], nchan_out_woLFE ); - if ( hDirAC->hParamIsm->flag_noisy_speech ) + if ( hDirAC->hParamIsm->flag_noisy_speech || hISMDTX.dtx_flag ) { dir_res_ptr = direct_response[w]; } @@ -245,9 +270,13 @@ static void ivas_param_ism_compute_mixing_matrix( set_zero( cy_diag, nchan_out_woLFE ); for ( w = 0; w < num_wave; w++ ) { - if ( hDirAC->hParamIsm->flag_noisy_speech ) + if ( hDirAC->hParamIsm->flag_noisy_speech || hISMDTX.dtx_flag ) { +#ifdef NCHAN_ISM_PARAMETER + direct_power[w] = ( 1.0f / nchan_ism ) * ref_power; +#else direct_power[w] = ( 1.0f / hDirAC->hParamIsm->num_obj ) * ref_power; +#endif } else { @@ -326,11 +355,11 @@ static ivas_error ivas_param_ism_rendering_init( } /* memory allocation for proto matrix and interpolator */ - if ( ( hParamIsmRendering->proto_matrix = (float *) count_malloc( hOutSetup.nchan_out_woLFE * nchan_transport * sizeof( float ) ) ) == NULL ) + if ( ( hParamIsmRendering->proto_matrix = (float *) malloc( hOutSetup.nchan_out_woLFE * nchan_transport * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for proto matrix\n" ) ); } - if ( ( hParamIsmRendering->interpolator = (float *) count_malloc( subframe_nbslots * sizeof( float ) ) ) == NULL ) + if ( ( hParamIsmRendering->interpolator = (float *) malloc( subframe_nbslots * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for interpolator\n" ) ); } @@ -393,35 +422,41 @@ ivas_error ivas_param_ism_dec_open( IVAS_OUTPUT_SETUP hOutSetup; AUDIO_CONFIG output_config; int32_t output_Fs; +#ifndef NCHAN_ISM_PARAMETER int16_t nchan_out; +#endif ivas_error error; error = IVAS_ERR_OK; - wmops_sub_start( "ivas_param_ism_dec_open" ); + push_wmops( "ivas_param_ism_dec_open" ); /*-----------------------------------------------------------------* * prepare library opening *-----------------------------------------------------------------*/ - if ( ( hDirAC = (DIRAC_DEC_HANDLE) count_malloc( sizeof( DIRAC_DEC_DATA ) ) ) == NULL ) + if ( ( hDirAC = (DIRAC_DEC_HANDLE) malloc( sizeof( DIRAC_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } /* Assign memory to Param Object handle */ - if ( ( hDirAC->hParamIsm = (PARAM_ISM_CONFIG_HANDLE) count_malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL ) + if ( ( hDirAC->hParamIsm = (PARAM_ISM_CONFIG_HANDLE) malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM\n" ) ); } - if ( ( hDirAC->hParamIsmRendering = (PARAM_ISM_RENDERING_HANDLE) count_malloc( sizeof( PARAM_ISM_RENDERING_DATA ) ) ) == NULL ) + if ( ( hDirAC->hParamIsmRendering = (PARAM_ISM_RENDERING_HANDLE) malloc( sizeof( PARAM_ISM_RENDERING_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); } output_Fs = st_ivas->hDecoderConfig->output_Fs; output_config = st_ivas->hDecoderConfig->output_config; +#ifdef NCHAN_ISM_PARAMETER + + ivas_param_ism_config( hDirAC->hParamIsm, st_ivas->nchan_ism ); +#else nchan_out = st_ivas->hDecoderConfig->nchan_out; if ( output_config == AUDIO_CONFIG_EXTERNAL ) @@ -433,6 +468,7 @@ ivas_error ivas_param_ism_dec_open( hDirAC->hParamIsm->num_obj = MAX_NUM_OBJECTS; } ivas_param_ism_config( hDirAC->hParamIsm ); +#endif /*-----------------------------------------------------------------* * set input parameters @@ -464,7 +500,11 @@ ivas_error ivas_param_ism_dec_open( if ( output_config == AUDIO_CONFIG_EXTERNAL ) { /* nchan_out is essential for memory initialization for CLDFB Synthesis */ +#ifdef NCHAN_ISM_PARAMETER + st_ivas->hIntSetup.nchan_out_woLFE = st_ivas->nchan_ism; +#else st_ivas->hIntSetup.nchan_out_woLFE = hDirAC->hParamIsm->num_obj; +#endif st_ivas->hIntSetup.is_loudspeaker_setup = 1; } @@ -500,41 +540,114 @@ ivas_error ivas_param_ism_dec_open( if ( ( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) { hDirAC->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; - hDirAC->azimuth = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->elevation = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->azimuth2 = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->elevation2 = (int16_t **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ); - hDirAC->energy_ratio1 = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->spreadCoherence = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->energy_ratio2 = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->spreadCoherence2 = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); - hDirAC->surroundingCoherence = (float **) count_malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ); + if ( ( hDirAC->azimuth = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->elevation = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->azimuth2 = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->elevation2 = (int16_t **) malloc( hDirAC->dirac_md_buffer_length * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->energy_ratio1 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->spreadCoherence = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->energy_ratio2 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->spreadCoherence2 = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + + if ( ( hDirAC->surroundingCoherence = (float **) malloc( hDirAC->dirac_md_buffer_length * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } + for ( i = 0; i < hDirAC->dirac_md_buffer_length; i++ ) { - hDirAC->azimuth[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + if ( ( hDirAC->azimuth[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_s( hDirAC->azimuth[i], 0, hDirAC->num_freq_bands ); - hDirAC->elevation[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + + if ( ( hDirAC->elevation[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_s( hDirAC->elevation[i], 0, hDirAC->num_freq_bands ); - hDirAC->azimuth2[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + + if ( ( hDirAC->azimuth2[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_s( hDirAC->azimuth2[i], 0, hDirAC->num_freq_bands ); - hDirAC->elevation2[i] = (int16_t *) count_malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ); + + if ( ( hDirAC->elevation2[i] = (int16_t *) malloc( hDirAC->num_freq_bands * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_s( hDirAC->elevation2[i], 0, hDirAC->num_freq_bands ); - hDirAC->energy_ratio1[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->energy_ratio1[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_f( hDirAC->energy_ratio1[i], 0.0f, hDirAC->num_freq_bands ); - hDirAC->spreadCoherence[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->spreadCoherence[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_f( hDirAC->spreadCoherence[i], 0.0f, hDirAC->num_freq_bands ); - hDirAC->energy_ratio2[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->energy_ratio2[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_f( hDirAC->energy_ratio2[i], 0.0f, hDirAC->num_freq_bands ); - hDirAC->spreadCoherence2[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->spreadCoherence2[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_f( hDirAC->spreadCoherence2[i], 0.0f, hDirAC->num_freq_bands ); - hDirAC->surroundingCoherence[i] = (float *) count_malloc( hDirAC->num_freq_bands * sizeof( float ) ); + + if ( ( hDirAC->surroundingCoherence[i] = (float *) malloc( hDirAC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM Rendering handle\n" ) ); + } set_f( hDirAC->surroundingCoherence[i], 0.0f, hDirAC->num_freq_bands ); } } + st_ivas->hISMDTX.dtx_flag = 0; + st_ivas->hDirAC = hDirAC; - wmops_sub_end(); + pop_wmops(); return error; } @@ -546,16 +659,24 @@ ivas_error ivas_param_ism_dec_open( *-------------------------------------------------------------------------*/ void ivas_param_ism_dec_close( - DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ - AUDIO_CONFIG output_config /* i : output audio configuration */ + DIRAC_DEC_HANDLE *hDirAC_out, /* i/o: decoder DirAC handle */ + AUDIO_CONFIG output_config /* i : output audio configuration */ ) { int16_t i; + DIRAC_DEC_HANDLE hDirAC; + + if ( hDirAC_out == NULL || *hDirAC_out == NULL ) + { + return; + } + + hDirAC = *hDirAC_out; /* Config & CLDFB */ if ( hDirAC->hParamIsm != NULL ) { - count_free( hDirAC->hParamIsm ); + free( hDirAC->hParamIsm ); hDirAC->hParamIsm = NULL; } @@ -565,25 +686,25 @@ void ivas_param_ism_dec_close( { if ( hDirAC->azimuth[i] != NULL ) { - count_free( hDirAC->azimuth[i] ); + free( hDirAC->azimuth[i] ); hDirAC->azimuth[i] = NULL; } if ( hDirAC->elevation[i] != NULL ) { - count_free( hDirAC->elevation[i] ); + free( hDirAC->elevation[i] ); hDirAC->elevation[i] = NULL; } } if ( hDirAC->azimuth != NULL ) { - count_free( hDirAC->azimuth ); + free( hDirAC->azimuth ); hDirAC->azimuth = NULL; } if ( hDirAC->elevation != NULL ) { - count_free( hDirAC->elevation ); + free( hDirAC->elevation ); hDirAC->elevation = NULL; } @@ -593,11 +714,11 @@ void ivas_param_ism_dec_close( { if ( hDirAC->azimuth2[i] != NULL ) { - count_free( hDirAC->azimuth2[i] ); + free( hDirAC->azimuth2[i] ); hDirAC->azimuth2[i] = NULL; } } - count_free( hDirAC->azimuth2 ); + free( hDirAC->azimuth2 ); hDirAC->azimuth2 = NULL; } @@ -607,11 +728,11 @@ void ivas_param_ism_dec_close( { if ( hDirAC->elevation2[i] != NULL ) { - count_free( hDirAC->elevation2[i] ); + free( hDirAC->elevation2[i] ); hDirAC->elevation2[i] = NULL; } } - count_free( hDirAC->elevation2 ); + free( hDirAC->elevation2 ); hDirAC->elevation2 = NULL; } @@ -621,11 +742,11 @@ void ivas_param_ism_dec_close( { if ( hDirAC->energy_ratio1[i] != NULL ) { - count_free( hDirAC->energy_ratio1[i] ); + free( hDirAC->energy_ratio1[i] ); hDirAC->energy_ratio1[i] = NULL; } } - count_free( hDirAC->energy_ratio1 ); + free( hDirAC->energy_ratio1 ); hDirAC->energy_ratio1 = NULL; } @@ -635,11 +756,11 @@ void ivas_param_ism_dec_close( { if ( hDirAC->energy_ratio2[i] != NULL ) { - count_free( hDirAC->energy_ratio2[i] ); + free( hDirAC->energy_ratio2[i] ); hDirAC->energy_ratio2[i] = NULL; } } - count_free( hDirAC->energy_ratio2 ); + free( hDirAC->energy_ratio2 ); hDirAC->energy_ratio2 = NULL; } @@ -649,11 +770,11 @@ void ivas_param_ism_dec_close( { if ( hDirAC->spreadCoherence[i] != NULL ) { - count_free( hDirAC->spreadCoherence[i] ); + free( hDirAC->spreadCoherence[i] ); hDirAC->spreadCoherence[i] = NULL; } } - count_free( hDirAC->spreadCoherence ); + free( hDirAC->spreadCoherence ); hDirAC->spreadCoherence = NULL; } @@ -663,11 +784,11 @@ void ivas_param_ism_dec_close( { if ( hDirAC->spreadCoherence2[i] != NULL ) { - count_free( hDirAC->spreadCoherence2[i] ); + free( hDirAC->spreadCoherence2[i] ); hDirAC->spreadCoherence2[i] = NULL; } } - count_free( hDirAC->spreadCoherence2 ); + free( hDirAC->spreadCoherence2 ); hDirAC->spreadCoherence2 = NULL; } @@ -677,11 +798,11 @@ void ivas_param_ism_dec_close( { if ( hDirAC->surroundingCoherence[i] != NULL ) { - count_free( hDirAC->surroundingCoherence[i] ); + free( hDirAC->surroundingCoherence[i] ); hDirAC->surroundingCoherence[i] = NULL; } } - count_free( hDirAC->surroundingCoherence ); + free( hDirAC->surroundingCoherence ); hDirAC->surroundingCoherence = NULL; } } @@ -691,23 +812,24 @@ void ivas_param_ism_dec_close( /* Param ISM Rendering */ if ( hDirAC->hParamIsmRendering->interpolator != NULL ) { - count_free( hDirAC->hParamIsmRendering->interpolator ); + free( hDirAC->hParamIsmRendering->interpolator ); hDirAC->hParamIsmRendering->interpolator = NULL; } if ( hDirAC->hParamIsmRendering->proto_matrix != NULL ) { - count_free( hDirAC->hParamIsmRendering->proto_matrix ); + free( hDirAC->hParamIsmRendering->proto_matrix ); hDirAC->hParamIsmRendering->proto_matrix = NULL; } } if ( hDirAC->hParamIsmRendering != NULL ) { - count_free( hDirAC->hParamIsmRendering ); + free( hDirAC->hParamIsmRendering ); hDirAC->hParamIsmRendering = NULL; } - count_free( hDirAC ); + free( *hDirAC_out ); + *hDirAC_out = NULL; return; } @@ -726,6 +848,7 @@ void ivas_param_ism_dec( { int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; int16_t subframe_idx, slot_idx, index_slot, bin_idx; + int32_t ivas_total_brate; /* CLDFB Input Buffers */ float Cldfb_RealBuffer_in[PARAM_ISM_MAX_DMX][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; @@ -752,7 +875,11 @@ void ivas_param_ism_dec( nchan_transport = st_ivas->nchan_transport; if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) { +#ifdef NCHAN_ISM_PARAMETER + nchan_out = st_ivas->nchan_ism; +#else nchan_out = st_ivas->hDirAC->hParamIsm->num_obj; +#endif nchan_out_woLFE = nchan_out; st_ivas->hDecoderConfig->nchan_out = nchan_out; } @@ -762,19 +889,37 @@ void ivas_param_ism_dec( nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; } + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + hSetup = st_ivas->hIntSetup; - wmops_sub_start( "ivas_param_ism_dec" ); + push_wmops( "ivas_param_ism_dec" ); /* Frame-level Processing */ /* De-quantization */ - ivas_param_ism_dec_dequant_DOA( hDirAC ); - ivas_param_ism_dec_dequant_powrat( hDirAC ); + if ( !( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) ) + { +#ifdef NCHAN_ISM_PARAMETER + ivas_param_ism_dec_dequant_DOA( hDirAC, st_ivas->nchan_ism ); +#else + ivas_param_ism_dec_dequant_DOA( hDirAC ); +#endif + ivas_param_ism_dec_dequant_powrat( hDirAC ); + st_ivas->hISMDTX.dtx_flag = 0; + } + else + { + st_ivas->hISMDTX.dtx_flag = 1; + } /* obtain the direct response using EFAP */ if ( !( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) ) { +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < st_ivas->nchan_ism; i++ ) +#else for ( i = 0; i < hDirAC->hParamIsm->num_obj; i++ ) +#endif { efap_determine_gains( st_ivas->hEFAPdata, direct_response[i], hDirAC->azimuth_values[i], hDirAC->elevation_values[i], EFAP_MODE_EFAP ); } @@ -783,7 +928,11 @@ void ivas_param_ism_dec( { int16_t j; +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < st_ivas->nchan_ism; i++ ) +#else for ( i = 0; i < hDirAC->hParamIsm->num_obj; i++ ) +#endif { for ( j = 0; j < nchan_out_woLFE; j++ ) { @@ -832,7 +981,11 @@ void ivas_param_ism_dec( } /* Compute mixing matrix */ - ivas_param_ism_compute_mixing_matrix( hDirAC, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, direct_response, nchan_transport, nchan_out_woLFE, 0, CLDFB_NO_COL_MAX, mixing_matrix ); +#ifdef NCHAN_ISM_PARAMETER + ivas_param_ism_compute_mixing_matrix( st_ivas->nchan_ism, hDirAC, st_ivas->hISMDTX, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, direct_response, nchan_transport, nchan_out_woLFE, 0, CLDFB_NO_COL_MAX, mixing_matrix ); +#else + ivas_param_ism_compute_mixing_matrix( hDirAC, st_ivas->hISMDTX, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, direct_response, nchan_transport, nchan_out_woLFE, 0, CLDFB_NO_COL_MAX, mixing_matrix ); +#endif /* subframe loop for synthesis*/ for ( subframe_idx = 0; subframe_idx < hDirAC->nb_subframes; subframe_idx++ ) @@ -901,7 +1054,11 @@ void ivas_param_ism_dec( ivas_param_ism_update_mixing_matrix( hDirAC, mixing_matrix, nchan_transport, nchan_out_woLFE ); /* store MetaData parameters */ +#ifdef NCHAN_ISM_PARAMETER + for ( ch = 0; ch < st_ivas->nchan_ism; ch++ ) +#else for ( ch = 0; ch < hDirAC->hParamIsm->num_obj; ch++ ) +#endif { if ( st_ivas->hDirAC->azimuth_values[ch] > 180.0f ) { @@ -915,7 +1072,7 @@ void ivas_param_ism_dec( st_ivas->hIsmMetaData[ch]->elevation = st_ivas->hDirAC->elevation_values[ch]; } - wmops_sub_end(); + pop_wmops(); return; } @@ -938,47 +1095,93 @@ void ivas_param_ism_params_to_masa_param_mapping( int16_t azimuth[2]; int16_t elevation[2]; float power_ratio[2]; + int32_t ivas_total_brate; + hDirAC = st_ivas->hDirAC; nBins = hDirAC->num_freq_bands; - ivas_param_ism_dec_dequant_DOA( hDirAC ); - ivas_param_ism_dec_dequant_powrat( hDirAC ); + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + if ( !( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) ) + { +#ifdef NCHAN_ISM_PARAMETER + ivas_param_ism_dec_dequant_DOA( hDirAC, st_ivas->nchan_ism ); +#else + ivas_param_ism_dec_dequant_DOA( hDirAC ); +#endif + ivas_param_ism_dec_dequant_powrat( hDirAC ); + st_ivas->hISMDTX.dtx_flag = 0; + } + else + { + st_ivas->hISMDTX.dtx_flag = 1; + } + +#ifdef NCHAN_ISM_PARAMETER + if ( st_ivas->nchan_ism > 1 ) +#else if ( hDirAC->hParamIsm->num_obj > 1 ) +#endif { - hDirAC->numSimultaneousDirections = 2; - for ( band_idx = 0; band_idx < hDirAC->hParamIsm->nbands; band_idx++ ) + if ( st_ivas->hISMDTX.dtx_flag ) { - brange[0] = hDirAC->hParamIsm->band_grouping[band_idx]; - brange[1] = hDirAC->hParamIsm->band_grouping[band_idx + 1]; - - azimuth[0] = (int16_t) roundf( hDirAC->azimuth_values[hDirAC->hParamIsm->obj_indices[band_idx][0][0]] ); - elevation[0] = (int16_t) roundf( hDirAC->elevation_values[hDirAC->hParamIsm->obj_indices[band_idx][0][0]] ); - power_ratio[0] = hDirAC->power_ratios[band_idx][0][0]; - - azimuth[1] = (int16_t) roundf( hDirAC->azimuth_values[hDirAC->hParamIsm->obj_indices[band_idx][0][1]] ); - elevation[1] = (int16_t) roundf( hDirAC->elevation_values[hDirAC->hParamIsm->obj_indices[band_idx][0][1]] ); - power_ratio[1] = hDirAC->power_ratios[band_idx][0][1]; + float energy_ratio; + energy_ratio = powf( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence, 2.0f ); + hDirAC->numSimultaneousDirections = 1; + azimuth[0] = (int16_t) roundf( hDirAC->azimuth_values[0] ); + elevation[0] = (int16_t) roundf( hDirAC->elevation_values[0] ); for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) { - for ( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) + for ( bin_idx = 0; bin_idx < nBins; bin_idx++ ) { hDirAC->azimuth[sf_idx][bin_idx] = azimuth[0]; hDirAC->elevation[sf_idx][bin_idx] = elevation[0]; - hDirAC->energy_ratio1[sf_idx][bin_idx] = power_ratio[0]; - hDirAC->azimuth2[sf_idx][bin_idx] = azimuth[1]; - hDirAC->elevation2[sf_idx][bin_idx] = elevation[1]; - hDirAC->energy_ratio2[sf_idx][bin_idx] = power_ratio[1]; + + hDirAC->energy_ratio1[sf_idx][bin_idx] = energy_ratio; + + hDirAC->spreadCoherence[sf_idx][bin_idx] = 0.0f; + hDirAC->surroundingCoherence[sf_idx][bin_idx] = 0.0; } } } - for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + else { - for ( bin_idx = 0; bin_idx < nBins; bin_idx++ ) + hDirAC->numSimultaneousDirections = 2; + for ( band_idx = 0; band_idx < hDirAC->hParamIsm->nbands; band_idx++ ) { - hDirAC->spreadCoherence[sf_idx][bin_idx] = 0.0f; - hDirAC->spreadCoherence2[sf_idx][bin_idx] = 0.0f; - hDirAC->surroundingCoherence[sf_idx][bin_idx] = 0.0; + brange[0] = hDirAC->hParamIsm->band_grouping[band_idx]; + brange[1] = hDirAC->hParamIsm->band_grouping[band_idx + 1]; + + azimuth[0] = (int16_t) roundf( hDirAC->azimuth_values[hDirAC->hParamIsm->obj_indices[band_idx][0][0]] ); + elevation[0] = (int16_t) roundf( hDirAC->elevation_values[hDirAC->hParamIsm->obj_indices[band_idx][0][0]] ); + power_ratio[0] = hDirAC->power_ratios[band_idx][0][0]; + + azimuth[1] = (int16_t) roundf( hDirAC->azimuth_values[hDirAC->hParamIsm->obj_indices[band_idx][0][1]] ); + elevation[1] = (int16_t) roundf( hDirAC->elevation_values[hDirAC->hParamIsm->obj_indices[band_idx][0][1]] ); + power_ratio[1] = hDirAC->power_ratios[band_idx][0][1]; + + for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + for ( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) + { + hDirAC->azimuth[sf_idx][bin_idx] = azimuth[0]; + hDirAC->elevation[sf_idx][bin_idx] = elevation[0]; + hDirAC->energy_ratio1[sf_idx][bin_idx] = power_ratio[0]; + hDirAC->azimuth2[sf_idx][bin_idx] = azimuth[1]; + hDirAC->elevation2[sf_idx][bin_idx] = elevation[1]; + hDirAC->energy_ratio2[sf_idx][bin_idx] = power_ratio[1]; + } + } + } + for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + for ( bin_idx = 0; bin_idx < nBins; bin_idx++ ) + { + hDirAC->spreadCoherence[sf_idx][bin_idx] = 0.0f; + hDirAC->spreadCoherence2[sf_idx][bin_idx] = 0.0f; + hDirAC->surroundingCoherence[sf_idx][bin_idx] = 0.0; + } } } } @@ -1003,77 +1206,143 @@ void ivas_param_ism_params_to_masa_param_mapping( return; } +#ifndef DISCRETE_ISM_DTX_CNG +static void ivas_param_ism_dec_dequantize_DOA_dtx( + int16_t azi_bits, + int16_t ele_bits, + int16_t azi_idx, + int16_t ele_idx, + float *azi_val, + float *ele_val ) +{ + int16_t nbits, npoints, angle_spacing, az_alpha, ele_alpha, tmp_alpha; + + /* Step 1: Determine angle spacing/n_points based on minimum value among elevation/azimuth bits */ + nbits = min( azi_bits, ele_bits ); + + if ( nbits == ISM_ELEVATION_NBITS ) + { + angle_spacing = 5; + } + else + { + angle_spacing = (int16_t) ( ( 180.f / (float) ( 1 << nbits ) ) + 0.5f ); + } + + npoints = (int16_t) ( ( 90 / angle_spacing ) + 0.5f ); + + /* sanity check */ + if ( angle_spacing == 360 ) + { + assert( azi_idx == 0 ); + assert( ele_idx == 0 ); + + *azi_val = 0.f; + *ele_val = 0.f; + return; + } + + /* Get the azimuth and elevation values */ + ele_alpha = 2 * npoints - 1; + assert( ( 0 <= ele_idx ) && ( ele_idx < ele_alpha ) ); + *ele_val = (float) ( ( ele_idx - npoints ) * angle_spacing ); + + az_alpha = 4 * npoints - 1; + assert( ( 0 <= azi_idx ) && ( azi_idx < az_alpha ) ); + tmp_alpha = (int16_t) ( azi_idx * ( 360.f / az_alpha ) ); + + if ( tmp_alpha > 180.0f ) + { + *azi_val = ( (float) tmp_alpha ) - 360.0f; + } + else + { + *azi_val = (float) tmp_alpha; + } + + return; +} + + /*------------------------------------------------------------------------- - * ivas_ism_dec_config() + * ivas_param_ism_metadata_dtx_dec() + * * - * - select ISM format mode - * - reconfigure the ISM format decoder *-------------------------------------------------------------------------*/ -/*! r : ISM format mode */ -ivas_error ivas_ism_dec_config( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const int16_t num_obj /* i : number of objects in the bitstream */ +void ivas_param_ism_metadata_dtx_dec( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { - int32_t ivas_total_brate; - ISM_MODE last_ism_mode; - ivas_error error; - - error = IVAS_ERR_OK; + int16_t azi_idx, ele_idx, i; + int16_t last_bit_pos, next_bit_pos_orig; + uint16_t bstr_meta[IVAS_SID_5k2 / FRAMES_PER_SEC], *bstr_orig; + DEC_CORE_HANDLE st0; + PARAM_ISM_CONFIG_HANDLE hParamIsm; /* Parametric ISM handle */ + int16_t coh_idx; + + if ( st_ivas->hDecoderConfig->ivas_total_brate == FRAME_NO_DATA ) + { + return; + } - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + st0 = st_ivas->hSCE[0]->hCoreCoder[0]; + hParamIsm = st_ivas->hDirAC->hParamIsm; - /* store last frame ISM mode */ - last_ism_mode = st_ivas->ism_mode; + last_bit_pos = (int16_t) ( ( st_ivas->hDecoderConfig->ivas_total_brate / FRAMES_PER_SEC ) - 1 - SID_FORMAT_NBITS ); + bstr_orig = st0->bit_stream; + next_bit_pos_orig = st0->next_bit_pos; + st0->next_bit_pos = 0; - if ( !st_ivas->bfi && ivas_total_brate != IVAS_SID_4k4 && ivas_total_brate != FRAME_NO_DATA ) + /* reverse the bitstream for easier reading of indices */ + for ( i = 0; i < min( MAX_BITS_METADATA, last_bit_pos ); i++ ) { - /* select ISM format mode */ - st_ivas->ism_mode = ivas_ism_mode_select( num_obj, ivas_total_brate ); + bstr_meta[i] = st0->bit_stream[last_bit_pos - i]; + } + st0->bit_stream = bstr_meta; + st0->total_brate = st_ivas->hDecoderConfig->ivas_total_brate; /* needed for BER detection in get_next_indice() */ + + /* number of objects was already read in ivas_ism_get_dtx_dec() */ + /* update the position in the bitstream */ +#ifdef NCHAN_ISM_PARAMETER + st0->next_bit_pos += st_ivas->nchan_ism; +#else + st0->next_bit_pos += hParamIsm->num_obj; +#endif - st_ivas->nchan_transport = num_obj; - if ( st_ivas->ism_mode == ISM_MODE_PARAM ) - { - st_ivas->nchan_transport = 2; - if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) - { - st_ivas->hDecoderConfig->nchan_out = num_obj; - } - } + /* read sce id */ + st_ivas->hISMDTX.sce_id_dtx = get_next_indice( st0, 1 ); - if ( st_ivas->ini_active_frame != 0 ) - { - /* ISM format switching */ - if ( st_ivas->ism_mode != last_ism_mode ) - { - /*ivas_ism_dec_reconfigure( st_ivas );*/ - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "\n\n!!! Error: ISM format switching not supported yet!!!\n\n" ); - } - } - } - else if ( !st_ivas->bfi && ivas_total_brate == IVAS_SID_4k4 ) - { - st_ivas->nchan_transport = num_obj; - } - switch ( num_obj ) + /* read the noisy speech flag */ + hParamIsm->flag_noisy_speech = get_next_indice( st0, 1 ); + + /* decode the coherence */ + coh_idx = get_next_indice( st0, PARAM_ISM_DTX_COH_SCA_BITS ); + st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence = (float) ( coh_idx ) / (float) ( ( 1 << PARAM_ISM_DTX_COH_SCA_BITS ) - 1 ); + st_ivas->hSCE[1]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence; + + /* get the DOA'S */ +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < st_ivas->nchan_ism; i++ ) +#else + for ( i = 0; i < hParamIsm->num_obj; i++ ) +#endif { - case 1: - st_ivas->transport_config = AUDIO_CONFIG_ISM1; - break; - case 2: - st_ivas->transport_config = AUDIO_CONFIG_ISM2; - break; - case 3: - st_ivas->transport_config = AUDIO_CONFIG_ISM3; - break; - case 4: - st_ivas->transport_config = AUDIO_CONFIG_ISM4; - break; - default: - st_ivas->transport_config = AUDIO_CONFIG_INVALID; - break; + /* read from bitstream and dequantize */ + azi_idx = get_next_indice( st0, PARAM_ISM_DTX_AZI_BITS ); + ele_idx = get_next_indice( st0, PARAM_ISM_DTX_ELE_BITS ); + + ivas_param_ism_dec_dequantize_DOA_dtx( PARAM_ISM_DTX_AZI_BITS, PARAM_ISM_DTX_ELE_BITS, azi_idx, ele_idx, &( st_ivas->hDirAC->azimuth_values[i] ), &( st_ivas->hDirAC->elevation_values[i] ) ); } - return error; + /* set the bitstream pointer to its original position */ + st0->bit_stream = bstr_orig; + st0->next_bit_pos = next_bit_pos_orig; + +#ifdef DEBUG_MODE_PARAM_ISM + dbgwrite( &( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence ), sizeof( float ), 1, 1, "./res/ParamISM_coh_dec.dat" ); +#endif + + return; } +#endif diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index 0e7f5f864a62bfb02000ac2a05ed1ccf1bf132f1..a5bdcc410046ad9acd629d86862610ac3b39714c 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,8 +33,9 @@ #include #include "options.h" #include "ivas_cnst.h" -#include "ivas_prot.h" #include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_stat_com.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" @@ -42,7 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------* @@ -61,7 +62,7 @@ ivas_error ivas_ism_renderer_open( error = IVAS_ERR_OK; - if ( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) count_malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL ) + if ( ( st_ivas->hIsmRendererData = (ISM_RENDERER_HANDLE) malloc( sizeof( ISM_RENDERER_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM renderer\n" ) ); } @@ -82,7 +83,7 @@ ivas_error ivas_ism_renderer_open( interpolator_length = (uint16_t) ( st_ivas->hDecoderConfig->output_Fs / FRAMES_PER_SEC ); for ( i = 0; i < interpolator_length; i++ ) { - st_ivas->hIsmRendererData->interpolator[i] = (float) i / ( (float) interpolator_length ); + st_ivas->hIsmRendererData->interpolator[i] = (float) i / ( (float) interpolator_length - 1 ); } return error; @@ -106,11 +107,15 @@ void ivas_ism_render( float tmp_output_f[MAX_OUTPUT_CHANNELS][L_FRAME48k]; float gains[MAX_NUM_OBJECTS][MAX_OUTPUT_CHANNELS]; float g1, g2; - int16_t num_objects, nchan_out_woLFE, lfe_index; + int16_t nchan_ism, nchan_out_woLFE, lfe_index; int16_t azimuth, elevation; float Rmat[3][3]; - num_objects = st_ivas->nchan_transport; +#ifdef NCHAN_ISM_PARAMETER + nchan_ism = st_ivas->nchan_ism; +#else + nchan_ism = st_ivas->nchan_transport; +#endif nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; lfe_index = 0; @@ -120,7 +125,7 @@ void ivas_ism_render( set_f( tmp_output_f[j], 0.0f, output_frame ); } - for ( i = 0; i < num_objects; i++ ) + for ( i = 0; i < nchan_ism; i++ ) { mvr2r( output_f[i], input_f[i], output_frame ); } @@ -136,40 +141,14 @@ void ivas_ism_render( QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[st_ivas->hHeadTrackData->num_quaternions++], Rmat ); } - for ( i = 0; i < num_objects; i++ ) + for ( i = 0; i < nchan_ism; i++ ) { if ( st_ivas->intern_config == AUDIO_CONFIG_STEREO ) { - float aziRad, eleRad; - float y, mappedX, aziRadMapped, A, A2, A3; - const float LsAngleRad = 30.0f * PI_OVER_180; - - /* Convert azi and ele to an azi value of the cone of confusion */ - aziRad = st_ivas->hIsmMetaData[i]->azimuth * PI_OVER_180; - eleRad = st_ivas->hIsmMetaData[i]->elevation * PI_OVER_180; - y = ( sinf( aziRad ) * cosf( eleRad ) ); - mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) ); - aziRadMapped = atan2f( y, mappedX ); - - /* Determine the amplitude panning gains */ - if ( aziRadMapped >= LsAngleRad ) - { /* Left side */ - gains[i][0] = 1.0f; - gains[i][1] = 0.0f; - } - else if ( aziRadMapped <= -LsAngleRad ) - { /* Right side */ - gains[i][0] = 0.0f; - gains[i][1] = 1.0f; - } - else /* Tangent panning law */ - { - A = tanf( aziRadMapped ) / tanf( LsAngleRad ); - A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); - A3 = 1.0f / ( A2 * A2 + 1.0f ); - gains[i][0] = sqrtf( A3 ); - gains[i][1] = sqrtf( 1.0f - A3 ); - } + ivas_ism_get_stereo_gains( st_ivas->hIsmMetaData[i]->azimuth, + st_ivas->hIsmMetaData[i]->elevation, + &gains[i][0], + &gains[i][1] ); } else { @@ -180,8 +159,9 @@ void ivas_ism_render( } else { - azimuth = (int16_t) ( st_ivas->hIsmMetaData[i]->azimuth + 0.5f ); - elevation = (int16_t) ( st_ivas->hIsmMetaData[i]->elevation + 0.5f ); + // TODO tmu review when #215 is resolved + azimuth = (int16_t) floorf( st_ivas->hIsmMetaData[i]->azimuth + 0.5f ); + elevation = (int16_t) floorf( st_ivas->hIsmMetaData[i]->elevation + 0.5f ); if ( st_ivas->hIntSetup.is_planar_setup ) { @@ -211,6 +191,7 @@ void ivas_ism_render( st_ivas->hIsmRendererData->prev_gains[i][j] = gains[i][j]; } } + /* Move to output skipping LFE */ for ( j = 0, j2 = 0; j < nchan_out_woLFE; j++, j2++ ) { @@ -220,5 +201,54 @@ void ivas_ism_render( } mvr2r( tmp_output_f[j], output_f[j2], output_frame ); } + + return; +} + + +/*-------------------------------------------------------------------------* + * ivas_ism_get_stereo_gains() + * + * + *-------------------------------------------------------------------------*/ + +void ivas_ism_get_stereo_gains( + const float azimuth, /* i : object azimuth */ + const float elevation, /* i : object elevation */ + float *left_gain, /* o : left channel gain */ + float *right_gain /* o : right channel gain */ +) +{ + float aziRad, eleRad; + float y, mappedX, aziRadMapped, A, A2, A3; + const float LsAngleRad = 30.0f * PI_OVER_180; + + /* Convert azi and ele to an azi value of the cone of confusion */ + aziRad = azimuth * PI_OVER_180; + eleRad = elevation * PI_OVER_180; + y = ( sinf( aziRad ) * cosf( eleRad ) ); + mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) ); + aziRadMapped = atan2f( y, mappedX ); + + /* Determine the amplitude panning gains */ + if ( aziRadMapped >= LsAngleRad ) + { /* Left side */ + *left_gain = 1.0f; + *right_gain = 0.0f; + } + else if ( aziRadMapped <= -LsAngleRad ) + { /* Right side */ + *left_gain = 0.0f; + *right_gain = 1.0f; + } + else /* Tangent panning law */ + { + A = tanf( aziRadMapped ) / tanf( LsAngleRad ); + A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f ); + A3 = 1.0f / ( A2 * A2 + 1.0f ); + *left_gain = sqrtf( A3 ); + *right_gain = sqrtf( 1.0f - A3 ); + } + return; } diff --git a/lib_dec/ivas_lfe_dec.c b/lib_dec/ivas_lfe_dec.c index a3dd0472acdc62a7efee52f58caa880004629b12..5c250286eedfd2291b691c92b3587f71ea484674 100644 --- a/lib_dec/ivas_lfe_dec.c +++ b/lib_dec/ivas_lfe_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include "math.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -154,6 +154,8 @@ static int16_t ivas_lfe_dec_dequant( { int16_t shift_bits, i; int16_t quant_strategy; + int16_t coding_strategy; + int16_t base2_bit_size; int16_t lfe_bits; int16_t all_zeros_dct; int16_t min_shift_bits; @@ -195,16 +197,32 @@ static int16_t ivas_lfe_dec_dequant( sign_bits[i] = get_next_indice( st0, 1 ); } - for ( iii = 0; iii < num_groups; iii++ ) - { - extra_bits_read = 0; - ivas_ari_start_decoding_14bits_ext_1_lfe( st0, &as, &extra_bits_read ); + coding_strategy = get_next_indice( st0, 1 ); - for ( i = 0; i < 4; i++ ) + if ( coding_strategy ) + { + for ( iii = 0; iii < num_groups; iii++ ) + { + base2_bit_size = hLFE->lfe_dec_indices_coeffs_tbl[quant_strategy][iii]; + for ( i = 0; i < 4; i++ ) + { + abs_values[iii * 4 + i] = get_next_indice( st0, base2_bit_size ); + } + } + } + else + { + for ( iii = 0; iii < num_groups; iii++ ) { - abs_values[iii * 4 + i] = ivas_ari_decode_14bits_bit_ext_1_lfe( st0, &as, hLFE->cum_freq_models[quant_strategy][iii], &extra_bits_read ); + extra_bits_read = 0; + ivas_ari_start_decoding_14bits_ext_1_lfe( st0, &as, &extra_bits_read ); + + for ( i = 0; i < 4; i++ ) + { + abs_values[iii * 4 + i] = ivas_ari_decode_14bits_bit_ext_1_lfe( st0, &as, hLFE->cum_freq_models[quant_strategy][iii], &extra_bits_read ); + } + ivas_ari_done_decoding_14bits_ext_1_lfe( st0, extra_bits_read ); } - ivas_ari_done_decoding_14bits_ext_1_lfe( st0, extra_bits_read ); } for ( i = 0; i < num_dct_coeffs; i++ ) @@ -315,7 +333,7 @@ void ivas_lfe_dec( ivas_filter_process( &hLFE->filter_state, output_lfe_ch, output_frame ); } - /* ADD delay to make overall max(block_offset, 11.5)*/ + /* add delay to make overall max(block_offset, 11.5) */ if ( hLFE->lfe_addl_delay > 0 ) { delay_signal( output_lfe_ch, output_frame, hLFE->lfe_delay_buf, hLFE->lfe_addl_delay ); @@ -332,9 +350,9 @@ void ivas_lfe_dec( *-------------------------------------------------------------------------*/ ivas_error ivas_create_lfe_dec( - LFE_DEC_HANDLE *hLFE_out, /* o : IVAS LFE decoder structure */ - const int32_t output_Fs, /* i : output sampling rate */ - const float add_delay_s /* additional delay in second to lfe to sync with binaural filter*/ + LFE_DEC_HANDLE *hLFE_out, /* o : IVAS LFE decoder structure */ + const int32_t output_Fs, /* i : output sampling rate */ + const int32_t binauralization_delay_ns /* i : additional LFE delay to sync with binaural renderer */ ) { float low_pass_delay_dec_out, block_offset_s; @@ -342,6 +360,8 @@ ivas_error ivas_create_lfe_dec( const float *filt_coeff; LFE_DEC_HANDLE hLFE; float lfe_addl_delay_s; + int16_t i, j; + int16_t add_delay_sa; low_pass_delay_dec_out = 0; block_offset_s = 0; @@ -352,7 +372,7 @@ ivas_error ivas_create_lfe_dec( * Allocate LFE handle *-----------------------------------------------------------------*/ - if ( ( hLFE = (LFE_DEC_HANDLE) count_malloc( sizeof( LFE_DEC_DATA ) ) ) == NULL ) + if ( ( hLFE = (LFE_DEC_HANDLE) malloc( sizeof( LFE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE\n" ) ); } @@ -361,7 +381,7 @@ ivas_error ivas_create_lfe_dec( * LFE Window: allocate and initialize *-----------------------------------------------------------------*/ - if ( ( hLFE->pWindow_state = (LFE_WINDOW_HANDLE) count_malloc( sizeof( LFE_WINDOW_DATA ) ) ) == NULL ) + if ( ( hLFE->pWindow_state = (LFE_WINDOW_HANDLE) malloc( sizeof( LFE_WINDOW_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE window structure\n" ) ); } @@ -379,7 +399,7 @@ ivas_error ivas_create_lfe_dec( hLFE->cum_freq_models[1][3] = &ivas_str_lfe_freq_models.entropy_coder_model_coarse_sg4; /* delay calculation */ - hLFE->lfe_block_delay_s = IVAS_LFE_FADE_LEN_SEC_FLOAT + ivas_lfe_lpf_delay[IVAS_FILTER_ORDER_4 - 3]; + hLFE->lfe_block_delay_s = ( IVAS_LFE_FADE_NS / 1000000000.f ) + ivas_lfe_lpf_delay[IVAS_FILTER_ORDER_4 - 3]; block_offset_s = BLOCK_OFFSET_MS * 0.001f; @@ -409,19 +429,21 @@ ivas_error ivas_create_lfe_dec( { hLFE->filter_state.order = filt_order; } + hLFE->lfe_block_delay_s = hLFE->lfe_block_delay_s + low_pass_delay_dec_out; - hLFE->lfe_prior_buf_len = (int16_t) ( IVAS_LFE_FADE_LEN_SEC_FLOAT * output_Fs ); + hLFE->lfe_prior_buf_len = NS2SA( output_Fs, IVAS_LFE_FADE_NS ); hLFE->bfi_count = 0; lfe_addl_delay_s = block_offset_s - hLFE->lfe_block_delay_s; lfe_addl_delay_s = max( 0.0f, lfe_addl_delay_s ); - hLFE->lfe_addl_delay = (int16_t) ( lfe_addl_delay_s * output_Fs ) + (int16_t) roundf( add_delay_s * output_Fs ); - hLFE->lfe_block_delay_s += lfe_addl_delay_s + add_delay_s; + add_delay_sa = (int16_t) roundf( (float) binauralization_delay_ns * output_Fs / 1000000000.f ); + hLFE->lfe_addl_delay = (int16_t) ( lfe_addl_delay_s * output_Fs ) + add_delay_sa; + hLFE->lfe_block_delay_s += lfe_addl_delay_s + add_delay_sa / output_Fs; if ( hLFE->lfe_addl_delay > 0 ) { - if ( ( hLFE->lfe_delay_buf = (float *) count_malloc( hLFE->lfe_addl_delay * sizeof( float ) ) ) == NULL ) + if ( ( hLFE->lfe_delay_buf = (float *) malloc( hLFE->lfe_addl_delay * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE additional delay buffer\n" ) ); } @@ -432,6 +454,15 @@ ivas_error ivas_create_lfe_dec( hLFE->lfe_delay_buf = NULL; } + /* Initialization base2 bits for each subgroup for no entropy coding */ + for ( i = 0; i < IVAS_MAX_NUM_QUANT_STRATS; i++ ) + { + for ( j = 0; j < IVAS_MAX_NUM_DCT_COEF_GROUPS; j++ ) + { + hLFE->lfe_dec_indices_coeffs_tbl[i][j] = + (int16_t) ceilf( log2f( (float) ( ivas_lfe_num_ele_in_coder_models[i][j] + 1 ) ) ); + } + } *hLFE_out = hLFE; @@ -446,19 +477,25 @@ ivas_error ivas_create_lfe_dec( *-------------------------------------------------------------------------*/ void ivas_lfe_dec_close( - LFE_DEC_HANDLE hLFE /* i/o: LFE decoder handle */ + LFE_DEC_HANDLE *hLFE /* i/o: LFE decoder handle */ ) { - count_free( hLFE->pWindow_state ); - hLFE->pWindow_state = NULL; + if ( hLFE == NULL || *hLFE == NULL ) + { + return; + } + + free( ( *hLFE )->pWindow_state ); + ( *hLFE )->pWindow_state = NULL; - if ( hLFE->lfe_delay_buf != NULL ) + if ( ( *hLFE )->lfe_delay_buf != NULL ) { - count_free( hLFE->lfe_delay_buf ); - hLFE->lfe_delay_buf = NULL; + free( ( *hLFE )->lfe_delay_buf ); + ( *hLFE )->lfe_delay_buf = NULL; } - count_free( hLFE ); + free( ( *hLFE ) ); + ( *hLFE ) = NULL; return; } diff --git a/lib_dec/ivas_lfe_plc.c b/lib_dec/ivas_lfe_plc.c index 71d1aa7a5e4af09d66d0a0c325ad4404a8b03f85..7e63c2d539ad965107966cecc3e676a167e96c69 100644 --- a/lib_dec/ivas_lfe_plc.c +++ b/lib_dec/ivas_lfe_plc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* * Local constants diff --git a/lib_dec/ivas_ls_custom_dec.c b/lib_dec/ivas_ls_custom_dec.c index 1d61ba0641980957ae0ff9baef0d72f1f27bdbe9..ef3698ab8c87c4929ffe12a01e4f29eedaafff23 100644 --- a/lib_dec/ivas_ls_custom_dec.c +++ b/lib_dec/ivas_ls_custom_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -29,7 +29,6 @@ the United Nations Convention on Contracts on the International Sales of Goods. *******************************************************************************************************/ - #include #include "options.h" #include "ivas_prot.h" @@ -37,7 +36,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -51,7 +50,7 @@ ivas_error ivas_ls_custom_open( ) { /* Allocate handle */ - if ( ( *hLsSetupCustom = (LSSETUP_CUSTOM_HANDLE) count_malloc( sizeof( LSSETUP_CUSTOM_STRUCT ) ) ) == NULL ) + if ( ( *hLsSetupCustom = (LSSETUP_CUSTOM_HANDLE) malloc( sizeof( LSSETUP_CUSTOM_STRUCT ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Custom LS layout memory\n" ) ); } @@ -79,8 +78,8 @@ ivas_error ivas_ls_custom_open( *-------------------------------------------------------------------------*/ void ivas_ls_custom_setup( - IVAS_OUTPUT_SETUP_HANDLE hOutSetup, /* o : IVAS output setup handle */ - const LSSETUP_CUSTOM_HANDLE hLsSetupCustom /* i : Custom loudspeaker setup handle */ + IVAS_OUTPUT_SETUP_HANDLE hOutSetup, /* o : IVAS output setup handle */ + const LSSETUP_CUSTOM_STRUCT *hLsSetupCustom /* i : Custom loudspeaker setup handle */ ) { hOutSetup->output_config = AUDIO_CONFIG_LS_CUSTOM; @@ -92,8 +91,8 @@ void ivas_ls_custom_setup( hOutSetup->num_lfe = hLsSetupCustom->num_lfe; hOutSetup->index_lfe[0] = hLsSetupCustom->lfe_idx[0]; /* IVAS_OUTPUT_SETUP only supports 1 LFE */ - hOutSetup->is_loudspeaker_setup = true; - hOutSetup->is_planar_setup = (uint8_t) hLsSetupCustom->is_planar_setup; + hOutSetup->is_loudspeaker_setup = TRUE; + hOutSetup->is_planar_setup = (int8_t) hLsSetupCustom->is_planar_setup; return; } diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 0e2c68f385b8c2b1a277fbf59e10d5c63c163624..3c7e490cbc1c18191c288d82d2f5eb6bef784878 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,12 +42,15 @@ #include "debug.h" #endif #include -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * Local constants *-----------------------------------------------------------------------*/ #define SPAR_META_DELAY_SUBFRAMES 2 /* Number of subframes to delay the SPAR metadata */ +#ifdef FIX_350_MASA_DELAY_COMP +#define SPH_IDX_FRONT ( MASA_NO_POINTS_EQUATOR / 2 ) /* Spherical index corresponding to front direction for setting as default value */ +#endif /*-----------------------------------------------------------------------* * Local function prototypes @@ -57,12 +60,15 @@ static int16_t quantize_theta( float x, int16_t no_cb, float *xhat ); static uint16_t index_theta_phi_16( float theta, float phi, SPHERICAL_GRID_DATA *Sph_Grid16 ); static int16_t quantize_phi_masa( float phi, int16_t flag_delta, float *phi_hat, const int16_t n ); static void index_16bits( IVAS_QMETADATA_HANDLE hQMetaData, SPHERICAL_GRID_DATA *Sph_Grid16 ); +#ifdef FIX_350_MASA_DELAY_COMP +static void create_masa_ext_out_meta( MASA_DECODER *hMasa, IVAS_QMETADATA_HANDLE hQMetaData, const int16_t nchan_transport ); +#endif static void replicate_subframes( IVAS_QMETADATA_HANDLE hQMetaData ); static void restore_lowbitrate_masa( IVAS_QMETADATA_HANDLE hQMetaData, const int16_t low_bitrate_mode, const int16_t numCodingBands ); -static void init_lfe_synth_data( Decoder_Struct *st_ivas, MASA_DECODER_HANDLE hMasa ); +static ivas_error init_lfe_synth_data( Decoder_Struct *st_ivas, MASA_DECODER_HANDLE hMasa ); static void compute_foa_cov_matrix( float foaCov[FOA_CHANNELS][FOA_CHANNELS], float inCov[FOA_CHANNELS][FOA_CHANNELS], float mixMtx[FOA_CHANNELS][FOA_CHANNELS] ); @@ -111,11 +117,11 @@ ivas_error ivas_masa_decode( ivas_format = st_ivas->ivas_format; hMasa->data.dir_decode_quality = 1.0f; /* Set to default of max quality */ - hQMetaData->is_masa_type_format = 1; + hQMetaData->is_masa_ivas_format = 1; *nb_bits_read = 0; next_bit_pos_orig = st->next_bit_pos; - if ( masa_brate == IVAS_SID_4k4 ) + if ( masa_brate == IVAS_SID_5k2 ) { st->next_bit_pos = (int16_t) ( ( masa_brate / FRAMES_PER_SEC ) - 1 - SID_FORMAT_NBITS ); } @@ -124,7 +130,7 @@ ivas_error ivas_masa_decode( st->next_bit_pos = (int16_t) ( ( masa_brate / FRAMES_PER_SEC ) - 1 ); } - if ( !st->bfi && ivas_total_brate > IVAS_SID_4k4 ) + if ( !st->bfi && ivas_total_brate > IVAS_SID_5k2 ) { if ( !( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) { @@ -169,7 +175,6 @@ ivas_error ivas_masa_decode( return error; } - /* If we are under metadata bit budget limit and joined subframes is not signalled, then read LBR mode. */ if ( hMasa->config.max_metadata_bits < MINIMUM_BIT_BUDGET_NORMAL_META && hMasa->config.joinedSubframes == FALSE ) { @@ -216,7 +221,7 @@ ivas_error ivas_masa_decode( replicate_subframes( hQMetaData ); } } - else if ( !st->bfi && ivas_format == MASA_FORMAT && ivas_total_brate == IVAS_SID_4k4 ) + else if ( !st->bfi && ivas_format == MASA_FORMAT && ivas_total_brate == IVAS_SID_5k2 ) { if ( hQMetaData->q_direction == NULL ) { @@ -229,14 +234,13 @@ ivas_error ivas_masa_decode( ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); - hQMetaData->metadata_max_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC; + hQMetaData->metadata_max_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; if ( ( error = ivas_qmetadata_allocate_memory( hQMetaData, 5, 1, 0 ) ) != IVAS_ERR_OK ) { return error; } - hQMetaData->numTwoDirBands = hMasa->config.numTwoDirBands; hQMetaData->useLowerRes = 0; @@ -254,8 +258,7 @@ ivas_error ivas_masa_decode( } tmp_elem_mode = -1; - *nb_bits_read += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), st_ivas->nchan_transport, &tmp_elem_mode, ivas_format, - SBA_MODE_NONE ); + *nb_bits_read += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), st_ivas->nchan_transport, &tmp_elem_mode, ivas_format, SBA_MODE_NONE ); if ( st_ivas->nchan_transport == 2 ) { @@ -276,8 +279,7 @@ ivas_error ivas_masa_decode( } if ( st_ivas->hDirAC != NULL ) { - ivas_qmetadata_to_dirac( hQMetaData, st_ivas->hDirAC, hMasa, ivas_total_brate, - SBA_MODE_NONE, 0 ); + ivas_qmetadata_to_dirac( hQMetaData, st_ivas->hDirAC, hMasa, ivas_total_brate, SBA_MODE_NONE, 0 ); } st->next_bit_pos = next_bit_pos_orig; @@ -285,7 +287,7 @@ ivas_error ivas_masa_decode( { st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = ivas_total_brate < MASA_STEREO_MIN_BITRATE ? 1 : 0; - if ( ivas_total_brate <= IVAS_SID_4k4 ) + if ( ivas_total_brate <= IVAS_SID_5k2 ) { st_ivas->hCPE[0]->hStereoDft->hConfig->force_mono_transmission = 0; } @@ -295,17 +297,24 @@ ivas_error ivas_masa_decode( { st_ivas->hCPE[0]->hCoreCoder[0]->masa_sid_format = 0; - if ( st_ivas->hDecoderConfig->last_ivas_total_brate <= IVAS_SID_4k4 ) + if ( st_ivas->hDecoderConfig->last_ivas_total_brate <= IVAS_SID_5k2 ) { st_ivas->hCPE[0]->hCoreCoder[0]->masa_sid_format = 1; - if ( ivas_total_brate >= IVAS_SID_4k4 ) + if ( ivas_total_brate >= IVAS_SID_5k2 ) { st_ivas->hCPE[0]->element_brate = ivas_total_brate; } } } +#ifdef FIX_350_MASA_DELAY_COMP + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) + { + create_masa_ext_out_meta( hMasa, hQMetaData, st_ivas->nchan_transport ); + } +#endif + return error /* *nb_bits_read*/; } @@ -321,8 +330,11 @@ ivas_error ivas_masa_dec_open( ) { MASA_DECODER_HANDLE hMasa; + ivas_error error; + + error = IVAS_ERR_OK; - if ( ( hMasa = (MASA_DECODER_HANDLE) count_malloc( sizeof( MASA_DECODER ) ) ) == NULL ) + if ( ( hMasa = (MASA_DECODER_HANDLE) malloc( sizeof( MASA_DECODER ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); } @@ -337,17 +349,30 @@ ivas_error ivas_masa_dec_open( /* Create spherical grid only for external output */ if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) { - hMasa->data.sph_grid16 = (SPHERICAL_GRID_DATA *) count_malloc( sizeof( SPHERICAL_GRID_DATA ) ); + if ( ( hMasa->data.sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + generate_gridEq( hMasa->data.sph_grid16 ); +#ifdef FIX_350_MASA_DELAY_COMP + if ( ( hMasa->data.extOutMeta = (MASA_DECODER_EXT_OUT_META *) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } +#endif } else { hMasa->data.sph_grid16 = NULL; +#ifdef FIX_350_MASA_DELAY_COMP + hMasa->data.extOutMeta = NULL; +#endif } if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { - init_lfe_synth_data( st_ivas, hMasa ); + error = init_lfe_synth_data( st_ivas, hMasa ); } else { @@ -356,7 +381,7 @@ ivas_error ivas_masa_dec_open( st_ivas->hMasa = hMasa; - return IVAS_ERR_OK; + return error; } @@ -367,44 +392,61 @@ ivas_error ivas_masa_dec_open( *-----------------------------------------------------------------------*/ void ivas_masa_dec_close( - MASA_DECODER_HANDLE hMasa /* i/o: MASA metadata structure */ + MASA_DECODER_HANDLE *hMasa_out /* i/o: MASA metadata structure */ ) { + MASA_DECODER_HANDLE hMasa; + + if ( hMasa_out == NULL || *hMasa_out == NULL ) + { + return; + } + + hMasa = *hMasa_out; + /* Free spherical grid memory if in use */ if ( hMasa->data.sph_grid16 != NULL ) { - count_free( hMasa->data.sph_grid16 ); + free( hMasa->data.sph_grid16 ); hMasa->data.sph_grid16 = NULL; } +#ifdef FIX_350_MASA_DELAY_COMP + if ( hMasa->data.extOutMeta != NULL ) + { + free( hMasa->data.extOutMeta ); + hMasa->data.extOutMeta = NULL; + } +#endif + if ( hMasa->hMasaLfeSynth != NULL ) { if ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer != NULL ) { - count_free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer ); + free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer ); hMasa->hMasaLfeSynth->lfeSynthRingBuffer = NULL; } if ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 != NULL ) { - count_free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 ); + free( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 ); hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 = NULL; } if ( hMasa->hMasaLfeSynth->delayBuffer_syncLp != NULL ) { - count_free( hMasa->hMasaLfeSynth->delayBuffer_syncLp ); + free( hMasa->hMasaLfeSynth->delayBuffer_syncLp ); hMasa->hMasaLfeSynth->delayBuffer_syncLp = NULL; } if ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC != NULL ) { - count_free( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC ); + free( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC ); hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = NULL; } - count_free( hMasa->hMasaLfeSynth ); + free( hMasa->hMasaLfeSynth ); hMasa->hMasaLfeSynth = NULL; } - count_free( hMasa ); - hMasa = NULL; + free( *hMasa_out ); + *hMasa_out = NULL; return; } @@ -425,7 +467,6 @@ static ivas_error ivas_masa_dec_config( ivas_error error; error = IVAS_ERR_OK; - hMasa = st_ivas->hMasa; ivas_masa_set_elements( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &st_ivas->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); @@ -440,7 +481,6 @@ static ivas_error ivas_masa_dec_config( return error; } - st_ivas->hQMetaData->numTwoDirBands = st_ivas->hMasa->config.numTwoDirBands; st_ivas->hQMetaData->useLowerRes = 0; @@ -461,7 +501,19 @@ static ivas_error ivas_masa_dec_config( ivas_set_qmetadata_maxbit_req( st_ivas->hQMetaData, st_ivas->ivas_format ); +#ifdef FIX_350_MASA_DELAY_COMP + if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) + { + /* need to apply the sampling rate correction also for the EXT output MASA meta buffer */ + masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hQMetaData, st_ivas->hDecoderConfig->output_Fs, hMasa->data.extOutMeta ); + } + else + { + masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hQMetaData, st_ivas->hDecoderConfig->output_Fs, NULL ); + } +#else masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, st_ivas->hQMetaData, st_ivas->hDecoderConfig->output_Fs ); +#endif return error; } @@ -479,7 +531,7 @@ void ivas_masa_prerender( const int16_t output_frame /* i : output frame length per channel */ ) { - if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->nchan_transport == 2 && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_4k4 ) + if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->nchan_transport == 2 && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_5k2 ) { if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_EXTERNAL ) { @@ -643,7 +695,7 @@ static uint16_t index_theta_phi_16( } else { - theta = MASA_NTOT2_FAC * (float) ( id_th + 0.5f ); + theta = MASA_ANGLE_AT_EQUATOR * (float) ( id_th + 0.5f ); if ( id_th == 1 ) { cum_n = 2 * (uint16_t) ceilf( MASA_NTOT2_FAC * ( sinf( theta ) - MASA_ASIN_OFFSET ) ); @@ -792,7 +844,7 @@ static void restore_lowbitrate_masa( } -static void init_lfe_synth_data( +static ivas_error init_lfe_synth_data( Decoder_Struct *st_ivas, /* i : IVAS decoder struct */ MASA_DECODER_HANDLE hMasa /* i/o: MASA decoder structure */ ) @@ -803,7 +855,10 @@ static void init_lfe_synth_data( output_Fs = st_ivas->hDecoderConfig->output_Fs; output_config = st_ivas->hDecoderConfig->output_config; - hMasa->hMasaLfeSynth = (MCMASA_LFE_SYNTH_DATA_HANDLE) count_malloc( sizeof( MCMASA_LFE_SYNTH_DATA ) ); + if ( ( hMasa->hMasaLfeSynth = (MCMASA_LFE_SYNTH_DATA_HANDLE) malloc( sizeof( MCMASA_LFE_SYNTH_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } hMasa->hMasaLfeSynth->transportEneSmooth = 0.0f; hMasa->hMasaLfeSynth->protoLfeEneSmooth = 0.0f; @@ -827,7 +882,10 @@ static void init_lfe_synth_data( /* Ring buffer for the filterbank of the LFE synthesis. * The filterbank is using moving average lowpass filter with the crossover of 120 Hz. */ bufferSize = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES ); - hMasa->hMasaLfeSynth->lfeSynthRingBuffer = (float *) count_malloc( bufferSize * sizeof( float ) ); + if ( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } set_zero( hMasa->hMasaLfeSynth->lfeSynthRingBuffer, bufferSize ); hMasa->hMasaLfeSynth->ringBufferLoPointer = 0; hMasa->hMasaLfeSynth->ringBufferHiPointer = bufferSize / 2; @@ -837,7 +895,10 @@ static void init_lfe_synth_data( /* Ring buffer for additional lowpass filter for the LFE signal. * Moving average lowpass filter with the crossover of 240 Hz. */ bufferSize /= 2; - hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 = (float *) count_malloc( bufferSize * sizeof( float ) ); + if ( ( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2 = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } set_zero( hMasa->hMasaLfeSynth->lfeSynthRingBuffer2, bufferSize ); hMasa->hMasaLfeSynth->ringBufferLoPointer2 = 0; hMasa->hMasaLfeSynth->lowpassSum2 = 0.0f; @@ -845,13 +906,19 @@ static void init_lfe_synth_data( /* Delay buffer for matching the delay of the lowpass filter */ bufferSize /= 2; /* The delay of the moving average lowpass filter is bufferSize / 2 */ - hMasa->hMasaLfeSynth->delayBuffer_syncLp = (float *) count_malloc( bufferSize * sizeof( float ) ); + if ( ( hMasa->hMasaLfeSynth->delayBuffer_syncLp = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } set_zero( hMasa->hMasaLfeSynth->delayBuffer_syncLp, bufferSize ); hMasa->hMasaLfeSynth->delayBuffer_syncLp_size = bufferSize; /* Delay buffer for syncing with DirAC rendering */ bufferSize = NS2SA( output_Fs, IVAS_FB_DEC_DELAY_NS ) - hMasa->hMasaLfeSynth->ringBufferSize / 2 - hMasa->hMasaLfeSynth->ringBufferSize2 / 2; - hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = (float *) count_malloc( bufferSize * sizeof( float ) ); + if ( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } set_zero( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC, bufferSize ); hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size = bufferSize; @@ -870,7 +937,10 @@ static void init_lfe_synth_data( /* Delay buffer for syncing with DirAC rendering */ bufferSize = NS2SA( output_Fs, IVAS_FB_DEC_DELAY_NS ); - hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = (float *) count_malloc( bufferSize * sizeof( float ) ); + if ( ( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } set_zero( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC, bufferSize ); hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size = bufferSize; @@ -886,7 +956,7 @@ static void init_lfe_synth_data( hMasa->hMasaLfeSynth->delayBuffer_syncDirAC = NULL; } - return; + return IVAS_ERR_OK; } @@ -1031,7 +1101,7 @@ ivas_error ivas_masa_dec_reconfigure( last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; /*-----------------------------------------------------------------* - * Allocate and initalize SCE/CPE and other handles + * Allocate and initialize SCE/CPE and other handles *-----------------------------------------------------------------*/ bit_stream = st_ivas->hSCE[0] != NULL ? st_ivas->hSCE[0]->hCoreCoder[0]->bit_stream : st_ivas->hCPE[0]->hCoreCoder[0]->bit_stream; @@ -1150,7 +1220,7 @@ void ivas_spar_param_to_masa_param_mapping( { for ( j = 0; j < FOA_CHANNELS; j++ ) { - mixer_mat_sf_bands_real[sf][band][i][j] = st_ivas->hSpar->hSparFoa->hMdDec->mixer_mat_prev[mixer_mat_index][i][j][band]; + mixer_mat_sf_bands_real[sf][band][i][j] = st_ivas->hSpar->hMdDec->mixer_mat_prev[mixer_mat_index][i][j][band]; } } } @@ -1164,7 +1234,7 @@ void ivas_spar_param_to_masa_param_mapping( { for ( j = 0; j < FOA_CHANNELS; j++ ) { - mixer_mat_sf_bands_real[sf][band][i][j] = st_ivas->hSpar->hSparFoa->hMdDec->mixer_mat[i][j][band + mixer_mat_index * IVAS_MAX_NUM_BANDS]; + mixer_mat_sf_bands_real[sf][band][i][j] = st_ivas->hSpar->hMdDec->mixer_mat[i][j][band + mixer_mat_index * IVAS_MAX_NUM_BANDS]; } } } @@ -1357,3 +1427,137 @@ static void compute_foa_cov_matrix( return; } + +#ifdef FIX_350_MASA_DELAY_COMP +static void create_masa_ext_out_meta( + MASA_DECODER *hMasa, + IVAS_QMETADATA_HANDLE hQMetaData, + const int16_t nchan_transport ) +{ + const uint8_t ivasmasaFormatDescriptor[8] = { 0x49, 0x56, 0x41, 0x53, 0x4D, 0x41, 0x53, 0x41 }; /* "IVASMASA" */ + int16_t i, sf, b_old, b_new, dir; + MASA_DECRIPTIVE_META *descMeta; + int16_t *bandMap; + uint8_t numCodingBands; + uint8_t numDirections; + MASA_DECODER_EXT_OUT_META *extOutMeta; + + numDirections = hMasa->config.numberOfDirections; + numCodingBands = hMasa->config.numCodingBands; + bandMap = hMasa->data.band_mapping; + extOutMeta = hMasa->data.extOutMeta; + descMeta = &hMasa->data.extOutMeta->descriptiveMeta; + + /* Construct descriptive meta */ + for ( i = 0; i < 8; i++ ) + { + descMeta->formatDescriptor[i] = ivasmasaFormatDescriptor[i]; + } + descMeta->numberOfDirections = numDirections - 1; + descMeta->numberOfChannels = (uint8_t) ( nchan_transport - 1 ); + /* Following correspond to "unknown" values until transmission is implemented */ + descMeta->sourceFormat = 0x0u; + descMeta->transportDefinition = 0x0u; + descMeta->channelAngle = 0x0u; + descMeta->channelDistance = 0x0u; + descMeta->channelLayout = 0x0u; + + /* Construct spatial metadata from qmetadata */ + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + for ( dir = 0; dir < numDirections; dir++ ) + { + /* Spherical index */ + for ( b_old = 0; b_old < numCodingBands; b_old++ ) + { + for ( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ ) + { + extOutMeta->directionIndex[dir][sf][b_new] = hQMetaData->q_direction[dir].band_data[b_old].spherical_index[sf]; + } + } + + /* Direct-to-total ratio */ + for ( b_old = 0; b_old < numCodingBands; b_old++ ) + { + for ( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ ) + { + extOutMeta->directToTotalRatio[dir][sf][b_new] = (uint8_t) floorf( hQMetaData->q_direction[dir].band_data[b_old].energy_ratio[sf] * UINT8_MAX ); + } + } + + /* Spread coherence */ + if ( hQMetaData->q_direction[dir].coherence_band_data != NULL ) + { + for ( b_old = 0; b_old < numCodingBands; b_old++ ) + { + for ( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ ) + { + extOutMeta->spreadCoherence[dir][sf][b_new] = hQMetaData->q_direction[dir].coherence_band_data[b_old].spread_coherence[sf]; + } + } + } + else + { + for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) + { + extOutMeta->spreadCoherence[dir][sf][i] = 0; + } + } + } + + /* Fill second direction with zero energy data for EXT output */ + if ( numDirections == 1 ) + { + for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) + { + extOutMeta->directionIndex[1][sf][i] = SPH_IDX_FRONT; + } + + for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) + { + extOutMeta->directToTotalRatio[1][sf][i] = 0; + } + + for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) + { + extOutMeta->spreadCoherence[1][sf][i] = 0; + } + } + + /* Common spatial meta */ + /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */ + for ( b_old = 0; b_old < numCodingBands; b_old++ ) + { + for ( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ ) + { + extOutMeta->diffuseToTotalRatio[sf][b_new] = UINT8_MAX; + for ( dir = 0; dir < numDirections; dir++ ) + { + extOutMeta->diffuseToTotalRatio[sf][b_new] -= (uint8_t) floorf( hQMetaData->q_direction[dir].band_data[b_old].energy_ratio[sf] * UINT8_MAX ); + } + } + } + + /* Surround coherence */ + if ( hQMetaData->surcoh_band_data != NULL ) + { + for ( b_old = 0; b_old < numCodingBands; b_old++ ) + { + for ( b_new = bandMap[b_old]; b_new < bandMap[b_old + 1]; b_new++ ) + { + extOutMeta->surroundCoherence[sf][b_new] = hQMetaData->surcoh_band_data[b_old].surround_coherence[sf]; + } + } + } + else + { + for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) + { + extOutMeta->surroundCoherence[sf][i] = 0; + } + } + } + + return; +} +#endif diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index e1df8f2a7dbf6f9f53c2c9758ce3882d3b458b83..a6637ed1f2d306d2cbd52ef130f7755d848582f9 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,11 +32,13 @@ #include #include "options.h" +#include #include "cnst.h" #include "rom_enc.h" #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" @@ -47,7 +49,7 @@ #ifdef DEBUG_PLOT #include "deb_out.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "rom_dec.h" /*-----------------------------------------------------------------------* @@ -56,13 +58,24 @@ #define PARAM_MC_LOCAL_SZ_LFE_MAP 5 +/*-----------------------------------------------------------------------* + * Local typedefs + *-----------------------------------------------------------------------*/ + +typedef struct parameter_band_mapping_struct +{ + int16_t n_source_bands[20]; + int16_t source_band_idx[20][4]; + float source_band_factor[20][4]; + +} PARAM_MC_PARAMETER_BAND_MAPPING; + /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ static void ivas_param_mc_dec_init( PARAM_MC_DEC_HANDLE hParamMC, const int16_t nchan_in, const int16_t nchan_out ); - static void param_mc_protoSignalComputation( float RealBuffer[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], float ImagBuffer[PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_NSLOTS][CLDFB_NO_CHANNELS_MAX], float *proto_frame_f, const PARAM_MC_DIFF_PROTO_INFO *diff_proto_info, const int16_t slot_index, const int16_t num_freq_bands ); static void ivas_param_mc_dec_copy_diffuse_proto( PARAM_MC_DEC_HANDLE hParamMC, float Cldfb_buffer_real[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Cldfb_buffer_imag[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nY, const int16_t slot_idx ); @@ -83,11 +96,13 @@ static void param_mc_compute_interpolator( const uint16_t bAttackPresent, const static void param_mc_set_num_synth_bands( const int32_t output_Fs, PARAM_MC_DEC_HANDLE hParamMC ); -static void param_mc_get_diff_proto_info( const float *proto_mtx, const uint16_t nchan_transport, const uint16_t nchan_out_cov, PARAM_MC_DIFF_PROTO_INFO *p_diff_proto_info ); +static ivas_error param_mc_get_diff_proto_info( const float *proto_mtx, const uint16_t nchan_transport, const uint16_t nchan_out_cov, PARAM_MC_DIFF_PROTO_INFO *p_diff_proto_info ); static void ivas_param_mc_mc2sba_cldfb( IVAS_OUTPUT_SETUP hTransSetup, float *hoa_encoder, const int16_t slot_idx, float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], const int16_t nBands, const float gain_lfe ); -void ivas_param_mc_bs_decode_parameter_values( uint16_t bit_buffer[], int16_t *bit_pos, const int16_t max_bits, int16_t *BER_detect, HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC, HANDLE_PARAM_MC_PARAMETER_CODING_INFO hParamCodingInfo, const int16_t map_size_wo_lfe, const int16_t map_size, const int16_t num_lfe_bands, const int16_t band_step, const int16_t num_param_bands, float *value_buffer ); +static void ivas_param_mc_get_param_band_mapping( const int16_t n_target_bands, const int16_t *target_band_grouping, const int16_t n_source_bands, const int16_t *source_band_grouping, PARAM_MC_PARAMETER_BAND_MAPPING *parameter_band_mapping ); + +static void ivas_param_mc_bs_decode_parameter_values( uint16_t bit_buffer[], int16_t *bit_pos, const int16_t max_bits, int16_t *BER_detect, HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC, HANDLE_PARAM_MC_PARAMETER_CODING_INFO hParamCodingInfo, const int16_t map_size_wo_lfe, const int16_t map_size, const int16_t num_lfe_bands, const int16_t band_step, const int16_t num_param_bands, float *value_buffer ); /*------------------------------------------------------------------------- * ivas_param_mc_dec_open() @@ -120,12 +135,12 @@ ivas_error ivas_param_mc_dec_open( * prepare library opening *-----------------------------------------------------------------*/ - if ( ( hParamMC = (PARAM_MC_DEC_HANDLE) count_malloc( sizeof( PARAM_MC_DEC_DATA ) ) ) == NULL ) + if ( ( hParamMC = (PARAM_MC_DEC_HANDLE) malloc( sizeof( PARAM_MC_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); } - if ( ( hParamMC->hMetadataPMC = (HANDLE_IVAS_PARAM_MC_METADATA) count_malloc( sizeof( IVAS_PARAM_MC_METADATA ) ) ) == NULL ) + if ( ( hParamMC->hMetadataPMC = (HANDLE_IVAS_PARAM_MC_METADATA) malloc( sizeof( IVAS_PARAM_MC_METADATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC metadata \n" ) ); } @@ -216,8 +231,14 @@ ivas_error ivas_param_mc_dec_open( ivas_param_mc_metadata_open( mc_ls_setup, hTransportSetup.index_lfe[0], ivas_total_brate, hParamMC->hMetadataPMC ); /* init arrays for quantized parameters */ - hParamMC->icc_q = (float *) count_malloc( hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe * sizeof( float ) ); - hParamMC->icld_q = (float *) count_malloc( hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe * sizeof( float ) ); + if ( ( hParamMC->icc_q = (float *) malloc( hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + if ( ( hParamMC->icld_q = (float *) malloc( hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } set_f( hParamMC->icld_q, PARAM_MC_DEFAULT_MIN_ILD, hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe ); set_f( hParamMC->icc_q, 0.0f, hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe ); @@ -249,7 +270,6 @@ ivas_error ivas_param_mc_dec_open( hParamMC->max_param_band_abs_cov = ( k++ ); } - /*-----------------------------------------------------------------* * open sub-modules *-----------------------------------------------------------------*/ @@ -263,15 +283,19 @@ ivas_error ivas_param_mc_dec_open( return error; } - /* convert the ls conv dmx matrix into column order matrix format (nchan_out_cldfb x nchan_out) */ if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) { - hParamMC->ls_conv_dmx_matrix = (float *) count_malloc( nchan_out_transport * nchan_out_cov * sizeof( float ) ); + if ( ( hParamMC->ls_conv_dmx_matrix = (float *) malloc( nchan_out_transport * nchan_out_cov * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + for ( k = 0; k < nchan_out_transport; k++ ) { mvr2r( st_ivas->hLsSetUpConversion->dmxMtx[k], &hParamMC->ls_conv_dmx_matrix[k * nchan_out_cov], nchan_out_cov ); } + /* convert ParamMC parameter bands to SFB */ if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) { @@ -289,7 +313,10 @@ ivas_error ivas_param_mc_dec_open( } } - hParamMC->proto_matrix_int = (float *) count_malloc( nchan_out_transport * nchan_transport * sizeof( float ) ); + if ( ( hParamMC->proto_matrix_int = (float *) malloc( nchan_out_transport * nchan_transport * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } mvr2r( ivas_param_mc_conf[config_index].dmx_fac, hParamMC->proto_matrix_int, nchan_transport * nchan_out_transport ); if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) @@ -297,6 +324,7 @@ ivas_error ivas_param_mc_dec_open( matrix_product( hParamMC->ls_conv_dmx_matrix, nchan_out_cov, nchan_out_transport, 0, ivas_param_mc_conf[config_index].dmx_fac, nchan_out_transport, nchan_transport, 0, proto_matrix ); + if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) { proto_mtx_norm = 1.f; @@ -333,9 +361,15 @@ ivas_error ivas_param_mc_dec_open( else { hParamMC->num_outputs_diff = nchan_out_cov; - hParamMC->diff_proto_info = (PARAM_MC_DIFF_PROTO_INFO *) count_malloc( sizeof( PARAM_MC_DIFF_PROTO_INFO ) ); + if ( ( hParamMC->diff_proto_info = (PARAM_MC_DIFF_PROTO_INFO *) malloc( sizeof( PARAM_MC_DIFF_PROTO_INFO ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } - param_mc_get_diff_proto_info( proto_matrix, nchan_transport, nchan_out_cov, hParamMC->diff_proto_info ); + if ( ( error = param_mc_get_diff_proto_info( proto_matrix, nchan_transport, nchan_out_cov, hParamMC->diff_proto_info ) ) != IVAS_ERR_OK ) + { + return error; + } /* decorrelation */ hParamMC->h_freq_domain_decorr_ap_params = NULL; @@ -343,15 +377,18 @@ ivas_error ivas_param_mc_dec_open( ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, hParamMC->num_freq_bands ); - ivas_dirac_dec_decorr_open( &( hParamMC->h_freq_domain_decorr_ap_params ), - &( hParamMC->h_freq_domain_decorr_ap_state ), - hParamMC->num_freq_bands, - hParamMC->num_outputs_diff, - hParamMC->diff_proto_info->num_protos_diff, - DIRAC_SYNTHESIS_COV_MC_LS, - frequency_axis, - nchan_transport, - output_Fs ); + if ( ( error = ivas_dirac_dec_decorr_open( &( hParamMC->h_freq_domain_decorr_ap_params ), + &( hParamMC->h_freq_domain_decorr_ap_state ), + hParamMC->num_freq_bands, + hParamMC->num_outputs_diff, + hParamMC->diff_proto_info->num_protos_diff, + DIRAC_SYNTHESIS_COV_MC_LS, + frequency_axis, + nchan_transport, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } hParamMC->h_output_synthesis_params.use_onset_filters = 0; hParamMC->max_band_decorr = hParamMC->h_freq_domain_decorr_ap_params->max_band_decorr; @@ -370,21 +407,27 @@ ivas_error ivas_param_mc_dec_open( } /* output synthesis */ - ivas_dirac_dec_output_synthesis_cov_open( &( hParamMC->h_output_synthesis_params ), - &( hParamMC->h_output_synthesis_cov_state ), - hParamMC->max_band_decorr, - PARAM_MC_MAX_NSLOTS, - hParamMC->hMetadataPMC->num_parameter_bands, - max_param_band_residual, - nchan_transport, - nchan_out_cov, - proto_matrix ); + if ( ( error = ivas_dirac_dec_output_synthesis_cov_open( &( hParamMC->h_output_synthesis_params ), + &( hParamMC->h_output_synthesis_cov_state ), + hParamMC->max_band_decorr, + PARAM_MC_MAX_NSLOTS, + hParamMC->hMetadataPMC->num_parameter_bands, + max_param_band_residual, + nchan_transport, + nchan_out_cov, + proto_matrix ) ) != IVAS_ERR_OK ) + { + return error; + } /* Head rotation */ if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) && st_ivas->hDecoderConfig->Opt_Headrotation ) { - hParamMC->hoa_encoder = (float *) count_malloc( st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS * sizeof( float ) ); + if ( ( hParamMC->hoa_encoder = (float *) malloc( st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } compute_hoa_encoder_mtx( st_ivas->hTransSetup.ls_azimuth, st_ivas->hTransSetup.ls_elevation, hParamMC->hoa_encoder, st_ivas->hTransSetup.nchan_out_woLFE, HEAD_ROTATION_HOA_ORDER ); } @@ -394,8 +437,15 @@ ivas_error ivas_param_mc_dec_open( if ( hParamMC->max_band_decorr > 0 ) { - hParamMC->proto_frame_f = (float *) count_malloc( 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands * sizeof( float ) ); - hParamMC->proto_frame_dec_f = (float *) count_malloc( 2 * nchan_out_cov * hParamMC->num_freq_bands * sizeof( float ) ); + if ( ( hParamMC->proto_frame_f = (float *) malloc( 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + + if ( ( hParamMC->proto_frame_dec_f = (float *) malloc( 2 * nchan_out_cov * hParamMC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } } else { @@ -410,6 +460,516 @@ ivas_error ivas_param_mc_dec_open( return error; } + +/*------------------------------------------------------------------------- + * ivas_param_mc_get_param_band_mapping() + * + * + *-------------------------------------------------------------------------*/ + +static void ivas_param_mc_get_param_band_mapping( + const int16_t n_target_bands, + const int16_t *target_band_grouping, + const int16_t n_source_bands, + const int16_t *source_band_grouping, + PARAM_MC_PARAMETER_BAND_MAPPING *parameter_band_mapping ) +{ + int16_t target_band_idx; + int16_t source_band_idx = 0; + int16_t source_band_cnt_total; + + for ( target_band_idx = 0; target_band_idx < n_target_bands; target_band_idx++ ) + { + int16_t upper = target_band_grouping[target_band_idx + 1]; + int16_t lower = target_band_grouping[target_band_idx]; + int16_t source_band_in_target_band_cnt = 0; + float norm_fac = 1.0f; + source_band_cnt_total = 0; + for ( source_band_idx = 0; source_band_idx < n_source_bands; source_band_idx++ ) + { + /* find lowest corresponding source band*/ + if ( source_band_grouping[source_band_idx] <= lower && source_band_grouping[source_band_idx + 1] >= lower ) + { + do + { + int16_t source_bands_in_target_band = min( source_band_grouping[source_band_idx + 1], upper ) - max( source_band_grouping[source_band_idx], lower ); + if ( source_bands_in_target_band ) + { + source_band_cnt_total += source_bands_in_target_band; + parameter_band_mapping->source_band_idx[target_band_idx][source_band_in_target_band_cnt] = source_band_idx; + parameter_band_mapping->source_band_factor[target_band_idx][source_band_in_target_band_cnt++] = (float) source_bands_in_target_band; + } + source_band_idx++; + } while ( source_band_grouping[source_band_idx] <= upper && source_band_idx < n_source_bands ); + break; + } + } + norm_fac = 1.0f / ( (float) source_band_cnt_total ); + for ( source_band_idx = 0; source_band_idx < source_band_in_target_band_cnt; source_band_idx++ ) + { + + parameter_band_mapping->source_band_factor[target_band_idx][source_band_idx] *= norm_fac; + } + parameter_band_mapping->n_source_bands[target_band_idx] = source_band_in_target_band_cnt; + } + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_param_mc_dec_reconfig() + * + * Reconfiguration of ParamMC decoder + *-------------------------------------------------------------------------*/ + +ivas_error ivas_param_mc_dec_reconfig( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + int16_t k, nchan_transport; + PARAM_MC_DEC_HANDLE hParamMC; + IVAS_OUTPUT_SETUP hTransportSetup; + int16_t nchan_out_transport; + int16_t nchan_out_cov; + float proto_matrix[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float proto_mtx_norm; + int16_t max_param_band_residual; + uint16_t config_index; + MC_LS_SETUP mc_ls_setup; + float frequency_axis[CLDFB_NO_CHANNELS_MAX]; + int32_t output_Fs, ivas_total_brate; + ivas_error error; + int16_t nchan_transport_old; + int16_t num_param_bands_old; + PARAM_MC_PARAMETER_BAND_MAPPING parameter_band_mapping; + int16_t band_grouping_old[20 + 1]; + + error = IVAS_ERR_OK; + hParamMC = st_ivas->hParamMC; + + /* save important config information from the previous state */ + nchan_transport_old = st_ivas->nchan_transport; + num_param_bands_old = hParamMC->hMetadataPMC->num_parameter_bands; + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + hTransportSetup = st_ivas->hTransSetup; + mc_ls_setup = ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ); + nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + hParamMC->hoa_encoder = NULL; + + if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + } + else + { + nchan_out_cov = nchan_out_transport; + } + + st_ivas->nchan_transport = ivas_param_mc_getNumTransportChannels( ivas_total_brate, mc_ls_setup ); + config_index = ivas_param_mc_get_configuration_index( mc_ls_setup, ivas_total_brate ); + nchan_transport = st_ivas->nchan_transport; + + switch ( nchan_transport ) + { + case 4: + case 3: + st_ivas->nCPE = 2; + st_ivas->nSCE = 0; + st_ivas->element_mode_init = IVAS_CPE_MDCT; + break; + case 2: + st_ivas->nCPE = 1; + st_ivas->nSCE = 0; + st_ivas->element_mode_init = IVAS_CPE_MDCT; + + break; +#ifdef DEBUGGING + default: + assert( 0 && "Number of TC not supported for Parametric MC!" ); +#endif + } + + /*-----------------------------------------------------------------* + * set input parameters + *-----------------------------------------------------------------*/ + + hParamMC->slot_size = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX; + hParamMC->subframe_nbslots = CLDFB_NO_COL_MAX / PARAM_MC_NSUBFRAMES_DEC; + + hParamMC->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); + hParamMC->max_band_energy_compensation = hParamMC->num_freq_bands; + + /* deallocate the full icc map, gets newly allocated in the metadata open function */ + + for ( k = 0; k < 2; k++ ) + { +#ifdef DEBUGGING + assert( hParamMC->hMetadataPMC->icc_map_full[k] != NULL ); +#endif + if ( hParamMC->hMetadataPMC->icc_map_full[k] != NULL ) + { + free( hParamMC->hMetadataPMC->icc_map_full[k] ); + hParamMC->hMetadataPMC->icc_map_full[k] = NULL; + } + } + + mvs2s( hParamMC->band_grouping, band_grouping_old, hParamMC->hMetadataPMC->num_parameter_bands + 1 ); + + ivas_param_mc_metadata_open( mc_ls_setup, hTransportSetup.index_lfe[0], ivas_total_brate, hParamMC->hMetadataPMC ); + + /* Band Grouping */ + if ( hParamMC->hMetadataPMC->num_parameter_bands == 20 ) + { + mvs2s( param_mc_band_grouping_20, hParamMC->band_grouping, 20 + 1 ); + } + else if ( hParamMC->hMetadataPMC->num_parameter_bands == 14 ) + { + mvs2s( param_mc_band_grouping_14, hParamMC->band_grouping, 14 + 1 ); + } + else if ( hParamMC->hMetadataPMC->num_parameter_bands == 10 ) + { + mvs2s( param_mc_band_grouping_10, hParamMC->band_grouping, 10 + 1 ); + } + else + { + assert( 0 && "nbands must be 20, 14, or 10!" ); + } + + ivas_param_mc_get_param_band_mapping( hParamMC->hMetadataPMC->num_parameter_bands, hParamMC->band_grouping, num_param_bands_old, band_grouping_old, ¶meter_band_mapping ); + + if ( nchan_transport_old != nchan_transport || num_param_bands_old != hParamMC->hMetadataPMC->num_parameter_bands ) + { + float *ild_q_old = hParamMC->icld_q; + float *icc_q_old = hParamMC->icc_q; + + + /* init arrays for the quantized parameters */ + if ( ( hParamMC->icc_q = (float *) malloc( hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + if ( ( hParamMC->icld_q = (float *) malloc( hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + set_f( hParamMC->icld_q, PARAM_MC_DEFAULT_MIN_ILD, hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe ); + set_f( hParamMC->icc_q, 0.0f, hParamMC->hMetadataPMC->num_parameter_bands * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe ); + + /* map old to new parameter banding, only for same number of TCs, needs some more thought for a changing number of TCs */ + if ( num_param_bands_old != hParamMC->hMetadataPMC->num_parameter_bands && nchan_transport_old == nchan_transport ) + { + int16_t new_param_band_idx, param_idx, source_param_idx; + int16_t num_param_lfe; + float *p_icc_new = hParamMC->icc_q; + float *p_ild_new = hParamMC->icld_q; + + /* ICC */ + num_param_lfe = hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe; + for ( new_param_band_idx = 0; new_param_band_idx < hParamMC->hMetadataPMC->num_parameter_bands; new_param_band_idx++ ) + { + for ( param_idx = 0; param_idx < num_param_lfe; param_idx++ ) + { + *p_icc_new = 0.0f; + for ( source_param_idx = 0; source_param_idx < parameter_band_mapping.n_source_bands[new_param_band_idx]; source_param_idx++ ) + { + *p_icc_new += icc_q_old[parameter_band_mapping.source_band_idx[new_param_band_idx][source_param_idx] * num_param_lfe + param_idx] * parameter_band_mapping.source_band_factor[new_param_band_idx][source_param_idx]; + } + p_icc_new++; + } + } + + /* ILD */ + num_param_lfe = hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe; + for ( new_param_band_idx = 0; new_param_band_idx < hParamMC->hMetadataPMC->num_parameter_bands; new_param_band_idx++ ) + { + for ( param_idx = 0; param_idx < num_param_lfe; param_idx++ ) + { + *p_ild_new = 0.0f; + for ( source_param_idx = 0; source_param_idx < parameter_band_mapping.n_source_bands[new_param_band_idx]; source_param_idx++ ) + { + *p_ild_new += powf( 10.0f, ild_q_old[parameter_band_mapping.source_band_idx[new_param_band_idx][source_param_idx] * num_param_lfe + param_idx] / 10.0f ) * parameter_band_mapping.source_band_factor[new_param_band_idx][source_param_idx]; + } + *p_ild_new = 10.0f * log10f( *p_ild_new ); + p_ild_new++; + } + } + } + free( ild_q_old ); + free( icc_q_old ); + } + + param_mc_set_num_synth_bands( output_Fs, hParamMC ); + + + /* set max parameter band for abs cov */ + k = 0; + while ( hParamMC->band_grouping[k] <= PARAM_MC_MAX_BAND_ABS_COV_DEC ) + { + hParamMC->max_param_band_abs_cov = ( k++ ); + } + + /*-----------------------------------------------------------------* + * open sub-modules + *-----------------------------------------------------------------*/ + + /* prototype signal computation */ + + if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + if ( nchan_transport_old != nchan_transport ) + { + if ( st_ivas->hLsSetUpConversion != NULL ) + { + ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion ); + } + + if ( ( error = ivas_ls_setup_conversion_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* convert the ls conv dmx matrix into column order matrix format (nchan_out_cldfb x nchan_out) */ + free( hParamMC->ls_conv_dmx_matrix ); + if ( ( hParamMC->ls_conv_dmx_matrix = (float *) malloc( nchan_out_transport * nchan_out_cov * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + for ( k = 0; k < nchan_out_transport; k++ ) + { + mvr2r( st_ivas->hLsSetUpConversion->dmxMtx[k], &hParamMC->ls_conv_dmx_matrix[k * nchan_out_cov], nchan_out_cov ); + } + } + /* convert ParamMC parameter bands to SFB */ + + st_ivas->hLsSetUpConversion->sfbCnt = hParamMC->num_param_bands_synth; + for ( k = 0; k <= hParamMC->num_param_bands_synth; k++ ) + { + st_ivas->hLsSetUpConversion->sfbOffset[k] = PARAM_MC_BAND_TO_MDCT_BAND_RATIO * hParamMC->band_grouping[k]; + } + for ( ; k < MAX_SFB + 2; k++ ) + { + st_ivas->hLsSetUpConversion->sfbOffset[k] = 0; + } + } + + if ( nchan_transport_old != nchan_transport ) + { + free( hParamMC->proto_matrix_int ); + if ( ( hParamMC->proto_matrix_int = (float *) malloc( nchan_out_transport * nchan_transport * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + mvr2r( ivas_param_mc_conf[config_index].dmx_fac, hParamMC->proto_matrix_int, nchan_transport * nchan_out_transport ); + } + + if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + matrix_product( hParamMC->ls_conv_dmx_matrix, nchan_out_cov, nchan_out_transport, 0, + ivas_param_mc_conf[config_index].dmx_fac, nchan_out_transport, nchan_transport, 0, + proto_matrix ); + + if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + proto_mtx_norm = 1.f; + for ( k = 0; k < nchan_transport * nchan_out_cov; k++ ) + { + proto_mtx_norm = max( fabsf( proto_mtx_norm ), fabsf( proto_matrix[k] ) ); + } + proto_mtx_norm = 1.f / proto_mtx_norm; + + /* transfer flattened proto_matrix to 2D in hLsSetupConversion->dmxMtx */ + for ( k = 0; k < nchan_transport; k++ ) + { + for ( int16_t i = 0; i < nchan_out_cov; i++ ) + { + st_ivas->hLsSetUpConversion->dmxMtx[k][i] = proto_matrix[k * nchan_out_cov + i] * proto_mtx_norm; + } + } + } + } + else + { + mvr2r( ivas_param_mc_conf[config_index].dmx_fac, proto_matrix, nchan_out_transport * nchan_transport ); + } + + if ( nchan_transport_old != nchan_transport && hParamMC->synthesis_conf != PARAM_MC_SYNTH_MONO_STEREO ) + { + int16_t i; + int16_t len; + + /* close decorrelator */ + ivas_dirac_dec_decorr_close( &hParamMC->h_freq_domain_decorr_ap_params, &hParamMC->h_freq_domain_decorr_ap_state ); + + /* deallocate diffuse prototype info */ + if ( hParamMC->diff_proto_info ) + { + for ( i = 0; i < hParamMC->diff_proto_info->num_protos_diff; i++ ) + { + free( hParamMC->diff_proto_info->source_chan_idx[i] ); + hParamMC->diff_proto_info->source_chan_idx[i] = NULL; + + free( hParamMC->diff_proto_info->proto_fac[i] ); + hParamMC->diff_proto_info->proto_fac[i] = NULL; + } + + free( hParamMC->diff_proto_info->source_chan_idx ); + hParamMC->diff_proto_info->source_chan_idx = NULL; + + free( hParamMC->diff_proto_info->proto_fac ); + hParamMC->diff_proto_info->proto_fac = NULL; + + free( hParamMC->diff_proto_info->proto_index_diff ); + hParamMC->diff_proto_info->proto_index_diff = NULL; + + free( hParamMC->diff_proto_info->num_source_chan_diff ); + hParamMC->diff_proto_info->num_source_chan_diff = NULL; + + free( hParamMC->diff_proto_info ); + hParamMC->diff_proto_info = NULL; + } + + hParamMC->num_outputs_diff = nchan_out_cov; + if ( ( hParamMC->diff_proto_info = (PARAM_MC_DIFF_PROTO_INFO *) malloc( sizeof( PARAM_MC_DIFF_PROTO_INFO ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + + if ( ( param_mc_get_diff_proto_info( proto_matrix, nchan_transport, nchan_out_cov, hParamMC->diff_proto_info ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* decorrelation */ + hParamMC->h_freq_domain_decorr_ap_params = NULL; + hParamMC->h_freq_domain_decorr_ap_state = NULL; + + ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, hParamMC->num_freq_bands ); + + if ( ( error = ivas_dirac_dec_decorr_open( &( hParamMC->h_freq_domain_decorr_ap_params ), + &( hParamMC->h_freq_domain_decorr_ap_state ), + hParamMC->num_freq_bands, + hParamMC->num_outputs_diff, + hParamMC->diff_proto_info->num_protos_diff, + DIRAC_SYNTHESIS_COV_MC_LS, + frequency_axis, + nchan_transport, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + + hParamMC->h_output_synthesis_params.use_onset_filters = 0; + hParamMC->max_band_decorr = hParamMC->h_freq_domain_decorr_ap_params->max_band_decorr; + /* init decorrelation */ + if ( hParamMC->max_band_decorr > 0 ) + { + + len = hParamMC->diff_proto_info->num_protos_diff * hParamMC->h_freq_domain_decorr_ap_params->h_onset_detection_power_params.max_band_decorr; + + /* init onsetDetectionPower */ + set_zero( hParamMC->h_freq_domain_decorr_ap_state->h_onset_detection_power_state.onset_detector_1, len ); + set_zero( hParamMC->h_freq_domain_decorr_ap_state->h_onset_detection_power_state.onset_detector_2, len ); + } + } + hParamMC->max_band_energy_compensation = hParamMC->band_grouping[hParamMC->hMetadataPMC->nbands_coded]; + max_param_band_residual = 0; + + for ( k = hParamMC->hMetadataPMC->num_parameter_bands; k >= 0; k-- ) + { + if ( hParamMC->band_grouping[k] <= hParamMC->max_band_decorr ) + { + max_param_band_residual = k; + assert( hParamMC->band_grouping[k] == hParamMC->max_band_decorr ); + break; + } + } + + if ( nchan_transport_old != nchan_transport || num_param_bands_old != hParamMC->hMetadataPMC->num_parameter_bands ) + { + DIRAC_OUTPUT_SYNTHESIS_COV_STATE cov_state_old = hParamMC->h_output_synthesis_cov_state; + DIRAC_OUTPUT_SYNTHESIS_PARAMS params_old = hParamMC->h_output_synthesis_params; + float tmp_buf[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + + set_zero( tmp_buf, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS ); + + /* output synthesis */ + if ( ( error = ivas_dirac_dec_output_synthesis_cov_open( &( hParamMC->h_output_synthesis_params ), + &( hParamMC->h_output_synthesis_cov_state ), + hParamMC->max_band_decorr, + PARAM_MC_MAX_NSLOTS, + hParamMC->hMetadataPMC->num_parameter_bands, + max_param_band_residual, + nchan_transport, + nchan_out_cov, + proto_matrix ) ) != IVAS_ERR_OK ) + { + return error; + } + + ivas_dirac_dec_output_synthesis_cov_init( &( hParamMC->h_output_synthesis_cov_state ), nchan_transport, nchan_out_cov, hParamMC->hMetadataPMC->num_parameter_bands, max_param_band_residual ); + + + /* map old to new parameter banding, only for same number of TCs, needs some more thought for changing number of TCs */ + if ( num_param_bands_old != hParamMC->hMetadataPMC->num_parameter_bands && nchan_transport_old == nchan_transport ) + { + int16_t new_param_band_idx, source_param_idx; + + + for ( new_param_band_idx = 0; new_param_band_idx < hParamMC->hMetadataPMC->num_parameter_bands; new_param_band_idx++ ) + { + for ( source_param_idx = 0; source_param_idx < parameter_band_mapping.n_source_bands[new_param_band_idx]; source_param_idx++ ) + { + /* Cx */ + v_multc( cov_state_old.cx_old[parameter_band_mapping.source_band_idx[new_param_band_idx][source_param_idx]], parameter_band_mapping.source_band_factor[new_param_band_idx][source_param_idx], tmp_buf, nchan_transport_old * nchan_transport_old ); + v_add( tmp_buf, hParamMC->h_output_synthesis_cov_state.cx_old[new_param_band_idx], hParamMC->h_output_synthesis_cov_state.cx_old[new_param_band_idx], nchan_transport_old * nchan_transport_old ); + /* Cy */ + v_multc( cov_state_old.cy_old[parameter_band_mapping.source_band_idx[new_param_band_idx][source_param_idx]], parameter_band_mapping.source_band_factor[new_param_band_idx][source_param_idx], tmp_buf, nchan_out_cov * nchan_out_cov ); + v_add( tmp_buf, hParamMC->h_output_synthesis_cov_state.cy_old[new_param_band_idx], hParamMC->h_output_synthesis_cov_state.cy_old[new_param_band_idx], nchan_out_cov * nchan_out_cov ); + /* mixing matrix*/ + v_multc( cov_state_old.mixing_matrix_old[parameter_band_mapping.source_band_idx[new_param_band_idx][source_param_idx]], parameter_band_mapping.source_band_factor[new_param_band_idx][source_param_idx], tmp_buf, nchan_transport_old * nchan_out_cov ); + v_add( tmp_buf, hParamMC->h_output_synthesis_cov_state.mixing_matrix_old[new_param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_old[new_param_band_idx], nchan_transport_old * nchan_out_cov ); + } + } + for ( new_param_band_idx = 0; new_param_band_idx < max_param_band_residual; new_param_band_idx++ ) + { + for ( source_param_idx = 0; source_param_idx < parameter_band_mapping.n_source_bands[new_param_band_idx]; source_param_idx++ ) + { + /* residual mixing matrix*/ + v_multc( cov_state_old.mixing_matrix_res_old[parameter_band_mapping.source_band_idx[new_param_band_idx][source_param_idx]], parameter_band_mapping.source_band_factor[new_param_band_idx][source_param_idx], tmp_buf, nchan_out_cov * nchan_out_cov ); + v_add( tmp_buf, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[new_param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[new_param_band_idx], nchan_out_cov * nchan_out_cov ); + } + } + } + + ivas_dirac_dec_output_synthesis_cov_close( ¶ms_old, &cov_state_old ); + } + + /*-----------------------------------------------------------------* + * memory allocation + *-----------------------------------------------------------------*/ + + if ( hParamMC->max_band_decorr > 0 && nchan_transport_old != nchan_transport ) + { + free( hParamMC->proto_frame_f ); + if ( ( hParamMC->proto_frame_f = (float *) malloc( 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + set_zero( hParamMC->proto_frame_f, 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands ); + } + + return error; +} + + /*------------------------------------------------------------------------- * param_mc_get_num_cldfb_syntheses() * @@ -487,19 +1047,19 @@ void ivas_param_mc_dec_close( { ivas_param_mc_metadata_close( hParamMC->hMetadataPMC ); - count_free( hParamMC->hMetadataPMC ); + free( hParamMC->hMetadataPMC ); hParamMC->hMetadataPMC = NULL; } if ( hParamMC->icc_q != NULL ) { - count_free( hParamMC->icc_q ); + free( hParamMC->icc_q ); hParamMC->icc_q = NULL; } if ( hParamMC->icld_q != NULL ) { - count_free( hParamMC->icld_q ); + free( hParamMC->icld_q ); hParamMC->icld_q = NULL; } @@ -508,26 +1068,26 @@ void ivas_param_mc_dec_close( { for ( i = 0; i < hParamMC->diff_proto_info->num_protos_diff; i++ ) { - count_free( hParamMC->diff_proto_info->source_chan_idx[i] ); + free( hParamMC->diff_proto_info->source_chan_idx[i] ); hParamMC->diff_proto_info->source_chan_idx[i] = NULL; - count_free( hParamMC->diff_proto_info->proto_fac[i] ); + free( hParamMC->diff_proto_info->proto_fac[i] ); hParamMC->diff_proto_info->proto_fac[i] = NULL; } - count_free( hParamMC->diff_proto_info->source_chan_idx ); + free( hParamMC->diff_proto_info->source_chan_idx ); hParamMC->diff_proto_info->source_chan_idx = NULL; - count_free( hParamMC->diff_proto_info->proto_fac ); + free( hParamMC->diff_proto_info->proto_fac ); hParamMC->diff_proto_info->proto_fac = NULL; - count_free( hParamMC->diff_proto_info->proto_index_diff ); + free( hParamMC->diff_proto_info->proto_index_diff ); hParamMC->diff_proto_info->proto_index_diff = NULL; - count_free( hParamMC->diff_proto_info->num_source_chan_diff ); + free( hParamMC->diff_proto_info->num_source_chan_diff ); hParamMC->diff_proto_info->num_source_chan_diff = NULL; - count_free( hParamMC->diff_proto_info ); + free( hParamMC->diff_proto_info ); hParamMC->diff_proto_info = NULL; } @@ -536,36 +1096,36 @@ void ivas_param_mc_dec_close( /* free prototype signal buffers */ if ( hParamMC->proto_frame_f != NULL ) { - count_free( hParamMC->proto_frame_f ); + free( hParamMC->proto_frame_f ); hParamMC->proto_frame_f = NULL; } if ( hParamMC->proto_frame_dec_f != NULL ) { - count_free( hParamMC->proto_frame_dec_f ); + free( hParamMC->proto_frame_dec_f ); hParamMC->proto_frame_dec_f = NULL; } if ( hParamMC->ls_conv_dmx_matrix != NULL ) { - count_free( hParamMC->ls_conv_dmx_matrix ); + free( hParamMC->ls_conv_dmx_matrix ); hParamMC->ls_conv_dmx_matrix = NULL; } if ( hParamMC->proto_matrix_int != NULL ) { - count_free( hParamMC->proto_matrix_int ); + free( hParamMC->proto_matrix_int ); hParamMC->proto_matrix_int = NULL; } if ( hParamMC->hoa_encoder != NULL ) { - count_free( hParamMC->hoa_encoder ); + free( hParamMC->hoa_encoder ); hParamMC->hoa_encoder = NULL; } - count_free( hParamMC ); - hParamMC = NULL; + free( *hParamMC_out ); + *hParamMC_out = NULL; return; } @@ -599,7 +1159,7 @@ void ivas_param_mc_dec_read_BS( int16_t ild_map_size_wo_lfe; HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC; - wmops_sub_start( "param_mc_read_bs" ); + push_wmops( "param_mc_read_bs" ); /* Inits */ *nb_bits = 0; @@ -761,7 +1321,6 @@ void ivas_param_mc_dec_read_BS( *nb_bits = bit_pos; - } /* if ( !st->bfi ) */ if ( st->bfi ) @@ -771,7 +1330,7 @@ void ivas_param_mc_dec_read_BS( hMetadataPMC->attackIndex = 0; } - wmops_sub_end(); + pop_wmops(); return; } @@ -817,7 +1376,7 @@ void ivas_param_mc_dec( hParamMC = st_ivas->hParamMC; assert( hParamMC ); - wmops_sub_start( "param_mc_dec" ); + push_wmops( "param_mc_dec" ); set_s( channel_active, 0, MAX_CICP_CHANNELS ); nchan_transport = st_ivas->nchan_transport; @@ -1051,8 +1610,7 @@ void ivas_param_mc_dec( if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) { - ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, - Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); + ivas_binRenderer( st_ivas->hBinRenderer, st_ivas->hHeadTrackData, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); } else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) { @@ -1101,7 +1659,7 @@ void ivas_param_mc_dec( /* update */ hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; param_mc_update_mixing_matrices( hParamMC, mixing_matrix, mixing_matrix_res, nchan_transport, nchan_out_cov ); - wmops_sub_end(); + pop_wmops(); return; } @@ -1313,6 +1871,7 @@ static int16_t ivas_param_mc_uniform_decoder( return n_bits; } + /*------------------------------------------------------------------------- * ivas_param_mc_range_decoder_LC() * @@ -1371,6 +1930,7 @@ static int16_t ivas_param_mc_range_decoder_LC( return cur_bit_pos; } + /*------------------------------------------------------------------------- * param_mc_compute_interpolator() * @@ -1446,9 +2006,11 @@ static void remove_lfe_from_cy( } ptrCy += nY; } + return; } + /*------------------------------------------------------------------------- * ivas_param_mc_get_mixing_matrices() * @@ -1564,6 +2126,14 @@ static void ivas_param_mc_get_mixing_matrices( matrix_product( mat_mult_buffer1, nY_intern, nX, 0, hParamMC->proto_matrix_int, nY_intern, nX, 1, Cproto ); + for ( ch_idx1 = 0; ch_idx1 < nY_intern; ch_idx1++ ) + { + if ( Cproto[ch_idx1 + ch_idx1 * nY_intern] < 0.0f ) + { + Cproto[ch_idx1 + ch_idx1 * nY_intern] = 0.0f; + } + } + ivas_param_mc_dequantize_cov( hParamMC, hParamMC->icld_q + param_band_idx * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe, hParamMC->icc_q + param_band_idx * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe, @@ -1604,6 +2174,15 @@ static void ivas_param_mc_get_mixing_matrices( matrix_product_diag( mat_mult_buffer1, nY_band, nX, 0, proto_matrix_ptr, nY_band, nX, 1, Cproto_diag ); + /* make sure we have no negative entries in Cproto_diag due to rounding errors */ + for ( ch_idx1 = 0; ch_idx1 < nY_band; ch_idx1++ ) + { + if ( Cproto_diag[ch_idx1] < 0.0f ) + { + Cproto_diag[ch_idx1] = 0.0f; + } + } + /* Computing the mixing matrices */ /* bands with decorr */ @@ -1808,6 +2387,7 @@ static void ivas_param_mc_get_mono_stereo_mixing_matrices( return; } + /*------------------------------------------------------------------------- * param_mc_update_mixing_matrices() * @@ -1842,6 +2422,7 @@ static void param_mc_update_mixing_matrices( return; } + /*------------------------------------------------------------------------- * ivas_param_mc_dequantize_cov() * @@ -2051,13 +2632,14 @@ static void param_mc_set_num_synth_bands( return; } + /*-------------------------------------------------------------------------* * param_mc_get_diff_proto_info() * * calculated the diffuse prototype information *-------------------------------------------------------------------------*/ -static void param_mc_get_diff_proto_info( +static ivas_error param_mc_get_diff_proto_info( const float *proto_mtx, /* i : protoype matrix for the synthesis */ const uint16_t nchan_transport, /* i : number of transport channels */ const uint16_t nchan_out_cov, /* i : number if output channels of the covariance synthesis */ @@ -2073,9 +2655,16 @@ static void param_mc_get_diff_proto_info( /* Initializations */ max_num_src_chan = 0; set_zero( proto_fac, MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS ); - p_diff_proto_info->proto_index_diff = (int16_t *) count_malloc( nchan_out_cov * sizeof( int16_t ) ); + if ( ( p_diff_proto_info->proto_index_diff = (int16_t *) malloc( nchan_out_cov * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } set_s( p_diff_proto_info->proto_index_diff, 0, nchan_out_cov ); - p_diff_proto_info->num_source_chan_diff = (int16_t *) count_malloc( nchan_out_cov * sizeof( int16_t ) ); + + if ( ( p_diff_proto_info->num_source_chan_diff = (int16_t *) malloc( nchan_out_cov * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } set_s( p_diff_proto_info->num_source_chan_diff, 0, nchan_out_cov ); /* we have at least one prototype, copy the first one */ @@ -2134,17 +2723,28 @@ static void param_mc_get_diff_proto_info( } } - /* set up the prototype info struct */ - p_diff_proto_info->source_chan_idx = (int16_t **) count_malloc( p_diff_proto_info->num_protos_diff * sizeof( int16_t * ) ); - p_diff_proto_info->proto_fac = (float **) count_malloc( p_diff_proto_info->num_protos_diff * sizeof( float * ) ); + if ( ( p_diff_proto_info->source_chan_idx = (int16_t **) malloc( p_diff_proto_info->num_protos_diff * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + if ( ( p_diff_proto_info->proto_fac = (float **) malloc( p_diff_proto_info->num_protos_diff * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } for ( cur_diff_proto = 0; cur_diff_proto < p_diff_proto_info->num_protos_diff; cur_diff_proto++ ) { float *proto_fac_ptr; - p_diff_proto_info->source_chan_idx[cur_diff_proto] = (int16_t *) count_malloc( max_num_src_chan * sizeof( int16_t ) ); - p_diff_proto_info->proto_fac[cur_diff_proto] = (float *) count_malloc( max_num_src_chan * sizeof( float ) ); + if ( ( p_diff_proto_info->source_chan_idx[cur_diff_proto] = (int16_t *) malloc( max_num_src_chan * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + if ( ( p_diff_proto_info->proto_fac[cur_diff_proto] = (float *) malloc( max_num_src_chan * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } proto_fac_ptr = proto_fac + cur_diff_proto; for ( cur_transport_ch = 0; cur_transport_ch < nchan_transport; cur_transport_ch++ ) @@ -2159,8 +2759,7 @@ static void param_mc_get_diff_proto_info( } } - - return; + return IVAS_ERR_OK; } @@ -2246,7 +2845,7 @@ static void ivas_param_mc_mc2sba_cldfb( * reads and decodes a sequence of Parametric MC parameters from the bitstream *-------------------------------------------------------------------------*/ -void ivas_param_mc_bs_decode_parameter_values( +static void ivas_param_mc_bs_decode_parameter_values( uint16_t bit_buffer[], /* i : bitstream buffer */ int16_t *bit_pos, /* i/o: current bitstream buffer position */ const int16_t max_bits, /* i : maximum available bits in the buffer */ diff --git a/lib_dec/ivas_mcmasa_dec.c b/lib_dec/ivas_mcmasa_dec.c new file mode 100644 index 0000000000000000000000000000000000000000..d075bf61da999ff97a6a1b29b2b627b72780fa3d --- /dev/null +++ b/lib_dec/ivas_mcmasa_dec.c @@ -0,0 +1,152 @@ +/****************************************************************************************************** + +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" +#include +#include "ivas_cnst.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*------------------------------------------------------------------------- + * ivas_mcmasa_dec_reconfig() + * + * Reconfigure McMASA decoder + *------------------------------------------------------------------------*/ + +ivas_error ivas_mcmasa_dec_reconfig( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + ivas_error error; + int32_t ivas_total_brate; + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + /* close the old MASA instance */ + ivas_masa_dec_close( &( st_ivas->hMasa ) ); + + /* get new McMASA settings */ + ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->element_mode_init ), ivas_total_brate ); + ivas_mcmasa_set_separate_channel_mode( &( st_ivas->hOutSetup.separateChannelEnabled ), &( st_ivas->hOutSetup.separateChannelIndex ), ivas_total_brate ); + + /* transport channel settings may affect renderer */ + ivas_renderer_select( st_ivas ); + + /* renderer change may affect internal config */ + ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); + ivas_mcmasa_set_separate_channel_mode( &( st_ivas->hIntSetup.separateChannelEnabled ), &( st_ivas->hIntSetup.separateChannelIndex ), ivas_total_brate ); + + if ( ( error = ivas_masa_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + +#ifdef SBA2MONO + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#else + st_ivas->sba_dirac_stereo_flag = ( st_ivas->nchan_transport == 1 && st_ivas->hOutSetup.output_config == AUDIO_CONFIG_STEREO ); +#endif + + if ( st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_MCMASA_MONO_STEREO ) + { + if ( st_ivas->hDirAC == NULL ) + { + if ( ( error = ivas_dirac_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + /*-------------------------------------------------------------------* + * Close binaural rendering handles and re-allocate proper ones + * in McMASA renderer_type can be only RENDERER_BINAURAL_PARAMETRIC, RENDERER_BINAURAL_PARAMETRIC_ROOM + *--------------------------------------------------------------------*/ + + if ( st_ivas->hBinRenderer != NULL ) + { + ivas_binRenderer_close( &st_ivas->hBinRenderer ); + } + + if ( st_ivas->hDiracDecBin == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + /* open parametric binaural renderer */ + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDiracDecBin != NULL ) + { + if ( st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + /* close unneeded renderer */ + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + } + else + { + /* the decision for useTdDecorr is done in ivas_dirac_dec_init_binaural_data(). here, comparing against the same condition. */ + if ( st_ivas->hDiracDecBin->useTdDecorr != ( ivas_total_brate < IVAS_48k && st_ivas->nchan_transport == 1 ) ) + { + /* st_ivas->hDiracDecBin->useTdDecorr will change => close and re-open. */ + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + } + + return error; +} diff --git a/lib_dec/ivas_mct_core_dec.c b/lib_dec/ivas_mct_core_dec.c index d7459efabdafac850c23e4340e28224bc430febb..5222d39b6436c2c2e4ae3563eec0235a3fa968e6 100644 --- a/lib_dec/ivas_mct_core_dec.c +++ b/lib_dec/ivas_mct_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "cnst.h" #include "basop_proto_func.h" #include "stat_com.h" @@ -70,7 +70,11 @@ void ivas_mct_side_bits( Decoder_State *st, *sts[MCT_MAX_CHANNELS]; nf_side_bits = 0; - nChannels = hMCT->nchan_out_woLFE + hMCT->num_lfe; + nChannels = hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ; /*initializations */ for ( cpe_id = 0, i = 0; cpe_id < nCPE; cpe_id++ ) @@ -88,7 +92,11 @@ void ivas_mct_side_bits( for ( ch = 0; ch < nChannels; ch++ ) { st = sts[ch]; - if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE || st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -108,15 +116,17 @@ void ivas_mct_side_bits( availableBits = 0; ivas_mct_dec_mct( hMCT, sts, nChannels ); - /* availableBits = ((hMCT->mc_bitrate/50) - sts[0]->next_bit_pos); - availableBits -= NBBITS_MCT_RATIO * nChannels;*/ /*read channel bitrate ratios from bitstream*/ for ( ch = 0; ch < nChannels; ch++ ) { st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && hMCT->LFE_off ) || st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && hMCT->LFE_off ) || +#endif + st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { chBitRatios[ch] = 0; st->bits_frame_channel = 0; @@ -183,13 +193,17 @@ void ivas_mct_core_dec( float nrg[MCT_MAX_CHANNELS]; #endif - wmops_sub_start( "mct_decoding" ); + push_wmops( "mct_decoding" ); /*--------------------------------------------------------------------------------* * Initializations *--------------------------------------------------------------------------------*/ - nChannels = hMCT->nchan_out_woLFE + hMCT->num_lfe; + nChannels = hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ; /*initializations */ for ( cpe_id = 0, i = 0; cpe_id < nCPE; cpe_id++ ) @@ -203,7 +217,11 @@ void ivas_mct_core_dec( for ( ch = 0, i = 0; ch < nChannels; ch++ ) { - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -232,7 +250,11 @@ void ivas_mct_core_dec( { st = sts[ch]; - if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) /*indicates LFE */ + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) /*indicates LFE */ { continue; } @@ -269,7 +291,7 @@ void ivas_mct_core_dec( apply_MCT_dec( hMCT, sts, x ); } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 31f32084291d8ddf9239f5a10c592e474f95ce34..4492968ad8e32902084ae90566a379fbfabf6ae1 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,15 +39,24 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_rom_com.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif + +/*-----------------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------------*/ + +static ivas_error ivas_mc_dec_reconfig( Decoder_Struct *st_ivas ); + + /*--------------------------------------------------------------------------* * ivas_mct_dec() * @@ -77,10 +86,9 @@ ivas_error ivas_mct_dec( int32_t ivas_total_brate; ivas_error error; - error = IVAS_ERR_OK; - - wmops_sub_start( "ivas_mct_dec" ); + push_wmops( "ivas_mct_dec" ); + error = IVAS_ERR_OK; nCPE = st_ivas->nCPE; hMCT = st_ivas->hMCT; @@ -98,10 +106,12 @@ ivas_error ivas_mct_dec( } } +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( !st_ivas->bfi ) { hMCT->LFE_off = 0; /* in case of PLC, stick to LFE_off of previous frame; otherwise, the update happens in ivas_mdct_dec_side_bits_frame_channel() */ } +#endif for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) { @@ -123,9 +133,14 @@ ivas_error ivas_mct_dec( if ( !st_ivas->bfi ) { - ivas_mdct_dec_side_bits_frame_channel( st_ivas->hCPE[cpe_id], param_lpc[cpe_id], p_param[cpe_id], st_ivas->hCPE[0]->hCoreCoder[0], - &hMCT->LFE_off, nTnsBitsTCX10[cpe_id], param[cpe_id], 1, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ivas_mdct_dec_side_bits_frame_channel( st_ivas->hCPE[cpe_id], param_lpc[cpe_id], p_param[cpe_id], st_ivas->hCPE[0]->hCoreCoder[0], &hMCT->LFE_off, nTnsBitsTCX10[cpe_id], param[cpe_id], 1, ( ( cpe_id + 1 ) * CPE_CHANNELS > st_ivas->nchan_transport ) ); +#else + ivas_mdct_dec_side_bits_frame_channel( st_ivas->hCPE[cpe_id], param_lpc[cpe_id], p_param[cpe_id], st_ivas->hCPE[0]->hCoreCoder[0], nTnsBitsTCX10[cpe_id], param[cpe_id], 1, + ( ( cpe_id + 1 ) * CPE_CHANNELS > hMCT->nchan_out_woLFE ) ); +#endif + st_ivas->BER_detect |= st_ivas->hCPE[cpe_id]->hCoreCoder[0]->BER_detect; st_ivas->BER_detect |= st_ivas->hCPE[cpe_id]->hCoreCoder[1]->BER_detect; @@ -148,7 +163,13 @@ ivas_error ivas_mct_dec( set_zero( x[n][1], L_FRAME48k / 2 ); } - ivas_mdct_core_invQ( st_ivas->hCPE[cpe_id], hMCT->LFE_off, nTnsBitsTCX10[cpe_id], p_param[cpe_id], param_lpc[cpe_id], param[cpe_id], + ivas_mdct_core_invQ( st_ivas->hCPE[cpe_id] +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + hMCT->LFE_off +#endif + , + nTnsBitsTCX10[cpe_id], p_param[cpe_id], param_lpc[cpe_id], param[cpe_id], fUseTns[cpe_id], tnsData[cpe_id], x, x, Aq[cpe_id], NULL, 1 ); st_ivas->BER_detect |= st_ivas->hCPE[cpe_id]->hCoreCoder[0]->BER_detect; @@ -158,6 +179,18 @@ ivas_error ivas_mct_dec( /* MCT core decoder */ ivas_mct_core_dec( hMCT, st_ivas->hCPE, nCPE, output ); + /* for sba to stereo output disable any further processing for TCs > 2 as it is not needed*/ + if ( st_ivas->sba_dirac_stereo_flag ) + { + for ( cpe_id = 1; cpe_id < nCPE; cpe_id++ ) + { + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + } + } + } + /* MCT reconstruction and CoreCoder updates */ for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) { @@ -169,7 +202,11 @@ ivas_error ivas_mct_dec( x[n][1] = &output[n + cpe_id * CPE_CHANNELS][L_FRAME48k / 2]; } - ivas_mdct_core_tns_ns( hCPE, hMCT->LFE_off, fUseTns[cpe_id], tnsData[cpe_id], x, Aq[cpe_id], 1 ); + ivas_mdct_core_tns_ns( hCPE, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + hMCT->LFE_off, +#endif + fUseTns[cpe_id], tnsData[cpe_id], x, Aq[cpe_id], 1 ); } if ( st_ivas->renderer_type == RENDERER_MC ) @@ -204,7 +241,11 @@ ivas_error ivas_mct_dec( x[n][1] = &output[n + cpe_id * CPE_CHANNELS][L_FRAME48k / 2]; } - ivas_mdct_core_reconstruct( hCPE, x, synth, hMCT->LFE_off, fUseTns[cpe_id], 1 ); + ivas_mdct_core_reconstruct( hCPE, x, synth, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + hMCT->LFE_off, +#endif + fUseTns[cpe_id], 1 ); /*----------------------------------------------------------------* * CoreCoder Post-processing and updates @@ -212,13 +253,24 @@ ivas_error ivas_mct_dec( for ( n = 0; n < CPE_CHANNELS; n++ ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[n]->mct_chan_mode == MCT_CHAN_MODE_LFE ) { break; } +#endif + + if ( st_ivas->sba_dirac_stereo_flag ) + { + ivas_post_proc( NULL, hCPE, n, synth[n], NULL, output_frame, 1 ); + } /* Postprocessing for ACELP/MDCT core switching and synchronization */ - if ( ( error = core_switching_post_dec( sts[n], synth[n], output[cpe_id * CPE_CHANNELS + n], hCPE->output_mem[1], 0, output_frame, 0 /*core_switching_flag*/, 0, -1, hCPE->last_element_mode ) ) != IVAS_ERR_OK ) +#ifdef FIX_ISM_DTX_CLICKS + if ( ( error = core_switching_post_dec( sts[n], synth[n], output[cpe_id * CPE_CHANNELS + n], hCPE->output_mem[1], st_ivas->ivas_format, 0, output_frame, 0 /*core_switching_flag*/, st_ivas->sba_dirac_stereo_flag, -1, hCPE->last_element_mode ) ) != IVAS_ERR_OK ) +#else + if ( ( error = core_switching_post_dec( sts[n], synth[n], output[cpe_id * CPE_CHANNELS + n], hCPE->output_mem[1], 0, output_frame, 0 /*core_switching_flag*/, st_ivas->sba_dirac_stereo_flag, -1, hCPE->last_element_mode ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -239,7 +291,10 @@ ivas_error ivas_mct_dec( /* synthesis synchronization between stereo modes */ - synchro_synthesis( ivas_total_brate, hCPE, output + cpe_id * CPE_CHANNELS, output_frame, 0 ); + if ( !st_ivas->sba_dirac_stereo_flag ) + { + synchro_synthesis( ivas_total_brate, hCPE, output + cpe_id * CPE_CHANNELS, output_frame, 0 ); + } #ifdef DEBUG_PLOT for ( n = 0; n < CPE_CHANNELS; n++ ) @@ -249,8 +304,38 @@ ivas_error ivas_mct_dec( } #endif } +#ifdef ISSUE_24_CLEANUP_MCT_LFE + /* move channels after LFE to correct output for multi-channel MCT */ + if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) + { + float tmp[L_FRAME48k]; + + /*save center channel output*/ + mvr2r( output[hMCT->nchan_out_woLFE - 1], tmp, output_frame ); + + for ( n = hMCT->nchan_out_woLFE - 1; n >= LFE_CHANNEL; n-- ) + { + mvr2r( output[n - 1], output[n + 1], output_frame ); + } + mvr2r( tmp, output[LFE_CHANNEL - 1], output_frame ); + set_zero( output[LFE_CHANNEL], output_frame ); + } +#endif + +#ifdef DEBUG_MODE_INFO + for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) + { + float tmpF = st_ivas->hCPE[cpe_id]->element_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "element_brate", 0, cpe_id, DEC ) ); + + dbgwrite( output[0], sizeof( float ), output_frame, 1, fname( debug_dir, "output.mct", 0, cpe_id, DEC ) ); + tmpF = 0; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.sce", 0, cpe_id, DEC ) ); + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.cpe", 0, cpe_id, DEC ) ); + } +#endif - wmops_sub_end(); + pop_wmops(); return error; } @@ -271,11 +356,11 @@ ivas_error create_mct_dec( int16_t max_blocks; int16_t cpe_id; - /*-----------------------------------------------------------------* + /*--------------------------------------------------------- --------* * Allocate MCT handle *-----------------------------------------------------------------*/ - if ( ( hMCT = (MCT_DEC_HANDLE) count_malloc( sizeof( MCT_DEC_DATA ) ) ) == NULL ) + if ( ( hMCT = (MCT_DEC_HANDLE) malloc( sizeof( MCT_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CPE\n" ) ); } @@ -285,6 +370,7 @@ ivas_error create_mct_dec( *-----------------------------------------------------------------*/ /* Determine active channels */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) { hMCT->num_lfe = st_ivas->hTransSetup.num_lfe; @@ -300,6 +386,16 @@ ivas_error create_mct_dec( hMCT->num_lfe = 0; hMCT->nchan_out_woLFE = st_ivas->nchan_transport; } +#else + if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC ) || st_ivas->ivas_format == SBA_FORMAT ) + { + hMCT->nchan_out_woLFE = st_ivas->nchan_transport; + } + else if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + hMCT->nchan_out_woLFE = st_ivas->nchan_transport - st_ivas->hTransSetup.num_lfe; + } +#endif else { assert( !"IVAS format currently not supported for MCT" ); @@ -313,14 +409,21 @@ ivas_error create_mct_dec( for ( n = 0; n < CPE_CHANNELS; n++ ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ( hMCT->num_lfe > 0 ) && ( ( n + cpe_id * CPE_CHANNELS ) == LFE_CHANNEL ) ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_LFE; } +#endif } } /* in case we have an uneven number of transport channels, indicate last channel ID as inactive */ - if ( ( hMCT->nchan_out_woLFE + hMCT->num_lfe ) % 2 ) + if ( ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ) % + 2 ) { st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; } @@ -330,7 +433,7 @@ ivas_error create_mct_dec( for ( n = 0; n < max_blocks; n++ ) { - if ( ( hMCT->hBlockData[n] = (MCT_DEC_BLOCK_DATA_HANDLE) count_malloc( sizeof( MCT_DEC_BLOCK_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n] = (MCT_DEC_BLOCK_DATA_HANDLE) malloc( sizeof( MCT_DEC_BLOCK_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT block data structure\n" ) ); } @@ -343,7 +446,7 @@ ivas_error create_mct_dec( * MDCT stereo initialization *-----------------------------------------------------------------*/ - if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); } @@ -400,6 +503,7 @@ ivas_error mct_dec_reconfigure( if ( b_nchan_change ) { /* Determine active channels */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) { hMCT->num_lfe = st_ivas->hTransSetup.num_lfe; @@ -415,6 +519,16 @@ ivas_error mct_dec_reconfigure( hMCT->num_lfe = 0; hMCT->nchan_out_woLFE = st_ivas->nchan_transport; } +#else + if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC ) || st_ivas->ivas_format == SBA_FORMAT ) + { + hMCT->nchan_out_woLFE = st_ivas->nchan_transport; + } + else if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + hMCT->nchan_out_woLFE = st_ivas->nchan_transport - st_ivas->hTransSetup.num_lfe; + } +#endif else { assert( !"IVAS format currently not supported for MCT" ); @@ -427,15 +541,22 @@ ivas_error mct_dec_reconfigure( for ( n = 0; n < CPE_CHANNELS; n++ ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ( hMCT->num_lfe > 0 ) && ( ( n + cpe_id * CPE_CHANNELS ) == LFE_CHANNEL ) ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_LFE; } +#endif } } /* in case we have an uneven number of transport channels, indicate last channel ID as inactive */ - if ( ( hMCT->nchan_out_woLFE + hMCT->num_lfe ) % 2 ) + if ( ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ) % + 2 ) { st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; } @@ -445,16 +566,26 @@ ivas_error mct_dec_reconfigure( * run into a number of problems */ for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { + st_ivas->hCPE[cpe_id]->element_brate = cp_bitrate; for ( n = 0; n < CPE_CHANNELS; n++ ) { st = st_ivas->hCPE[cpe_id]->hCoreCoder[n]; st->total_brate = st_ivas->hCPE[cpe_id]->element_brate; - if ( !( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) ) + if ( !( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) || +#endif + ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) ) { st->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[cpe_id]->element_brate / FRAMES_PER_SEC ); - st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_flag, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_flag +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); if ( st->igf ) { IGFDecSetMode( st->hIGFDec, st_ivas->hCPE[cpe_id]->element_brate, st->bwidth, st->element_mode, -1, -1, st->rf_flag ); @@ -472,7 +603,7 @@ ivas_error mct_dec_reconfigure( { if ( hMCT->hBlockData[n] == NULL ) { - if ( ( hMCT->hBlockData[n] = (MCT_DEC_BLOCK_DATA_HANDLE) count_malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n] = (MCT_DEC_BLOCK_DATA_HANDLE) malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT block data structure\n" ) ); } @@ -482,7 +613,7 @@ ivas_error mct_dec_reconfigure( hMCT->hBlockData[n]->ch2 = 0; /* MDCT stereo initialization */ - if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); } @@ -499,11 +630,11 @@ ivas_error mct_dec_reconfigure( { if ( hMCT->hBlockData[n]->hStereoMdct != NULL ) { - count_free( hMCT->hBlockData[n]->hStereoMdct ); + free( hMCT->hBlockData[n]->hStereoMdct ); hMCT->hBlockData[n]->hStereoMdct = NULL; } - count_free( hMCT->hBlockData[n] ); + free( hMCT->hBlockData[n] ); hMCT->hBlockData[n] = NULL; } } @@ -552,16 +683,16 @@ void ivas_mct_dec_close( { if ( ( *hMCT )->hBlockData[n]->hStereoMdct != NULL ) { - count_free( ( *hMCT )->hBlockData[n]->hStereoMdct ); + free( ( *hMCT )->hBlockData[n]->hStereoMdct ); ( *hMCT )->hBlockData[n]->hStereoMdct = NULL; } - count_free( ( *hMCT )->hBlockData[n] ); + free( ( *hMCT )->hBlockData[n] ); ( *hMCT )->hBlockData[n] = NULL; } } - count_free( *hMCT ); + free( *hMCT ); *hMCT = NULL; return; @@ -609,8 +740,7 @@ ivas_error ivas_mc_dec_config( { if ( st_ivas->hDecoderConfig->last_ivas_total_brate != st_ivas->hDecoderConfig->ivas_total_brate || st_ivas->transport_config != signaled_config || last_mc_mode != st_ivas->mc_mode ) { - /*ivas_mc_dec_reconfigure( st_ivas );*/ - return IVAS_ERROR( IVAS_ERR_RECONFIGURE_NOT_SUPPORTED, "Error: MC format switching not supported yet!!!\n\n" ); + ivas_mc_dec_reconfig( st_ivas ); } } @@ -619,3 +749,500 @@ ivas_error ivas_mc_dec_config( return error; } + + +/*------------------------------------------------------------------------- + * ivas_mc_dec_reconfig() + * + * reconfigure the MC format decoder + *-------------------------------------------------------------------------*/ + +static ivas_error ivas_mc_dec_reconfig( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + int16_t nchan_transport_old, nSCE_old, nCPE_old, sba_dirac_stereo_flag_old, nchan_hp20_old; + int16_t numCldfbAnalyses_old, numCldfbSyntheses_old; + int32_t new_brate_SCE, new_brate_CPE, ivas_total_brate; + RENDERER_TYPE renderer_type_old; + Decoder_State *st; + ivas_error error; + MC_MODE mc_mode, last_mc_mode; + + error = IVAS_ERR_OK; + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + nchan_transport_old = st_ivas->nchan_transport; + + last_mc_mode = ivas_mc_mode_select( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ), st_ivas->hDecoderConfig->last_ivas_total_brate ); /* NB: this assumes that LS config remains the same between frames */ + + /* we have to temporally set the current mc_mode back to the previous one to make sure the following call to + ivas_init_dec_get_num_cldfb_instances() returns the correct counts */ + mc_mode = st_ivas->mc_mode; + st_ivas->mc_mode = last_mc_mode; + ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); + st_ivas->mc_mode = mc_mode; + + nSCE_old = st_ivas->nSCE; + nCPE_old = st_ivas->nCPE; + sba_dirac_stereo_flag_old = st_ivas->sba_dirac_stereo_flag; + + /* special handling needed for the hp20 buffers for McMASA */ + if ( last_mc_mode == MC_MODE_MCMASA ) + { + nchan_hp20_old = getNumChanSynthesis( st_ivas ); + } + else + { + nchan_hp20_old = nchan_transport_old; + } +#ifdef SBA2MONO + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#else + st_ivas->sba_dirac_stereo_flag = 0; /* needs to be after getNumChanSynthesis() */ +#endif + + /* renderer might have changed, reselect */ + renderer_type_old = st_ivas->renderer_type; + ivas_renderer_select( st_ivas ); + + /* side effect of the renderer selection can be a changed internal config */ + ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); + + if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + st_ivas->nchan_transport = ivas_mc_ls_setup_get_num_channels( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ) ); + st_ivas->nSCE = 0; + st_ivas->nCPE = st_ivas->nchan_transport / 2; + + if ( last_mc_mode != MC_MODE_MCT ) + { + /*De-allocate handles for other MC modes*/ + if ( st_ivas->hParamMC != NULL ) + { + ivas_param_mc_dec_close( &st_ivas->hParamMC ); + + /* remove ls conversion if it was allocated by ParamMC */ + ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion ); + } + + /* De-allocate McMasa-related handles */ + ivas_masa_dec_close( &( st_ivas->hMasa ) ); + ivas_qmetadata_close( &st_ivas->hQMetaData ); + + /* init LS conversion if the renderer type asks for it */ + if ( st_ivas->renderer_type == RENDERER_MC && st_ivas->hLsSetUpConversion == NULL ) + { + if ( ( error = ivas_ls_setup_conversion_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + { + if ( last_mc_mode != MC_MODE_PARAMMC ) + { + /* remove old ls conversion for MCT if open, gets reopened correctly within ivas_param_mc_dec_open when needed */ + if ( renderer_type_old == RENDERER_MC && st_ivas->hLsSetUpConversion != NULL ) + { + ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion ); + } + + if ( ( error = ivas_param_mc_dec_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_param_mc_dec_reconfig( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* De-allocate McMasa-related handles */ + ivas_masa_dec_close( &( st_ivas->hMasa ) ); + ivas_qmetadata_close( &st_ivas->hQMetaData ); + + if ( last_mc_mode == MC_MODE_MCT ) + { + if ( st_ivas->hMCT != NULL && st_ivas->nchan_transport <= CPE_CHANNELS ) + { + ivas_mct_dec_close( &st_ivas->hMCT ); + } + + /* LFE handle */ + ivas_lfe_dec_close( &( st_ivas->hLFE ) ); + } + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->element_mode_init ), ivas_total_brate ); + + if ( last_mc_mode != MC_MODE_MCMASA ) + { + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_mcmasa_dec_reconfig( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* ls conversion */ + if ( st_ivas->hLsSetUpConversion != NULL ) + { + ivas_ls_setup_conversion_close( &st_ivas->hLsSetUpConversion ); + } + + if ( st_ivas->hParamMC != NULL ) + { + ivas_param_mc_dec_close( &st_ivas->hParamMC ); + st_ivas->hParamMC = NULL; + } + + if ( last_mc_mode == MC_MODE_MCT ) + { + ivas_mct_dec_close( &st_ivas->hMCT ); + + /* LFE handle */ + ivas_lfe_dec_close( &( st_ivas->hLFE ) ); + } + } + + if ( st_ivas->mc_mode != MC_MODE_MCMASA ) + { + if ( st_ivas->nchan_transport == 1 ) + { + st_ivas->element_mode_init = IVAS_SCE; + } + else + { + st_ivas->element_mode_init = IVAS_CPE_MDCT; + } + } + + /*-----------------------------------------------------------------* + * Reconfigure core coder + *-----------------------------------------------------------------*/ + + /* special case: MCT->ParamMC with more than 2 TC, CPE 1 stays, but has the wrong mct_chan_mode in channel 1 + and might have IGF static memory not allocated and the bit stream index list not set, + set correct mct_chan_mode and init missing static mem (IGF, HQ) and some config (TNS) do it here since it is _very_ MC specific */ + if ( last_mc_mode == MC_MODE_MCT && st_ivas->mc_mode == MC_MODE_PARAMMC && st_ivas->nchan_transport > CPE_CHANNELS ) + { + st = st_ivas->hCPE[1]->hCoreCoder[1]; + + if ( st_ivas->nchan_transport == 3 ) + { + st->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + } + else + { + st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } + + if ( st->hIGFDec == NULL ) + { + if ( ( st->hIGFDec = (IGF_DEC_INSTANCE_HANDLE) malloc( sizeof( IGFDEC_INSTANCE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for IGF\n" ) ); + } + + st->igf = 0; + init_igf_dec( st->hIGFDec ); + } + + if ( st->hHQ_core == NULL ) + { + + if ( ( st->hHQ_core = (HQ_DEC_HANDLE) malloc( sizeof( HQ_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ core\n" ) ); + } + + /* HQ core initialization */ + HQ_core_dec_init( st->hHQ_core ); + } + + /* check if we have a doubly used hTxcCfg, if so, allocate a distint one for the old MCT LFE channel */ + if ( st->hTcxCfg == st_ivas->hCPE[1]->hCoreCoder[0]->hTcxCfg ) + { + if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxCfg\n" ) ); + } + } + + st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( ivas_total_brate, st->igf, st->element_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + } +#ifndef ISSUE_24_CLEANUP_MCT_LFE + else if ( last_mc_mode == MC_MODE_PARAMMC && st_ivas->mc_mode == MC_MODE_MCT && nchan_transport_old > 2 ) + { +#ifdef DEBUGGING + assert( st_ivas->hCPE[1] != NULL ); +#endif + st = st_ivas->hCPE[1]->hCoreCoder[1]; + st->mct_chan_mode = MCT_CHAN_MODE_LFE; + st->hTcxCfg->fIsTNSAllowed = 0; + } +#endif + if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + uint8_t separateChannelEnabled; + int16_t separateChannelIndex; + ivas_mcmasa_set_separate_channel_mode( &separateChannelEnabled, &separateChannelIndex, ivas_total_brate ); + ivas_mcmasa_split_brate( separateChannelEnabled, ivas_total_brate, st_ivas->nSCE, st_ivas->nCPE, &new_brate_SCE, &new_brate_CPE ); + } + else if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + new_brate_SCE = 0; + new_brate_CPE = ( ivas_total_brate / ( st_ivas->nchan_transport - 1 ) ) * CPE_CHANNELS; + } + else + { + new_brate_SCE = 0; /* ivas_total_brate / st_ivas->nchan_transport;*/ + new_brate_CPE = ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS; + } + + if ( ( error = ivas_corecoder_dec_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, sba_dirac_stereo_flag_old, new_brate_SCE, new_brate_CPE ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( last_mc_mode == MC_MODE_MCT && st_ivas->mc_mode == MC_MODE_PARAMMC && st_ivas->nchan_transport > CPE_CHANNELS ) + { + st = st_ivas->hCPE[1]->hCoreCoder[1]; + + /* TCX-LTP */ + if ( st->hTcxLtpDec == NULL ) + { + if ( ( st->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TCX-LTP handle\n" ) ); + } + tcxltp_dec_init( st->hTcxLtpDec, 0, st->last_codec_mode, st->element_mode, st->pit_max, st->sr_core ); + } + } + + + /*-----------------------------------------------------------------* + * re-configure HP20 memories + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_hp20_dec_reconfig( st_ivas, nchan_hp20_old ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*-----------------------------------------------------------------* + * CLDFB instances + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_cldfb_dec_reconfig( st_ivas, nchan_transport_old, numCldfbAnalyses_old, numCldfbSyntheses_old ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*-----------------------------------------------------------------* + * Allocate the LFE handle that is coded seperately after the allocation of the core coders + *-----------------------------------------------------------------*/ + + if ( st_ivas->mc_mode == MC_MODE_MCT && st_ivas->hLFE == NULL ) + { + int32_t binauralization_delay_ns = st_ivas->binaural_latency_ns; + if ( st_ivas->hBinRenderer != NULL ) + { + if ( st_ivas->hBinRenderer->render_lfe ) + { + /* Account for filterbank delay */ + binauralization_delay_ns += IVAS_FB_DEC_DELAY_NS; + } + else + { + binauralization_delay_ns = 0; + } + } + + if ( ( error = ivas_create_lfe_dec( &st_ivas->hLFE, st_ivas->hDecoderConfig->output_Fs, binauralization_delay_ns ) ) != IVAS_ERR_OK ) + { + return error; + } + +#ifndef ISSUE_24_CLEANUP_MCT_LFE + /* reuse core-coder buffers for LFE decoder */ + st_ivas->hLFE->prevsynth_buf = &st_ivas->hCPE[1]->hCoreCoder[1]->old_synth_sw[0]; + st_ivas->hLFE->prior_out_buffer = &st_ivas->hCPE[1]->hCoreCoder[1]->previoussynth[0]; +#endif + + set_zero( st_ivas->hLFE->prevsynth_buf, LFE_PLC_BUFLEN ); + set_zero( st_ivas->hLFE->prior_out_buffer, L_FRAME48k ); + } + + /*-----------------------------------------------------------------* + * Reconfigure renderers + *-----------------------------------------------------------------*/ + + if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + if ( ( st_ivas->renderer_type != RENDERER_DISABLE ) && ( st_ivas->renderer_type != RENDERER_MCMASA_MONO_STEREO ) ) + { + if ( st_ivas->hDirAC != NULL ) + { + /* reconfigure existing DirAC dec */ + if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + /* init a new DirAC dec */ + if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else if ( st_ivas->renderer_type == RENDERER_DISABLE && st_ivas->hDirAC != NULL ) + { + ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); + } + } + + if ( renderer_type_old != st_ivas->renderer_type ) + { + AUDIO_CONFIG output_config; + + output_config = st_ivas->hDecoderConfig->output_config; + + /* binaural renderers*/ + if ( output_config == AUDIO_CONFIG_BINAURAL || output_config == AUDIO_CONFIG_BINAURAL_ROOM ) + { + /* remove unneeded binaural renderers */ + if ( st_ivas->hBinRenderer != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV && st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV_ROOM ) ) + { + ivas_binRenderer_close( &st_ivas->hBinRenderer ); + } + + if ( ( st_ivas->hCrendWrapper != NULL ) && ( st_ivas->hCrendWrapper->hCrend != NULL ) && ( st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV && st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV_ROOM && ( st_ivas->renderer_type != RENDERER_BINAURAL_OBJECTS_TD || st_ivas->hRenderConfig->roomAcoustics.late_reverb_on == 0 ) ) ) + { + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); + } + + if ( st_ivas->hBinRendererTd != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_OBJECTS_TD ) ) + { + ivas_td_binaural_close( &st_ivas->hBinRendererTd ); + } + + if ( st_ivas->hDiracDecBin != NULL ) + { + if ( st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + } + else + { + /* useTdDecorr may change => close and re-open */ + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + /* init necessary new renderers */ + if ( st_ivas->hBinRenderer == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) + { + if ( ( error = ivas_binRenderer_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hDiracDecBin == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) + { + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hBinRendererTd == NULL && st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + { + if ( ( error = ivas_td_binaural_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) + { + if ( ( error = ivas_rend_initCrendWrapper( &st_ivas->hCrendWrapper ) ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Wrapper\n" ); + } + st_ivas->hCrendWrapper->hCrend = NULL; + st_ivas->hCrendWrapper->hHrtfCrend = NULL; + if ( ( st_ivas->hCrendWrapper->hCrend = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend\n" ); + } + } + } + else if ( st_ivas->hCrendWrapper == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) + { + if ( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), + st_ivas->intern_config, + st_ivas->hDecoderConfig->output_config, + st_ivas->hRenderConfig, + st_ivas->hSetOfHRTF, + st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + st_ivas->binaural_latency_ns = st_ivas->hCrendWrapper->binaural_latency_ns; + } + } + /* mono/stereo */ + else if ( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) + { + /* nothing should happen here... */ + } + /* LS */ + else if ( output_config == AUDIO_CONFIG_5_1 || output_config == AUDIO_CONFIG_5_1_2 || output_config == AUDIO_CONFIG_5_1_4 || output_config == AUDIO_CONFIG_7_1 || output_config == AUDIO_CONFIG_7_1_4 || output_config == AUDIO_CONFIG_LS_CUSTOM ) + { +#ifdef DEBUGGING + assert( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_MC_PARAMMC || st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_DISABLE ); +#endif + } +#ifdef DEBUGGING + else if ( output_config == AUDIO_CONFIG_FOA || output_config == AUDIO_CONFIG_HOA2 || output_config == AUDIO_CONFIG_HOA3 ) + { + /* FOA/HOA output */ + /* Nothing to do, renderer is always RENDERER_SBA_LINEAR_ENC */ + assert( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC && renderer_type_old == RENDERER_SBA_LINEAR_ENC ); + } +#endif + } + + return error; +} diff --git a/lib_dec/ivas_mct_dec_mct.c b/lib_dec/ivas_mct_dec_mct.c index c8d91b9b076e3087b6bdba2b83a1d943166ab126..68a846b876dea6667e43abe6365e0dfc60e4498b 100644 --- a/lib_dec/ivas_mct_dec_mct.c +++ b/lib_dec/ivas_mct_dec_mct.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,7 @@ #include "ivas_cnst.h" #include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include #include "stat_enc.h" @@ -49,8 +49,11 @@ static void indexToChannelPair( MCT_DEC_BLOCK_DATA_HANDLE hBlock, const int16_t nChannels, - const int16_t pairIdx, + const int16_t pairIdx +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , Decoder_State **sts /* i/o: decoder state structure */ +#endif ) { int16_t ch1, ch2; @@ -60,10 +63,12 @@ static void indexToChannelPair( { for ( ch1 = 0; ch1 < ch2; ch1++ ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[ch1]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch2]->mct_chan_mode == MCT_CHAN_MODE_LFE ) { continue; } +#endif if ( tmpIdx == pairIdx ) { @@ -105,7 +110,11 @@ void ivas_mct_dec_mct( /*first get core and overlap info for all channels*/ for ( ch = 0; ch < nchan; ch++ ) { - if ( ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) && hMCT->currBlockDataCnt && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) && +#endif + hMCT->currBlockDataCnt && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) { hMCT->mc_global_ild[ch] = get_next_indice( sts[0], SMDCT_GLOBAL_ILD_BITS ); } @@ -119,7 +128,11 @@ void ivas_mct_dec_mct( { for ( ch = 0; ch < nchan; ch++ ) { - if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE && +#endif + sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) { hMCT->lowE_ch[ch] = get_next_indice( sts[0], 1 ); } @@ -128,7 +141,11 @@ void ivas_mct_dec_mct( for ( ch = 0; ch < nchan; ch++ ) { - if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE && +#endif + sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) { nchan_active++; } @@ -141,13 +158,18 @@ void ivas_mct_dec_mct( /*get channel pair index from BS*/ channelPairIndex = get_next_indice( sts[0], hMCT->bitsChannelPairIndex ); - indexToChannelPair( hBlock, nchan, channelPairIndex, sts ); + indexToChannelPair( hBlock, nchan, channelPairIndex +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + sts +#endif + ); /*point to decoder states of actual channels to read block pair bits*/ p_st[0] = sts[hBlock->ch1]; p_st[1] = sts[hBlock->ch2]; - parse_stereo_from_bitstream( hBlock->hStereoMdct, p_st, 1, sts[0], hBlock->mask ); + parse_stereo_from_bitstream( hBlock->hStereoMdct, p_st, 1, 0, sts[0], hBlock->mask ); } return; @@ -170,7 +192,12 @@ static void applyGlobalILD( int16_t nSubframes, L_subframeTCX; float qratio; - for ( ch = 0; ch < ( hMCT->nchan_out_woLFE + hMCT->num_lfe ); ch++ ) + for ( ch = 0; ch < ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); + ch++ ) { nSubframes = ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV; L_subframeTCX = sts[ch]->hTcxDec->L_frameTCX / nSubframes; @@ -220,8 +247,7 @@ void apply_MCT_dec( { hBlock = hMCT->hBlockData[pair]; - stereo_decoder_tcx( hBlock->hStereoMdct, hBlock->mask, &x[hBlock->ch2][0], &x[hBlock->ch1][0], &x[hBlock->ch2][0], hBlock->hStereoMdct->mdct_stereo_mode, - sts[hBlock->ch1]->core, sts[hBlock->ch2]->core, sts[0]->igf, sts[0]->hTcxDec->L_frameTCX, 1, TCX_20_CORE, TCX_20_CORE, 0 ); + stereo_decoder_tcx( hBlock->hStereoMdct, hBlock->mask, &x[hBlock->ch2][0], &x[hBlock->ch1][0], &x[hBlock->ch2][0], hBlock->hStereoMdct->mdct_stereo_mode, sts[hBlock->ch1]->core, sts[hBlock->ch2]->core, sts[0]->igf, sts[0]->hTcxDec->L_frameTCX, sts[1]->hTcxDec->L_frameTCX, 1, TCX_20_CORE, TCX_20_CORE, 0 ); } applyGlobalILD( sts, hMCT, x ); @@ -253,7 +279,11 @@ void mctStereoIGF_dec( float *p_x[CPE_CHANNELS][NB_DIV]; int16_t singleChEle[MCT_MAX_CHANNELS]; - set_s( singleChEle, 1, ( hMCT->nchan_out_woLFE + hMCT->num_lfe ) ); + set_s( singleChEle, 1, ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ) ); for ( b = 0; b < hMCT->currBlockDataCnt; b++ ) { @@ -283,7 +313,7 @@ void mctStereoIGF_dec( /* stereo IGF decoding */ assert( ( sts[0]->core == sts[1]->core ) || ( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) ); - decoder_tcx_IGF_stereo( sts, hMCT->hBlockData[b]->hStereoMdct, hMCT->hBlockData[b]->mask, p_x, L_frame[0], left_rect[0], k, bfi ); + decoder_tcx_IGF_stereo( sts, hMCT->hBlockData[b]->hStereoMdct, hMCT->hBlockData[b]->mask, p_x, L_frame[0], left_rect[0], k, bfi, 1 /* MCT_flag */ ); } else { @@ -306,9 +336,18 @@ void mctStereoIGF_dec( } - if ( sum_s( singleChEle, ( hMCT->nchan_out_woLFE + hMCT->num_lfe ) ) != 0 ) + if ( sum_s( singleChEle, ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ) ) != 0 ) { - for ( ch = 0; ch < ( hMCT->nchan_out_woLFE + hMCT->num_lfe ); ch++ ) + for ( ch = 0; ch < ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); + ch++ ) { if ( singleChEle[ch] ) { @@ -317,7 +356,11 @@ void mctStereoIGF_dec( { continue; } - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE || st->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || st->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { continue; } diff --git a/lib_dec/ivas_mdct_core_dec.c b/lib_dec/ivas_mdct_core_dec.c index 77c70b1f9f48bb3db63ad39f6272202cc0196b67..83aac5cbc1a915310f4603de74638960595879be 100644 --- a/lib_dec/ivas_mdct_core_dec.c +++ b/lib_dec/ivas_mdct_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "cnst.h" #include "basop_proto_func.h" #include "stat_com.h" @@ -49,9 +49,9 @@ /*-----------------------------------------------------------------* - * Function mdct_read_IGF_bits() * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * read IGF side bits * + * Function mdct_read_IGF_bits() + * + * read IGF side bits *-----------------------------------------------------------------*/ void mdct_read_IGF_bits( @@ -90,9 +90,9 @@ void mdct_read_IGF_bits( /*-----------------------------------------------------------------* - * Function dec_prm_tcx_sidebits() * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * decode TCX side parameters * + * Function dec_prm_tcx_sidebits() + * + * decode TCX side parameters *-----------------------------------------------------------------*/ static void dec_prm_tcx_sidebits( @@ -102,10 +102,8 @@ static void dec_prm_tcx_sidebits( int16_t p_param[NB_DIV], /* o : pointer to parameters for next round of bs reading*/ int16_t nTnsBitsTCX10[NB_DIV], /* o : number of TNS bits per TCX10 subframe */ Decoder_State *st0, /* i/o: core decoder state handle - for bitstream */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t MCT_flag, -#endif - const int16_t ch /* i : channel */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t ch /* i : channel */ ) { CONTEXT_HM_CONFIG hm_cfg; @@ -134,11 +132,7 @@ static void dec_prm_tcx_sidebits( *--------------------------------------------------------------------------------*/ /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT getTCXMode( st, st0, MCT_flag ); -#else - getTCXMode( st, st0 ); -#endif st->flagGuidedAcelp = 0; @@ -151,65 +145,43 @@ static void dec_prm_tcx_sidebits( if ( ( st->last_core == ACELP_CORE && st->last_total_brate == FRAME_NO_DATA ) || st->prev_bfi ) { /* needed for cases where first TCX frame after a certain transition (e.g. inactive SID/zero frame -> active or stereo switching) is lost */ -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - if ( st->core == TCX_20_CORE ) - { - st->last_core_from_bs = get_next_indice( st0, 1 ); - } - else - { - st->last_core_from_bs = st->last_core; - } -#else st->last_core_from_bs = get_next_indice( st0, 1 ); -#endif /* ACELP -> TCX_10 transitions are forbidden */ - if ( st->core == TCX_10_CORE && st->last_core == ACELP_CORE && st->last_total_brate == FRAME_NO_DATA ) + if ( st->core == TCX_10_CORE && st->last_core == ACELP_CORE ) { st->last_core = TCX_20_CORE; -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - st->last_core_from_bs = st->last_core; -#endif } } else { -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - if ( st->core != TCX_10_CORE ) - { - st->last_core = get_next_indice( st0, 1 ); - st->last_core_from_bs = st->last_core; - } -#else st->last_core = get_next_indice( st0, 1 ); st->last_core_from_bs = st->last_core; -#endif } -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 getTCXWindowing( st->core, st->last_core, st->element_mode, st->hTcxCfg, st0 ); -#else - getTCXWindowing( st->core, st->last_core, st->hTcxCfg, st0 ); -#endif st->hTcxDec->kernel_type[0] = st->hTcxDec->kernel_type[1] = MDCT_IV; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->element_mode == IVAS_CPE_MDCT && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif st->hTcxDec->kernel_type[0] = get_next_indice( st0, st->last_core_from_bs != ACELP_CORE ? 2 : 1 ); if ( st->core == TCX_10_CORE ) { st->hTcxDec->kernel_type[1] = 2 * ( st->hTcxDec->kernel_type[0] & 1 ) + get_next_indice( st0, 1 ); } +#ifndef ISSUE_24_CLEANUP_MCT_LFE } + if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { st->hTcxCfg->tcx_curr_overlap_mode = FULL_OVERLAP; st->hTcxCfg->tcx_last_overlap_mode = FULL_OVERLAP; st->hTcxCfg->last_aldo = 0; } - +#endif if ( st->core == TCX_20_CORE ) { st->transform_type[0] = st->transform_type[1] = TCX_20; @@ -244,18 +216,18 @@ static void dec_prm_tcx_sidebits( /*-----------------------------------------------------------------* - * Function dec_prm_tcx_spec() * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * decode TCX core parameters * + * Function dec_prm_tcx_spec() + * + * decode TCX core parameters *-----------------------------------------------------------------*/ static void dec_prm_tcx_spec( - Decoder_State *st, /* i/o: decoder memory state */ - int16_t param[], /* o : decoded parameters */ - int16_t *total_nbbits, /* i/o: number of bits / decoded bits */ - int16_t *bitsRead, /* o : number of read bits */ + Decoder_State *st, /* i/o: decoder memory state */ + int16_t param[], /* o : decoded parameters */ + int16_t *total_nbbits, /* i/o: number of bits / decoded bits */ + int16_t *bitsRead, /* o : number of read bits */ int16_t p_param[NB_DIV], /* o : pointer to parameters for next round of bs reading*/ - int16_t nTnsBitsTCX10[NB_DIV] /* i : number of TNS bits per TCX10 subframe*/ + int16_t nTnsBitsTCX10[NB_DIV] /* i : number of TNS bits per TCX10 subframe */ ) { int16_t nSubframes; @@ -320,20 +292,22 @@ static void dec_prm_tcx_spec( /*-----------------------------------------------------------------* - * Function ivas_mdct_dec_side_bits_frame_channel() * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * Initialize TCX and read TCX side parameters * + * Function ivas_mdct_dec_side_bits_frame_channel() + * + * Initialize TCX and read TCX side parameters *-----------------------------------------------------------------*/ void ivas_mdct_dec_side_bits_frame_channel( - CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ - int16_t param_lpc[MCT_MAX_CHANNELS][NPRM_LPC_NEW], /* o : lpc_parameters */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to param buffer */ - Decoder_State *st0, /* i : pointer to bitstream handle */ - int16_t *LFE_off, /* o : flag if LFE has content */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ + int16_t param_lpc[MCT_MAX_CHANNELS][NPRM_LPC_NEW], /* o : lpc_parameters */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to param buffer */ + Decoder_State *st0, /* i : pointer to bitstream handle */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + int16_t *LFE_off, /* o : flag if LFE has content */ +#endif int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* o : number of bits for TNS */ int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i/o: parameters buffer */ - const int16_t MCT_flag, /* i : MCT tool active(1) or deactive(0) */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ const int16_t odd_channel_cpe /* i : flag cpe with odd nb of tc channels */ ) { @@ -372,11 +346,14 @@ void ivas_mdct_dec_side_bits_frame_channel( continue; } st = sts[ch]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { *LFE_off = get_next_indice( st0, 1 ); } - else if ( MCT_flag ) + else +#endif + if ( MCT_flag ) { tmp = get_next_indice( st0, 1 ); if ( tmp ) @@ -394,7 +371,11 @@ void ivas_mdct_dec_side_bits_frame_channel( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && *LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { sts[ch]->coder_type = INACTIVE; sts[ch]->side_bits_frame_channel = 0; @@ -407,11 +388,7 @@ void ivas_mdct_dec_side_bits_frame_channel( tmp = 3; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT dec_prm_tcx_sidebits( param[ch], st, ( ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) ? sts[0]->hTcxDec->tnsActive : NULL ), p_param[ch], nTnsBitsTCX10[ch], st0, MCT_flag, tmp ); -#else - dec_prm_tcx_sidebits( param[ch], st, ( ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) ? sts[0]->hTcxDec->tnsActive : NULL ), p_param[ch], nTnsBitsTCX10[ch], st0, tmp ); -#endif assert( st->BER_detect != 1 ); } @@ -426,7 +403,11 @@ void ivas_mdct_dec_side_bits_frame_channel( { st = sts[ch]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && *LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { skipped_first_channel = 1; continue; @@ -440,7 +421,11 @@ void ivas_mdct_dec_side_bits_frame_channel( param_lpc[0][0] = get_next_indice( st0, 1 ) << 1; /* read low br mode flag (if it is possible to be non-zero) */ - if ( sts[0]->element_brate == IVAS_48k && !( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) + if ( sts[0]->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[1]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) ) { sns_low_br_mode = get_next_indice( st0, 1 ); } @@ -463,25 +448,27 @@ void ivas_mdct_dec_side_bits_frame_channel( /*-----------------------------------------------------------------* - * ivas_mdct_core_invQ() * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * Inverse processing steps up to inverse quantization * + * ivas_mdct_core_invQ() + * + * Inverse processing steps up to inverse quantization *-----------------------------------------------------------------*/ void ivas_mdct_core_invQ( - CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ - const int16_t LFE_off, /* i : flag if LFE content */ - int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* i : number of TNS bits */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to param buffer */ - int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW], /* i : lpc parameters */ - int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i : param buffer */ - int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flag TNS enabled */ - STnsData tnsData[CPE_CHANNELS][NB_DIV], /* i : TNS parameter */ - float *x_0[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ - float *x[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ - float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* i : LP coefficients */ - int16_t ms_mask[NB_DIV][MAX_SFB], /* i : M/S mask */ - const int16_t isMCT /* i : MCT flag */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE content */ +#endif + int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* i : number of TNS bits */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to param buffer */ + int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW], /* i : lpc parameters */ + int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i : param buffer */ + int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flag TNS enabled */ + STnsData tnsData[CPE_CHANNELS][NB_DIV], /* i : TNS parameter */ + float *x_0[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ + float *x[CPE_CHANNELS][NB_DIV], /* i/o: signal buffer */ + float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* i : LP coefficients */ + int16_t ms_mask[NB_DIV][MAX_SFB], /* i : M/S mask */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { int16_t ch, bfi, k; @@ -507,18 +494,14 @@ void ivas_mdct_core_invQ( const int16_t *prm_sqQ; int16_t L_frameTCX_global[CPE_CHANNELS]; float tmp_ms_sig[CPE_CHANNELS][N_MAX]; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT float concealment_noise[CPE_CHANNELS][L_FRAME48k]; TONALMDCTCONC_NOISE_GEN_MODE noise_gen_mode_bfi; -#endif - wmops_sub_start( "mdct_core_invQ" ); + push_wmops( "mdct_core_invQ" ); sts = hCPE->hCoreCoder; bfi = sts[0]->bfi; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT noise_gen_mode_bfi = -1; -#endif set_f( xn_buf, 0, L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ); set_s( total_nbbits, 0, CPE_CHANNELS ); @@ -531,16 +514,15 @@ void ivas_mdct_core_invQ( } /* temporarily restore LR representation of previous frame for PLC mode decision (done on the individual channels) */ - if ( bfi && !isMCT && ( hCPE->hStereoMdct->mdct_stereo_mode[0] > SMDCT_DUAL_MONO || hCPE->hStereoMdct->mdct_stereo_mode[1] > SMDCT_DUAL_MONO ) ) + if ( bfi && !MCT_flag && ( hCPE->hStereoMdct->mdct_stereo_mode[0] > SMDCT_DUAL_MONO || hCPE->hStereoMdct->mdct_stereo_mode[1] > SMDCT_DUAL_MONO ) ) { L_frameTCX[0] = sts[0]->L_frameTCX_past; + L_frameTCX[1] = sts[1]->L_frameTCX_past; mvr2r( sts[0]->hTonalMDCTConc->lastBlockData.spectralData, tmp_ms_sig[0], L_frameTCX[0] ); mvr2r( sts[1]->hTonalMDCTConc->lastBlockData.spectralData, tmp_ms_sig[1], L_frameTCX[0] ); - stereo_decoder_tcx( hCPE->hStereoMdct, ms_mask, x_0[1], &sts[0]->hTonalMDCTConc->lastBlockData.spectralData, &sts[1]->hTonalMDCTConc->lastBlockData.spectralData, &hCPE->hStereoMdct->mdct_stereo_mode[0], - sts[0]->core, sts[1]->core, sts[0]->igf, L_frameTCX[0], 0, sts[0]->last_core, sts[1]->last_core, 1 ); + stereo_decoder_tcx( hCPE->hStereoMdct, ms_mask, x_0[1], &sts[0]->hTonalMDCTConc->lastBlockData.spectralData, &sts[1]->hTonalMDCTConc->lastBlockData.spectralData, &hCPE->hStereoMdct->mdct_stereo_mode[0], sts[0]->core, sts[1]->core, sts[0]->igf, L_frameTCX[0], L_frameTCX[1], 0, sts[0]->last_core, sts[1]->last_core, 1 ); } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( bfi ) { if ( sts[0]->core == sts[1]->core ) @@ -556,14 +538,17 @@ void ivas_mdct_core_invQ( noise_gen_mode_bfi = TCX20_IN_0_TCX10_IN_1; } } -#endif /* parameter decoding */ for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) /* indicates LFE with no content, or odd number of channels */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { st->total_brate = st->bits_frame_channel; continue; @@ -617,12 +602,13 @@ void ivas_mdct_core_invQ( /* PLC: [Common: mode decision] * PLC: Decide which Concealment to use. Update pitch lags if needed */ st->core = GetPLCModeDecision( st ); - +#ifndef ISSUE_24_CLEANUP_MCT_LFE /*disable ACELP_PLC for LFE channel */ if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { st->core = st->last_core; } +#endif } if ( ( !st->bfi || st->hTcxCfg->psychParamsCurrent == NULL ) && st->core > ACELP_CORE ) @@ -649,7 +635,7 @@ void ivas_mdct_core_invQ( } } - if ( bfi && !isMCT && ( hCPE->hStereoMdct->mdct_stereo_mode[0] > SMDCT_DUAL_MONO || hCPE->hStereoMdct->mdct_stereo_mode[1] > SMDCT_DUAL_MONO ) ) + if ( bfi && !MCT_flag && ( hCPE->hStereoMdct->mdct_stereo_mode[0] > SMDCT_DUAL_MONO || hCPE->hStereoMdct->mdct_stereo_mode[1] > SMDCT_DUAL_MONO ) ) { /* avoid using TD-PLC in only one channel when stereo mode isn't dual mono */ if ( sts[0]->core != sts[1]->core && ( sts[0]->core == ACELP_CORE || sts[1]->core == ACELP_CORE ) ) @@ -712,7 +698,11 @@ void ivas_mdct_core_invQ( { st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) /* indicates LFE with no content, or odd number of channels */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { set_f( x[ch][0], 0.f, st->hTcxCfg->tcx_coded_lines ); /* usually set in decoder_tcx_invQ(), needed for concealment */ @@ -754,54 +744,49 @@ void ivas_mdct_core_invQ( } nf_seed = 0; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - decoder_tcx_invQ( st, prm[ch], Aq[ch], Aind[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], x[ch][k], NULL, xn_buf, &fUseTns[ch][k], &tnsData[ch][k], &gain_tcx, &prm_sqQ, &nf_seed, bfi, isMCT, k ); -#else decoder_tcx_invQ( st, prm[ch], Aq[ch], Aind[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], x[ch][k], NULL, xn_buf, &fUseTns[ch][k], &tnsData[ch][k], &gain_tcx, &prm_sqQ, &nf_seed, bfi, k ); -#endif mvr2r( x[ch][k], x_0[ch][k], L_frameTCX[ch] ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - if ( bfi && !isMCT ) + if ( bfi && !MCT_flag ) { TonalMdctConceal_create_concealment_noise( concealment_noise[ch], hCPE, L_frameTCX[ch], L_frame[ch], ch, k, st->core, st->hTcxDec->cummulative_damping_tcx, noise_gen_mode_bfi ); } - decoder_tcx_noisefilling( st, concealment_noise[ch], Aq[ch], L_frameTCX_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], x[ch][k], NULL, &tmp_concealment_method, gain_tcx, prm_sqQ, nf_seed, bfi, isMCT, k ); -#else - decoder_tcx_noisefilling( st, Aq[ch], L_frameTCX_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], x[ch][k], NULL, &tmp_concealment_method, gain_tcx, prm_sqQ, nf_seed, bfi, k ); -#endif - decoder_tcx_noiseshaping_igf( st, L_spec[ch], L_frame[ch], L_frameTCX[ch], left_rect[ch], x[ch][k], - NULL, &tmp_concealment_method, bfi ); + decoder_tcx_noisefilling( st, concealment_noise[ch], Aq[ch], L_frameTCX_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], x[ch][k], NULL, &tmp_concealment_method, gain_tcx, prm_sqQ, nf_seed, bfi, MCT_flag, k ); + + decoder_tcx_noiseshaping_igf( st, L_spec[ch], L_frame[ch], L_frameTCX[ch], left_rect[ch], x[ch][k], NULL, &tmp_concealment_method, bfi ); } } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) /*indicates LFE with no content*/ { set_f( &x[ch][0][MCT_LFE_MAX_LINE], 0.f, st->hTcxCfg->tcx_coded_lines - MCT_LFE_MAX_LINE ); } +#endif } - wmops_sub_end(); + pop_wmops(); return; } /*-----------------------------------------------------------------* - * ivas_mdct_core_reconstruct() * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * reconstruct time signal * + * ivas_mdct_core_reconstruct() + * + * reconstruct time signal *-----------------------------------------------------------------*/ void ivas_mdct_core_reconstruct( - CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ - float *x[][NB_DIV], /* i/o: synthesis @internal_FS */ - float signal_outFB[CPE_CHANNELS][L_FRAME_PLUS], /* o : synthesis @output_FS */ - const int16_t LFE_off, /* i : flag if LFE content */ - int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flage TNS enabled */ - const int16_t isMCT /* i : MCT flag */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ + float *x[][NB_DIV], /* i/o: synthesis @internal_FS */ + float signal_outFB[CPE_CHANNELS][L_FRAME_PLUS], /* o : synthesis @output_FS */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE content */ +#endif + int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : flage TNS enabled */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ ) { int16_t ch, k, bfi; @@ -823,7 +808,9 @@ void ivas_mdct_core_reconstruct( int16_t pitch[CPE_CHANNELS][NB_SUBFR16k]; float pit_gain[CPE_CHANNELS][NB_SUBFR16k]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE int16_t isLFE; +#endif int16_t skip_decoding; set_f( xn_buf, 0, L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ); @@ -838,16 +825,21 @@ void ivas_mdct_core_reconstruct( st = sts[ch]; skip_decoding = 0; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) /* indicates LFE with no content, or odd number of channels */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { skip_decoding = 1; } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE isLFE = 0; if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { isLFE = 1; } +#endif nSubframes[ch] = ( st->core == TCX_20_CORE ) ? 1 : NB_DIV; synth = synth_buf + st->hTcxDec->old_synth_len; @@ -872,8 +864,12 @@ void ivas_mdct_core_reconstruct( { decoder_tcx_imdct( st, L_frame_global[ch], L_frame_globalTCX[ch], L_spec[ch], tcx_offset[ch], tcx_offsetFB[ch], L_frame[ch], L_frameTCX[ch], left_rect[ch], &x[ch][k][0], xn_buf, - ( st->element_mode == IVAS_CPE_MDCT && hCPE->nchan_out == 1 && st->hTcxDec->kernel_type[k] == MDST_IV ) ? MDCT_IV : st->hTcxDec->kernel_type[k], - fUseTns[ch][k], &synth[k * L_frame[ch]], &synthFB[k * L_frameTCX[ch]], bfi, k, isLFE, 0 ); + ( ( hCPE->nchan_out == 1 && st->hTcxDec->kernel_type[k] == MDST_IV ) || st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ? MDCT_IV : st->hTcxDec->kernel_type[k], + fUseTns[ch][k], &synth[k * L_frame[ch]], &synthFB[k * L_frameTCX[ch]], bfi, k, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + isLFE, +#endif + 0 ); } else { @@ -887,31 +883,19 @@ void ivas_mdct_core_reconstruct( TonalMDCTConceal_SaveTimeSignal( st->hTonalMDCTConc, synthFB, L_frameTCX[ch] ); } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - decoder_tcx_post( st, synth, synthFB, NULL, bfi, isMCT ); -#else - decoder_tcx_post( st, synth, synthFB, NULL, bfi ); -#endif + decoder_tcx_post( st, synth, synthFB, NULL, bfi, MCT_flag ); } else /*ACELP core for ACELP-PLC */ { assert( st->bfi == 1 ); /* PLC: [TCX: TD PLC] */ - if ( isMCT ) + if ( MCT_flag ) { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT con_tcx( st, &synthFB[0], -1.f, NULL, 0, NULL ); -#else - con_tcx( st, &synthFB[0], -1.f, NULL, 0 ); -#endif } else { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT con_tcx( st, &synthFB[0], hCPE->hStereoMdct->lastCoh, &sts[0]->seed_acelp, ( sts[1]->core != ACELP_CORE ) ? 1 : 0, &st->hFdCngDec->hFdCngCom->A_cng[0] ); -#else - con_tcx( st, &synthFB[0], hCPE->hStereoMdct->lastCoh, &sts[0]->seed_acelp, ( sts[1]->core != ACELP_CORE ) ? 1 : 0 ); -#endif } lerp( synthFB, synth, st->L_frame, st->hTcxDec->L_frameTCX ); @@ -1002,10 +986,9 @@ void ivas_mdct_core_reconstruct( } /* calculate coherence of signal needed when next frame is lost */ - if ( !bfi && !isMCT && hCPE->element_mode == IVAS_CPE_MDCT ) + if ( !bfi && !MCT_flag && hCPE->element_mode == IVAS_CPE_MDCT ) { int16_t i; - float nrgL, nrgR, xcorr; nrgL = nrgR = xcorr = EPSILON; @@ -1017,7 +1000,7 @@ void ivas_mdct_core_reconstruct( xcorr += signal_outFB[0][i] * signal_outFB[1][i]; } - hCPE->hStereoMdct->lastCoh = fabsf( xcorr ) / sqrtf( nrgL * nrgR ); + hCPE->hStereoMdct->lastCoh = fabsf( xcorr ) * inv_sqrt( nrgL * nrgR ); hCPE->hStereoMdct->lastCoh = min( hCPE->hStereoMdct->lastCoh, 1.f ); } @@ -1026,19 +1009,21 @@ void ivas_mdct_core_reconstruct( /*-----------------------------------------------------------------* - * ivas_mdct_core_tns_ns() * - * ~~~~~~~~~~~~~~~~~~~~~~~ * - * reconstruct time signal * + * ivas_mdct_core_tns_ns() + * + * reconstruct time signal *-----------------------------------------------------------------*/ void ivas_mdct_core_tns_ns( - CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ - const int16_t LFE_off, /* i : flag if LFE has content */ - int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : two entries for each channel in TCX10 */ - STnsData tnsData[CPE_CHANNELS][NB_DIV], /* o : TNS parameter */ - float *x[CPE_CHANNELS][NB_DIV], /* o : synthesis @internal_FS */ - float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* o : LP coefficients */ - const int16_t isMCT /* i : MCT flag */ + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE has content */ +#endif + int16_t fUseTns[CPE_CHANNELS][NB_DIV], /* i : two entries for each channel in TCX10 */ + STnsData tnsData[CPE_CHANNELS][NB_DIV], /* o : TNS parameter */ + float *x[CPE_CHANNELS][NB_DIV], /* o : synthesis @internal_FS */ + float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* o : LP coefficients */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { int16_t ch, k, bfi; @@ -1070,7 +1055,11 @@ void ivas_mdct_core_tns_ns( L_frameTCX_glob[ch] = st->hTcxDec->L_frameTCX / nSubframes[ch]; L_spec[ch] = st->hTcxCfg->tcx_coded_lines / nSubframes[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) || ( st->bfi && st->core == ACELP_CORE ) ) /* indicates LFE with no content, or odd number of channels */ + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || +#endif + ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) || ( st->bfi && st->core == ACELP_CORE ) ) /* indicates LFE with no content, or odd number of channels */ { if ( st->hTonalMDCTConc != NULL ) { @@ -1090,54 +1079,26 @@ void ivas_mdct_core_tns_ns( { sns_interpolate_scalefactors( &sns_int_scf[0], &Aq[ch][k * M], DEC ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - if ( isMCT && st->hTonalMDCTConc != NULL && ( ( k + 1 ) == nSubframes[ch] ) ) -#else - if ( isMCT && st->hTonalMDCTConc != NULL ) -#endif + if ( MCT_flag && st->hTonalMDCTConc != NULL && ( ( k + 1 ) == nSubframes[ch] ) ) { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - int16_t infoIGFStartLine; - - if ( st->igf == 0 ) - { - if ( st->narrowBand == 0 ) - { - /* minimum needed for output with sampling rates lower then the - nominal sampling rate */ - infoIGFStartLine = min( L_frameTCX[ch], L_frame[ch] ); - } - else - { - infoIGFStartLine = L_frameTCX[ch]; - } - } - else - { - infoIGFStartLine = min( st->hIGFDec->infoIGFStartLine, L_frameTCX[ch] ); - } - - TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0], infoIGFStartLine ); -#else - TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0] ); -#endif + TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0], get_igf_startline( st, L_frame[ch], L_frameTCX[ch] ) ); } } else { if ( st->hTonalMDCTConc != NULL ) { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - if ( st->hTcxDec->cummulative_damping_tcx != 1.f ) + if ( !MCT_flag && st->hTcxDec->cummulative_damping_tcx != 1.f ) { - float *scf_last; - float *scf_bg; - float fade_in; - float fade_out; + float *scf_last, *scf_bg; + float fade_in, fade_out; scf_last = &st->hTonalMDCTConc->lastBlockData.scaleFactors[0]; scf_bg = &st->hTonalMDCTConc->scaleFactorsBackground[0]; - fade_out = st->hTcxDec->cummulative_damping_tcx; + + st->hTonalMDCTConc->scf_fadeout *= 0.95f; + + fade_out = st->hTonalMDCTConc->scf_fadeout; fade_in = 1 - fade_out; for ( int16_t i = 0; i < st->hTonalMDCTConc->nScaleFactors; i++ ) @@ -1147,22 +1108,18 @@ void ivas_mdct_core_tns_ns( } else { + st->hTonalMDCTConc->scf_fadeout = 1.0f; mvr2r( st->hTonalMDCTConc->lastBlockData.scaleFactors, &sns_int_scf[0], st->hTonalMDCTConc->nScaleFactors ); } -#else - mvr2r( st->hTonalMDCTConc->lastBlockData.scaleFactors, &sns_int_scf[0], st->hTonalMDCTConc->nScaleFactors ); -#endif } } - decoder_tcx_tns( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x[ch][k][0], - fUseTns[ch][k], &tnsData[ch][k], bfi, k, 1 ); + decoder_tcx_tns( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x[ch][k][0], fUseTns[ch][k], &tnsData[ch][k], bfi, k, 1 ); sns_shape_spectrum( x[ch][k], st->hTcxCfg->psychParamsCurrent, &sns_int_scf[0], st->hTcxCfg->psychParamsCurrent->nBins ); v_multc( x[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, sns_int_scf[FDNS_NPTS - 1], x[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, L_spec[ch] - st->hTcxCfg->psychParamsCurrent->nBins ); - decoder_tcx_tns( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x[ch][k][0], - fUseTns[ch][k], &tnsData[ch][k], bfi, k, 0 ); + decoder_tcx_tns( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x[ch][k][0], fUseTns[ch][k], &tnsData[ch][k], bfi, k, 0 ); } if ( bfi && st->tonal_mdct_plc_active ) @@ -1170,7 +1127,7 @@ void ivas_mdct_core_tns_ns( TonalMDCTConceal_Apply( st->hTonalMDCTConc, x[ch][0], st->hTcxCfg->psychParamsCurrent ); } - if ( ( bfi || isMCT ) && st->hTonalMDCTConc != NULL ) + if ( ( bfi || MCT_flag ) && st->hTonalMDCTConc != NULL ) { TonalMDCTConceal_UpdateState( st->hTonalMDCTConc, L_frameTCX[ch], ( st->hTcxDec->tcxltp_last_gain_unmodified > 0 ) ? st->old_fpitch : 0, bfi, bfi && st->tonal_mdct_plc_active ); } diff --git a/lib_dec/ivas_mono_dmx_renderer.c b/lib_dec/ivas_mono_dmx_renderer.c index 468b0215b0f90bb7b486581bc5c69eacbdb8cfa0..d4dcb7ac7339e69e50347c4061c68b9547d8a3b9 100644 --- a/lib_dec/ivas_mono_dmx_renderer.c +++ b/lib_dec/ivas_mono_dmx_renderer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -63,7 +63,7 @@ ivas_error ivas_mono_dmx_renderer_open( { MONO_DOWNMIX_RENDERER_HANDLE hDownmix; - if ( ( hDownmix = (MONO_DOWNMIX_RENDERER_HANDLE) count_malloc( sizeof( MONO_DOWNMIX_RENDERER_STRUCT ) ) ) == NULL ) + if ( ( hDownmix = (MONO_DOWNMIX_RENDERER_HANDLE) malloc( sizeof( MONO_DOWNMIX_RENDERER_STRUCT ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for downmixing\n" ) ); } @@ -124,10 +124,11 @@ void ivas_mono_downmix_render_passive( return; } + /*------------------------------------------------------------------------- * ivas_mono_stereo_downmix_mcmasa() * - * Downmix process + * Downmix process in McMASA *------------------------------------------------------------------------*/ void ivas_mono_stereo_downmix_mcmasa( @@ -165,4 +166,6 @@ void ivas_mono_stereo_downmix_mcmasa( /* Move to output */ mvr2r( dmx_tmp, output_f[0], output_frame ); } + + return; } diff --git a/lib_dec/ivas_objectRenderer.c b/lib_dec/ivas_objectRenderer.c deleted file mode 100644 index 43aa475e7da95ff80ebe3a3472c9e02e7f29a716..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_objectRenderer.c +++ /dev/null @@ -1,414 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include "prot.h" -#include "ivas_prot.h" -#include -#include "wmops.h" -#include "ivas_rom_com.h" -#ifdef DEBUGGING -#include "debug.h" -#endif - - -/*---------------------------------------------------------------------* - * Local function prototypes - *---------------------------------------------------------------------*/ -static ivas_error TDREND_GetMix( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, float output[][L_FRAME48k], const int16_t output_frame, const int32_t output_Fs ); -static void TDREND_Clear_Update_flags( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd ); - -/*---------------------------------------------------------------------* - * ivas_td_binaural_open() - * - * Open and initialize TD Object binaural renderer - *---------------------------------------------------------------------*/ - -/*! r: TD Renderer result code. */ -ivas_error ivas_td_binaural_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -) -{ - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd; - TDREND_PosType_t PosType; - int16_t nS; - int16_t SrcInd[MAX_NUM_TDREND_CHANNELS]; - const float *ls_azimuth, *ls_elevation; - float Pos[3]; - float Dir[3]; - TDREND_DirAtten_t *DirAtten_p; - int16_t nchan_rend; - ivas_error error; - - error = IVAS_ERR_OK; - - if ( ( hBinRendererTd = count_malloc( sizeof( BINAURAL_TD_OBJECT_RENDERER ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); - } - if ( ( hBinRendererTd->TdRend_MixSpatSpec_p = count_malloc( sizeof( TDREND_MixSpatSpec_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); - } - if ( ( hBinRendererTd->DirAtten_p = count_malloc( sizeof( TDREND_DirAtten_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); - } - if ( ( hBinRendererTd->Listener_p = count_malloc( sizeof( TDREND_MIX_Listener_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); - } - - hBinRendererTd->NumOfSrcs = 0; - hBinRendererTd->MaxSrcInd = -1; - - /* Mixer spatial setup */ - hBinRendererTd->TdRend_MixSpatSpec_p->UseCommonDistAttenModel = TRUE; - hBinRendererTd->TdRend_MixSpatSpec_p->DistAttenModel = 0; /* 0=Turned off, else use TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED */ - - TDREND_MIX_Init( hBinRendererTd, &st_ivas->hHrtfTD, hBinRendererTd->TdRend_MixSpatSpec_p, st_ivas->hDecoderConfig->output_Fs ); - - /* Set the attenuation (or can set MixSpatSpec.DistAttenModel above) */ - TDREND_MIX_SetDistAttenModel( hBinRendererTd, TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED ); - - /* Add sources to module and mixer, headphones */ - PosType = TDREND_POSTYPE_ABSOLUTE; /* or TDREND_POSTYPE_RELATIVE_TO_LISTENER */ - - nchan_rend = st_ivas->nchan_transport; - if ( st_ivas->ivas_format == MC_FORMAT ) - { - nchan_rend--; /* Skip LFE channel -- added to the others */ - } - - for ( nS = 0; nS < nchan_rend; nS++ ) - { - if ( ( error = TDREND_MIX_AddSrc( hBinRendererTd, &SrcInd[nS], PosType, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - if ( st_ivas->ivas_format == MC_FORMAT ) - { - switch ( st_ivas->transport_config ) - { - case AUDIO_CONFIG_5_1: - ls_azimuth = ls_azimuth_CICP6; - ls_elevation = ls_elevation_CICP6; - break; - case AUDIO_CONFIG_7_1: - ls_azimuth = ls_azimuth_CICP12; - ls_elevation = ls_elevation_CICP12; - break; - case AUDIO_CONFIG_5_1_2: - ls_azimuth = ls_azimuth_CICP14; - ls_elevation = ls_elevation_CICP14; - break; - case AUDIO_CONFIG_5_1_4: - ls_azimuth = ls_azimuth_CICP16; - ls_elevation = ls_elevation_CICP16; - break; - case AUDIO_CONFIG_7_1_4: - ls_azimuth = ls_azimuth_CICP19; - ls_elevation = ls_elevation_CICP19; - break; - default: - ls_azimuth = NULL; - ls_elevation = NULL; - } - - DirAtten_p = hBinRendererTd->DirAtten_p; - - for ( nS = 0; nS < nchan_rend; nS++ ) - { - /* Set source positions according to loudspeaker layout */ - Pos[0] = cosf( ls_elevation[nS] * PI_OVER_180 ) * cosf( ls_azimuth[nS] * PI_OVER_180 ); - Pos[1] = cosf( ls_elevation[nS] * PI_OVER_180 ) * sinf( ls_azimuth[nS] * PI_OVER_180 ); - Pos[2] = sinf( ls_elevation[nS] * PI_OVER_180 ); - Dir[0] = 1.0f; - Dir[1] = 0.0f; - Dir[2] = 0.0f; - - /* Source directivity info */ - DirAtten_p->ConeInnerAngle = 360.0f; - DirAtten_p->ConeOuterAngle = 360.0f; - DirAtten_p->ConeOuterGain = 1.0f; - - TDREND_MIX_SRC_SetPos( hBinRendererTd, nS, Pos ); - TDREND_MIX_SRC_SetDir( hBinRendererTd, nS, Dir ); - TDREND_MIX_SRC_SetPlayState( hBinRendererTd, nS, TDREND_PLAYSTATUS_PLAYING ); - TDREND_MIX_SRC_SetDirAtten( hBinRendererTd, nS, DirAtten_p ); - } - } - - st_ivas->hBinRendererTd = hBinRendererTd; - - st_ivas->binaural_latency_ns = (int32_t) ( BINAURAL_TD_LATENCY_S * 1000000000.f ); - - return error; -} - - -/*---------------------------------------------------------------------* - * ivas_td_binaural_close() - * - * Close TD Object binaural renderer - *---------------------------------------------------------------------*/ - -void ivas_td_binaural_close( - BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */ -) -{ - if ( hBinRendererTd == NULL || *hBinRendererTd == NULL ) - { - return; - } - - count_free( ( *hBinRendererTd )->TdRend_MixSpatSpec_p ); - count_free( ( *hBinRendererTd )->DirAtten_p ); - - TDREND_MIX_Dealloc( *hBinRendererTd ); - - count_free( *hBinRendererTd ); - *hBinRendererTd = NULL; - - return; -} - - -/*---------------------------------------------------------------------* - * ObjRenderIVASFrame() - * - * Receives the current frames for the object streams, updates metadata - * and renders the current frame. - *---------------------------------------------------------------------*/ - -/*! r: TD Renderer result code. */ -ivas_error ObjRenderIVASFrame( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ - const int16_t output_frame /* i : output frame length */ -) -{ - TDREND_DirAtten_t *DirAtten_p; - int16_t nS; - float Pos[3]; - float Dir[3]; - float FrontVec[3]; - float UpVec[3]; - float Rmat[3][3]; - int16_t c_indx; - int16_t subframe_idx; - float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k]; - - DirAtten_p = st_ivas->hBinRendererTd->DirAtten_p; - - /* Update the listener's location/orientation */ - /* Listener at the origin */ - Pos[0] = 0.0f; - Pos[1] = 0.0f; - Pos[2] = 0.0f; - - if ( st_ivas->hHeadTrackData != NULL ) - { - /* Obtain head rotation matrix */ - QuatToRotMat( st_ivas->hHeadTrackData->Quaternions[0], Rmat ); - /* Apply rotation matrix to looking vector [1;0;0] */ - FrontVec[0] = Rmat[0][0]; - FrontVec[1] = Rmat[0][1]; - FrontVec[2] = Rmat[0][2]; - /* Apply rotation matrix to up vector [0;0;1] */ - UpVec[0] = Rmat[2][0]; - UpVec[1] = Rmat[2][1]; - UpVec[2] = Rmat[2][2]; - } - else - { - /* Oriented with looking vector along the x axis */ - FrontVec[0] = 1.0f; - FrontVec[1] = 0.0f; - FrontVec[2] = 0.0f; - /* Oriented with up vector along the z axis */ - UpVec[0] = 0.0f; - UpVec[1] = 0.0f; - UpVec[2] = 1.0f; - } - - /* Set the listener position and orientation:*/ - TDREND_MIX_LIST_SetPos( st_ivas->hBinRendererTd, Pos ); - TDREND_MIX_LIST_SetOrient( st_ivas->hBinRendererTd, FrontVec, UpVec ); - - /* For each source, write the frame data to the source object*/ - c_indx = 0; - for ( nS = 0; nS < st_ivas->nchan_transport; nS++ ) - { - if ( !( st_ivas->ivas_format == MC_FORMAT && nS == LFE_CHANNEL ) ) /* Skip LFE for MC */ - { - st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p = output[nS]; - st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE; - c_indx++; - } - - if ( st_ivas->ivas_format == ISM_FORMAT ) - { - - /* Update the source positions */ - /* Source position and direction */ - Pos[0] = cosf( st_ivas->hIsmMetaData[nS]->elevation * PI_OVER_180 ) * cosf( st_ivas->hIsmMetaData[nS]->azimuth * PI_OVER_180 ); - Pos[1] = cosf( st_ivas->hIsmMetaData[nS]->elevation * PI_OVER_180 ) * sinf( st_ivas->hIsmMetaData[nS]->azimuth * PI_OVER_180 ); - Pos[2] = sinf( st_ivas->hIsmMetaData[nS]->elevation * PI_OVER_180 ); - Dir[0] = 1.0f; - Dir[1] = 0.0f; - Dir[2] = 0.0f; - - /* Source directivity info */ - DirAtten_p->ConeInnerAngle = 360.0f; - DirAtten_p->ConeOuterAngle = 360.0f; - DirAtten_p->ConeOuterGain = 1.0f; - - TDREND_MIX_SRC_SetPos( st_ivas->hBinRendererTd, nS, Pos ); - TDREND_MIX_SRC_SetDir( st_ivas->hBinRendererTd, nS, Dir ); - TDREND_MIX_SRC_SetDirAtten( st_ivas->hBinRendererTd, nS, DirAtten_p ); - TDREND_MIX_SRC_SetPlayState( st_ivas->hBinRendererTd, nS, TDREND_PLAYSTATUS_PLAYING ); - } - } - - if ( st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) - { - if ( st_ivas->ini_frame == 0 ) - { - ivas_reverb_open( &st_ivas->hCrend->hReverb, NULL, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ); - } - for ( subframe_idx = 0; subframe_idx < 4; subframe_idx++ ) - { - ivas_reverb_process( st_ivas->hCrend->hReverb, st_ivas->transport_config, 0, output, reverb_signal, subframe_idx ); - } - } - - /* Call the renderer */ - TDREND_GetMix( st_ivas->hBinRendererTd, output, output_frame, st_ivas->hDecoderConfig->output_Fs ); - - if ( st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) - { - /* add reverb to rendered signals */ - v_add( reverb_signal[0], output[0], output[0], output_frame ); - v_add( reverb_signal[1], output[1], output[1], output_frame ); - } - - return IVAS_ERR_OK; -} - - -/*---------------------------------------------------------------------* - * TDREND_GetMix() - * - * Render one output frame from the mixer - *---------------------------------------------------------------------*/ - -/*! r: TD Renderer result code. */ -static ivas_error TDREND_GetMix( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - float output[][L_FRAME48k], /* i/o: ISm object synth / rendered output in 0,1 */ - const int16_t output_frame, /* i/o: Output frame length */ - const int32_t output_Fs /* i : Output sampling rate */ -) -{ - int16_t i; - TDREND_SRC_t *Src_p; - TDREND_SRC_SPATIAL_t *SrcSpatial_p; - TDREND_SRC_REND_t *SrcRend_p; - ivas_error result; - float output_buf[2][L_FRAME48k]; /* Temp buffer for left/right rendered signal */ - - result = IVAS_ERR_OK; - - /* Zero out the output buffer since objects are accumulated. */ - set_f( output_buf[0], 0.0f, output_frame ); - set_f( output_buf[1], 0.0f, output_frame ); - - /* Create the mix */ - /* Loop through the source list and render each source */ - for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) - { - Src_p = hBinRendererTd->Sources[i]; - SrcSpatial_p = Src_p->SrcSpatial_p; - SrcRend_p = Src_p->SrcRend_p; - - /* Update rendering params if needed */ - if ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) - { - TDREND_SRC_REND_UpdateFiltersFromSpatialParams( hBinRendererTd, SrcRend_p, SrcSpatial_p, output_Fs ); - } - - /* Render source if needed */ - if ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) ) - { -#ifdef TDREND_HRTF_TABLE_METHODS - result = TDREND_REND_RenderSourceHRFilt( Src_p, hBinRendererTd, output_buf, output_frame, output_Fs ); -#else - result = TDREND_REND_RenderSourceHRFilt( Src_p, output_buf, output_frame, output_Fs ); -#endif - } - SrcRend_p->InputAvailable = FALSE; - } - - /* Populate output variable */ - mvr2r( output_buf[0], output[0], output_frame ); /* Left */ - mvr2r( output_buf[1], output[1], output_frame ); /* Right */ - - /* Clear the mixer update flags */ - TDREND_Clear_Update_flags( hBinRendererTd ); - - return result; -} - - -/*---------------------------------------------------------------------* - * TDREND_Clear_Update_flags() - * - * Initializes the audio mixer module - *---------------------------------------------------------------------*/ - -static void TDREND_Clear_Update_flags( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */ -) -{ - int16_t i; - - hBinRendererTd->Listener_p->PoseUpdated = FALSE; - for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) - { - hBinRendererTd->Sources[i]->SrcSpatial_p->Updated = FALSE; - } - return; -} diff --git a/lib_dec/ivas_objectRenderer_hrFilt.c b/lib_dec/ivas_objectRenderer_hrFilt.c deleted file mode 100644 index fd2011a7d60c668853b94fbe09bc56f094478ce3..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_objectRenderer_hrFilt.c +++ /dev/null @@ -1,1339 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include -#include "options.h" -#include "prot.h" -#include -#include "ivas_prot.h" -#include "ivas_rom_dec.h" -#include "ivas_cnst.h" -#include "ivas_rom_TdBinauralRenderer.h" -#include "wmops.h" - - -/*---------------------------------------------------------------------* - * Local function prototypes - *---------------------------------------------------------------------*/ - -static void getPeriodicBSplineSampVec( float *BfVec, int16_t *AzIdx, const int16_t NumBFs, const float t, int16_t *num_az_idx, const float knot_interval, const float azimKSeq_0, const int16_t azimSegSamples, const float *azimBsShape, const int16_t subSampFactor ); -static void getStandardBSplineSampVec( float *BfVec, int16_t *NzIdx, int16_t *num_idx, const int16_t NumBFs, const float t, const float *KSeq, const int16_t SegSamples, const int16_t *BsLen, const int16_t *BsStart, const float *BsShape ); -static void GenerateFilter( const float elev, float azim, ModelParams_t *model, ModelEval_t *modelEval ); -static void GenerateITD( const float elev, float azim, ModelParamsITD_t *model, ModelEval_t *modelEval ); -static void SkipSmallest_ValueIndex( int16_t *use_inds, const ValueIndex_t *VI, const int16_t N, const int16_t n_smallest ); - -#ifdef TDREND_HRTF_TABLE_METHODS -static float GreatCircleAngleDeg( float Az1, float El1, float Az2, float El2 ); -static void GetFilterFromAngle_M( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, const float Elev, float Azim, SFX_SpatBin_Params_t *SfxSpatBinParams_p ); - -/*-------------------------------------------------------------------* - * TDREND_HRFILT_SetFiltSet() - * - * Load table format HR filter set from file. - --------------------------------------------------------------------*/ - -void TDREND_HRFILT_SetFiltSet( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR hilter set structure */ - FILE *f_hrtf /* i : File handle for HR filter parameters */ -) -{ - float Scaler_HrfGain; - int16_t n; - - int16_t num_to_read, num_bytes; - double temp; - int16_t temp_s; - double *buffer_p = NULL; - double *temp_p; - double *FiltSetIntLeft_p = NULL, *FiltSetIntRight_p = NULL; - double *FiltIntLeft0_p = NULL, *FiltIntLeft_p = NULL, *FiltIntRight0_p = NULL, *FiltIntRight_p = NULL; - double *LeftFilt_p = NULL, *RightFilt_p = NULL; - float *LeftFiltFlp_p = NULL, *RightFiltFlp_p = NULL; - - int32_t mem_size; - int16_t i; - -#ifdef TDREND_HRTF_TABLE_METHODS - int16_t count, m; -#endif - - /* The setting of Scaler_HrfGain varies among HR filter dataset */ - - Scaler_HrfGain = 1.0f; - - /* read the sampling rate */ - fread( &temp_s, sizeof( int16_t ), 1, f_hrtf ); - - switch ( temp_s ) - { - case 16: - HrFiltSet_p->SampleRate = 16000; - break; - case 32: - HrFiltSet_p->SampleRate = 32000; - break; - case 48: - HrFiltSet_p->SampleRate = 48000; - break; - default: -#ifdef DEBUGGING - IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Error: HR filter file had an unsupported sampling rate (%d kHz).\n\n", temp_s ); -#endif - } - - num_bytes = sizeof( double ); - num_to_read = 1; - - /* read the filter length */ - fread( &temp, num_bytes, num_to_read, f_hrtf ); - HrFiltSet_p->FiltLength = (int16_t) temp; - - /* read the distance */ - fread( &temp, num_bytes, num_to_read, f_hrtf ); - HrFiltSet_p->Dist = (float) temp; - /* read the number of positions */ - fread( &temp, num_bytes, num_to_read, f_hrtf ); - HrFiltSet_p->NumPos = (int16_t) temp; - - if ( HrFiltSet_p->FilterMethod == TDREND_HRFILT_Method_Table_F ) - { - /* Number of elevation angles */ - fread( &temp, num_bytes, num_to_read, f_hrtf ); - HrFiltSet_p->NumElev = (int16_t) temp; - - /* Elevation angles */ - HrFiltSet_p->Elev_p = (float *) count_malloc( HrFiltSet_p->NumElev * sizeof( float ) ); - buffer_p = (double *) count_malloc( HrFiltSet_p->NumElev * sizeof( double ) ); - num_to_read = HrFiltSet_p->NumElev; - fread( (void *) buffer_p, num_bytes, num_to_read, f_hrtf ); - temp_p = buffer_p; - HrFiltSet_p->ElevIncr = (float) ( buffer_p[1] - buffer_p[0] ); - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - HrFiltSet_p->Elev_p[n] = (float) *temp_p++; - if ( n > 0 && fabsf( ( HrFiltSet_p->Elev_p[n] - HrFiltSet_p->Elev_p[n - 1] - HrFiltSet_p->ElevIncr ) ) > 0.01 ) - { -#ifdef DEBUGGING - printf( "Error: HR Filter elevation values had irregular spacing.\n\n" ); -#endif - assert( 0 && "Error: HR Filter elevation values had irregular spacing." ); - } - } - count_free( buffer_p ); - - /* Number of azimuth values, one per elevation */ - HrFiltSet_p->NumAzim_p = (int16_t *) count_malloc( HrFiltSet_p->NumElev * sizeof( int16_t ) ); - buffer_p = (double *) count_malloc( HrFiltSet_p->NumElev * sizeof( double ) ); - fread( (void *) buffer_p, num_bytes, HrFiltSet_p->NumElev, f_hrtf ); - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - HrFiltSet_p->NumAzim_p[n] = (int16_t) buffer_p[n]; - } - count_free( buffer_p ); - - /* Indices to the first azimuth value, one per elevation */ - HrFiltSet_p->AzimStartIdx_p = (int16_t *) count_malloc( HrFiltSet_p->NumElev * sizeof( int16_t ) ); - count = 0; - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - HrFiltSet_p->AzimStartIdx_p[n] = count; - count += HrFiltSet_p->NumAzim_p[n]; - } - if ( count != HrFiltSet_p->NumPos ) - { -#ifdef DEBUGGING - printf( "Error: Inconsistent number of points in HR filter file.\n\n" ); -#endif - assert( 0 && "Error: Inconsistent number of points in HR filter file." ); - } - - /* Azimuth values, one set per elevation, i.e. one per measurement point */ - HrFiltSet_p->Azim_p = (float *) count_malloc( HrFiltSet_p->NumPos * sizeof( float ) ); - buffer_p = (double *) count_malloc( HrFiltSet_p->NumPos * sizeof( double ) ); - HrFiltSet_p->ElevFull_p = (float *) count_malloc( HrFiltSet_p->NumPos * sizeof( float ) ); - fread( (void *) buffer_p, num_bytes, HrFiltSet_p->NumPos, f_hrtf ); - i = 0; - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - for ( m = 0; m < HrFiltSet_p->NumAzim_p[n]; m++ ) - { - HrFiltSet_p->Azim_p[i] = (float) buffer_p[i]; - HrFiltSet_p->ElevFull_p[i] = HrFiltSet_p->Elev_p[n]; - /* Range needs to be (-180, 180] */ - if ( HrFiltSet_p->Azim_p[i] > 180.0 ) - { - HrFiltSet_p->Azim_p[i] -= 360.0; - } - i++; - } - } - count_free( buffer_p ); - } - if ( HrFiltSet_p->FilterMethod == TDREND_HRFILT_Method_Table_S ) - { - /* Number of elevation angles */ - fread( &temp, num_bytes, num_to_read, f_hrtf ); - HrFiltSet_p->NumElev = (int16_t) temp; - - /* Elevation angles */ - HrFiltSet_p->Elev_p = (float *) count_malloc( HrFiltSet_p->NumElev * sizeof( float ) ); - buffer_p = (double *) count_malloc( HrFiltSet_p->NumElev * sizeof( double ) ); - num_to_read = HrFiltSet_p->NumElev; - fread( (void *) buffer_p, num_bytes, num_to_read, f_hrtf ); - temp_p = buffer_p; - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - HrFiltSet_p->Elev_p[n] = (float) *temp_p++; - } - count_free( buffer_p ); - - /* Number of azimuth values, one per elevation */ - HrFiltSet_p->NumAzim_p = (int16_t *) count_malloc( HrFiltSet_p->NumElev * sizeof( int16_t ) ); - buffer_p = (double *) count_malloc( HrFiltSet_p->NumElev * sizeof( double ) ); - fread( (void *) buffer_p, num_bytes, HrFiltSet_p->NumElev, f_hrtf ); - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - HrFiltSet_p->NumAzim_p[n] = (int16_t) buffer_p[n]; - } - count_free( buffer_p ); - - /* Indices to the first azimuth value, one per elevation */ - HrFiltSet_p->AzimStartIdx_p = (int16_t *) count_malloc( HrFiltSet_p->NumElev * sizeof( int16_t ) ); - count = 0; - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - HrFiltSet_p->AzimStartIdx_p[n] = count; - count += HrFiltSet_p->NumAzim_p[n]; - } - if ( count != HrFiltSet_p->NumPos ) - { -#ifdef DEBUGGING - printf( "Inconsistent number of points in HR filter file.\n\n" ); -#endif - assert( 0 && "Inconsistent number of points in HR filter file." ); - } - - /* Azimuth values, one set per elevation, i.e. one per measurement point */ - HrFiltSet_p->Azim_p = (float *) count_malloc( HrFiltSet_p->NumPos * sizeof( float ) ); - buffer_p = (double *) count_malloc( HrFiltSet_p->NumPos * sizeof( double ) ); - HrFiltSet_p->ElevFull_p = (float *) count_malloc( HrFiltSet_p->NumPos * sizeof( float ) ); - fread( (void *) buffer_p, num_bytes, HrFiltSet_p->NumPos, f_hrtf ); - i = 0; - for ( n = 0; n < HrFiltSet_p->NumElev; n++ ) - { - for ( m = 0; m < HrFiltSet_p->NumAzim_p[n]; m++ ) - { - HrFiltSet_p->Azim_p[i] = (float) buffer_p[i]; - HrFiltSet_p->ElevFull_p[i] = HrFiltSet_p->Elev_p[n]; - /* Range needs to be (-180, 180] */ - if ( HrFiltSet_p->Azim_p[i] > 180.0 ) - { - HrFiltSet_p->Azim_p[i] -= 360.0; - } - i++; - } - } - count_free( buffer_p ); - } - - /* allocate memory to LeftFilt and RightFilt */ - mem_size = ( HrFiltSet_p->NumPos * HrFiltSet_p->FiltLength * sizeof( double ) ); - - FiltSetIntRight_p = (double *) count_malloc( mem_size ); - FiltSetIntLeft_p = (double *) count_malloc( mem_size ); - RightFilt_p = FiltSetIntRight_p; - LeftFilt_p = FiltSetIntLeft_p; - - /* read the HR filters */ - for ( i = 0; i < HrFiltSet_p->NumPos; i++ ) - { - /* read the left filter */ - fread( (void *) LeftFilt_p, num_bytes, HrFiltSet_p->FiltLength, f_hrtf ); - /* read the right filter */ - fread( (void *) RightFilt_p, num_bytes, HrFiltSet_p->FiltLength, f_hrtf ); - - LeftFilt_p += HrFiltSet_p->FiltLength; - RightFilt_p += HrFiltSet_p->FiltLength; - } - - /* Check that the whole file was read. */ - getc( f_hrtf ); - if ( !feof( f_hrtf ) ) - { -#ifdef DEBUGGING - printf( "Error: The HRTF filter file size was larger than expected.\n\n" ); -#endif - assert( 0 && "Error: The HRTF filter file size was larger than expected." ); - } - - /* IMPORTANT: We are now using reversed FIR filters as they */ - /* result in better SIMD (neon) optimization */ - /* Copy, and reverse the filter sets */ - - mem_size = ( HrFiltSet_p->NumPos * HrFiltSet_p->FiltLength * sizeof( float ) ); - RightFiltFlp_p = (float *) count_malloc( mem_size ); - LeftFiltFlp_p = (float *) count_malloc( mem_size ); - HrFiltSet_p->RightFiltSet_p = RightFiltFlp_p; - HrFiltSet_p->LeftFiltSet_p = LeftFiltFlp_p; - - FiltIntRight0_p = FiltSetIntRight_p + (int16_t) HrFiltSet_p->FiltLength - 1; - FiltIntLeft0_p = FiltSetIntLeft_p + (int16_t) HrFiltSet_p->FiltLength - 1; - - for ( i = 0; i < HrFiltSet_p->NumPos; i++ ) - { - /* Copy right filter */ - FiltIntRight_p = FiltIntRight0_p; - for ( n = 0; n < HrFiltSet_p->FiltLength; n++ ) - { - *RightFiltFlp_p++ = Scaler_HrfGain * (float) ( *FiltIntRight_p-- ); - } - FiltIntRight0_p += HrFiltSet_p->FiltLength; - - /* Copy left filter */ - FiltIntLeft_p = FiltIntLeft0_p; - for ( n = 0; n < HrFiltSet_p->FiltLength; n++ ) - { - *LeftFiltFlp_p++ = Scaler_HrfGain * (float) ( *FiltIntLeft_p-- ); - } - FiltIntLeft0_p += HrFiltSet_p->FiltLength; - } - - count_free( FiltSetIntLeft_p ); - count_free( FiltSetIntRight_p ); - - return; -} -#endif - - -/*-------------------------------------------------------------------* - * TDREND_REND_RenderSourceHRFilt() - * - * Renders each object using the HR filters - --------------------------------------------------------------------*/ - -ivas_error TDREND_REND_RenderSourceHRFilt( - const TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ -#ifdef TDREND_HRTF_TABLE_METHODS - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ -#endif - float output_buf[][L_FRAME48k], /* o : Output buffer */ - const int16_t output_frame, /* i : Output frame length in use */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - ivas_error SFX_Result; - TDREND_SRC_REND_t *SrcRend_p; - int16_t nS; - float *InFrame_nIC_p; - int16_t NoOfUsedInputSamples, NoOfDeliveredOutputSamples; - float LeftOutputFrame[L_FRAME48k]; - float RightOutputFrame[L_FRAME48k]; - float *LeftOutputFrame_p, *RightOutputFrame_p; - float *LeftAccOutputFrame_p, *RightAccOutputFrame_p; - - /* Input channel rendering loop */ - InFrame_nIC_p = Src_p->InputFrame_p; - SrcRend_p = Src_p->SrcRend_p; - - /* Gain not currently encoded/used */ - /* SrcGain = Mix_p->Gain * ( *SrcRend_p->SrcGain_p ); */ - /* SrcGain *= ( *SrcRend_p->DirGain_p ) * ( *SrcRend_p->DistGain_p ); */ - - SFX_Result = TDREND_SFX_SpatBin_Execute_Main( SrcRend_p->SfxSpatBin_p, InFrame_nIC_p, output_frame, - LeftOutputFrame, RightOutputFrame, - &NoOfUsedInputSamples, &NoOfDeliveredOutputSamples, output_Fs ); - -#ifdef TDREND_HRTF_TABLE_METHODS - if ( hBinRendererTd->HrFiltSet_p->FilterMethod != TDREND_HRFILT_Method_BSplineModel ) - { - SrcRend_p->SfxSpatBin_p->HrFilterInterpOn = 1; /* Turn on after first frame is rendered. */ - } -#endif - - /* Copy to accumulative output frame */ - LeftOutputFrame_p = LeftOutputFrame; - RightOutputFrame_p = RightOutputFrame; - LeftAccOutputFrame_p = output_buf[0]; - RightAccOutputFrame_p = output_buf[1]; - for ( nS = 0; nS < output_frame; nS++ ) - { - *LeftAccOutputFrame_p++ += *LeftOutputFrame_p++; - *RightAccOutputFrame_p++ += *RightOutputFrame_p++; - } - - return SFX_Result; -} - - -#ifdef TDREND_HRTF_TABLE_METHODS -/*-------------------------------------------------------------------* - * GetFilterFromAngle_F() - * - * Obtain an HR filter corresponding to the input angle pair. - * This version is for FABIAN format. - --------------------------------------------------------------------*/ - -static void GetFilterFromAngle_F( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ - const float Elev, /* i : Elevation, degrees */ - float Azim, /* i : Azimuth, degrees */ - SFX_SpatBin_Params_t *SfxSpatBinParams_p /* i/o: Currently used HR filter */ -) -{ - int16_t AzimInd, ElevInd, n; - int16_t ElevIndLo; - int16_t ElevIndHi; - int16_t flipped = 0; - float AzimMod; - float AzimLo, AzimHi; - uint32_t HrFiltInd; - int32_t CandidateIndices[100]; /* Stores the indices of the candidate points. */ - float CandidateAngles[100]; /* Stores the angular distance between the candidate and the test point. */ - int16_t c = 0; - int16_t test; - float CandidateAzim, CandidateElev, min; - - /* Note need to support azimuth range [-180,180] since this is what is returned by atan2f. AzimMod is on the */ - /* range (-180,180]. This should be faster than doing a full mod(360) etc. */ - if ( Azim == -180.0f ) - { - AzimMod = 180.0f; - } - else - { - AzimMod = Azim; - } - - /* Use the nearest filter point. Since the azimuth is not assumed to be the same for */ - /* different elevations, make a shortlist of rows to check, and a range azimuth to check. */ - ElevInd = (int16_t) roundf( ( Elev - HrFiltSet_p->Elev_p[0] ) / HrFiltSet_p->ElevIncr ); /* Regular elevation spacing */ - if ( ElevInd < 0 ) - { - ElevInd = 0; - } - else if ( ElevInd >= HrFiltSet_p->NumElev ) - { - ElevInd = HrFiltSet_p->NumElev - 1; - } - ElevIndLo = max( 0, ElevInd - 2 ); - ElevIndHi = min( HrFiltSet_p->NumElev - 1, ElevInd + 2 ); - - AzimLo = AzimMod - 15; - if ( AzimLo <= -180.0 ) - { - AzimLo += 360.0; - } - AzimHi = AzimMod + 15; - if ( AzimHi > 360.0 ) - { - AzimHi -= 360.0; - } - - if ( AzimHi < AzimLo ) - { - flipped = 1; - } - - /* Check each candidate elevation row, and each azimuth value in that row, to make a list of candidate points. */ - for ( ElevInd = ElevIndLo; ElevInd <= ElevIndHi; ElevInd++ ) - { - for ( AzimInd = HrFiltSet_p->AzimStartIdx_p[ElevInd]; - AzimInd < HrFiltSet_p->AzimStartIdx_p[ElevInd] + HrFiltSet_p->NumAzim_p[ElevInd]; - AzimInd++ ) - { - if ( flipped == 0 ) - { - test = HrFiltSet_p->Azim_p[AzimInd] >= AzimLo && HrFiltSet_p->Azim_p[AzimInd] <= AzimHi; - } - else - { - /* This is the case where the limits straddle the +/- 180 discontinuity */ - test = HrFiltSet_p->Azim_p[AzimInd] >= AzimLo || HrFiltSet_p->Azim_p[AzimInd] <= AzimHi; - } - if ( test ) - { - /* Azim value is within range, store it */ - CandidateIndices[c] = AzimInd; - c++; - } - } - } - - for ( n = 0; n < c; n++ ) - { - CandidateAzim = HrFiltSet_p->Azim_p[CandidateIndices[n]]; - CandidateElev = HrFiltSet_p->ElevFull_p[CandidateIndices[n]]; - CandidateAngles[n] = GreatCircleAngleDeg( AzimMod, Elev, CandidateAzim, CandidateElev ); - } - - /* Find the candidate with the minimum angle/distance */ - min = CandidateAngles[0]; - HrFiltInd = CandidateIndices[0]; - for ( n = 1; n < c; n++ ) - { - if ( CandidateAngles[n] < min ) - { - min = CandidateAngles[n]; - HrFiltInd = CandidateIndices[n]; - } - } - - HrFiltInd *= HrFiltSet_p->FiltLength; - - /* 3. No extracted ITD. */ - SfxSpatBinParams_p->Itd = 0; - - /* 4. Copy the filter over */ - for ( n = 0; n < HrFiltSet_p->FiltLength; n++ ) - { - SfxSpatBinParams_p->LeftFilter_p[n] = HrFiltSet_p->LeftFiltSet_p[HrFiltInd + n]; - SfxSpatBinParams_p->RightFilter_p[n] = HrFiltSet_p->RightFiltSet_p[HrFiltInd + n]; - } - - return; -} - - -/*-------------------------------------------------------------------* - * GetFilterFromAngle_S() - * - * Obtain an HR filter corresponding to the input angle pair. - * This version is for SADIE format. - --------------------------------------------------------------------*/ - -static void GetFilterFromAngle_S( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ - const float Elev, /* i : Elevation, degrees */ - float Azim, /* i : Azimuth, degrees */ - SFX_SpatBin_Params_t *SfxSpatBinParams_p /* i/o: Currently used HR filter */ -) -{ - int16_t AzimInd, n; - int16_t ElevInd = -1; - int16_t ElevIndLo; - int16_t ElevIndHi; - int16_t flipped = 0; - float ElevDiff = 200.f; - float AzimMod, AzimLo, AzimHi; - uint32_t HrFiltInd; - int32_t CandidateIndices[400]; /* Stores the indices of the candidate points. */ - float CandidateAngles[400]; /* Stores the angular distance between the candidate and the test point. */ - int16_t c; - int16_t test; - float CandidateAzim, CandidateElev, min; - - /* Note need to support azimuth range [-180,180] since this is what is returned by atan2f. AzimMod is on the */ - /* range (-180,180]. This should be faster than doing a full mod(360) etc. */ - if ( Azim == -180.0f ) - { - AzimMod = 180.0f; - } - else - { - AzimMod = Azim; - } - - /* Use the nearest filter point. Since the azimuth is not assumed to be the same for */ - /* different elevations, make a shortlist of rows to check, and a range azimuth to check. */ - for ( c = 0; c < HrFiltSet_p->NumElev; c++ ) - { - if ( fabsf( Elev - HrFiltSet_p->Elev_p[c] ) < ElevDiff ) - { - ElevDiff = fabsf( Elev - HrFiltSet_p->Elev_p[c] ); - ElevInd = c; - } - } - - if ( ElevInd < 0 ) - { - ElevInd = 0; - } - else if ( ElevInd >= HrFiltSet_p->NumElev ) - { - ElevInd = HrFiltSet_p->NumElev - 1; - } - ElevIndLo = max( 0, ElevInd - 2 ); - ElevIndHi = min( HrFiltSet_p->NumElev - 1, ElevInd + 2 ); - - AzimLo = AzimMod - 15; - if ( AzimLo <= -180.0 ) - { - AzimLo += 360.0; - } - AzimHi = AzimMod + 15; - if ( AzimHi > 360.0 ) - { - AzimHi -= 360.0; - } - - if ( AzimHi < AzimLo ) - { - flipped = 1; - } - - /* Check each candidate elevation row, and each azimuth value in that row, to make a list of candidate points. */ - c = 0; - for ( ElevInd = ElevIndLo; ElevInd <= ElevIndHi; ElevInd++ ) - { - for ( AzimInd = HrFiltSet_p->AzimStartIdx_p[ElevInd]; - AzimInd < HrFiltSet_p->AzimStartIdx_p[ElevInd] + HrFiltSet_p->NumAzim_p[ElevInd]; - AzimInd++ ) - { - if ( flipped == 0 ) - { - test = HrFiltSet_p->Azim_p[AzimInd] >= AzimLo && HrFiltSet_p->Azim_p[AzimInd] <= AzimHi; - } - else - { - /* This is the case where the limits straddle the +/- 180 discontinuity */ - test = HrFiltSet_p->Azim_p[AzimInd] >= AzimLo || HrFiltSet_p->Azim_p[AzimInd] <= AzimHi; - } - if ( test ) - { - /* Azim value is within range, store it */ - CandidateIndices[c] = AzimInd; - c++; - } - } - } - - for ( n = 0; n < c; n++ ) - { - CandidateAzim = HrFiltSet_p->Azim_p[CandidateIndices[n]]; - CandidateElev = HrFiltSet_p->ElevFull_p[CandidateIndices[n]]; - CandidateAngles[n] = GreatCircleAngleDeg( AzimMod, Elev, CandidateAzim, CandidateElev ); - } - - /* Find the candidate with the minimum angle/distance */ - min = CandidateAngles[0]; - HrFiltInd = CandidateIndices[0]; - for ( n = 1; n < c; n++ ) - { - if ( CandidateAngles[n] < min ) - { - min = CandidateAngles[n]; - HrFiltInd = CandidateIndices[n]; - } - } - - HrFiltInd *= HrFiltSet_p->FiltLength; - - /* 3. No extracted ITD. */ - SfxSpatBinParams_p->Itd = 0; - - /* 4. Copy the filter over */ - for ( n = 0; n < HrFiltSet_p->FiltLength; n++ ) - { - SfxSpatBinParams_p->LeftFilter_p[n] = HrFiltSet_p->LeftFiltSet_p[HrFiltInd + n]; - SfxSpatBinParams_p->RightFilter_p[n] = HrFiltSet_p->RightFiltSet_p[HrFiltInd + n]; - } - - return; -} - - -/*-------------------------------------------------------------------* - * GetFilterFromAngle() - * - * Obtain an HR filter corresponding to the input angle pair. - * This version is a controller that switches between the available - * methods (table, model) according to HrFiltSet_p->FilterMethod - --------------------------------------------------------------------*/ - -void GetFilterFromAngle( - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ - const float Elev, /* i : Elevation, degrees */ - float Azim, /* i : Azimuth, degrees */ - SFX_SpatBin_Params_t *SfxSpatBinParams_p /* i/o: Currently used HR filter */ -) -{ - switch ( HrFiltSet_p->FilterMethod ) - { - case TDREND_HRFILT_Method_BSplineModel: - GetFilterFromAngle_M( HrFiltSet_p, Elev, Azim, SfxSpatBinParams_p ); - break; - case TDREND_HRFILT_Method_Table_F: - GetFilterFromAngle_F( HrFiltSet_p, Elev, Azim, SfxSpatBinParams_p ); - break; - case TDREND_HRFILT_Method_Table_S: - GetFilterFromAngle_S( HrFiltSet_p, Elev, Azim, SfxSpatBinParams_p ); - break; - } - - return; -} -#endif - -/*-------------------------------------------------------------------* - * GetFilterFromAngle() - * - * Obtain an HR filter corresponding to the input angle pair. - * This version uses the HR filter model. - --------------------------------------------------------------------*/ - -#ifdef TDREND_HRTF_TABLE_METHODS -static void GetFilterFromAngle_M( -#else -void GetFilterFromAngle( -#endif - TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ - const float Elev, /* i : Elevation, degrees */ - float Azim, /* i : Azimuth, degrees */ - SFX_SpatBin_Params_t *SfxSpatBinParams_p /* i/o: Currently used HR filter */ -) -{ - int16_t count, ii; - - GenerateFilter( Elev, Azim, &HrFiltSet_p->ModelParams, &HrFiltSet_p->ModelEval ); - - /* Renderer requires filter in reversed order: */ - count = 0; - for ( ii = ( HrFiltSet_p->ModelParams.K - 1 ); ii >= 0; ii-- ) - { - SfxSpatBinParams_p->LeftFilter_p[ii] = HrFiltSet_p->ModelEval.hrfModL[count]; - SfxSpatBinParams_p->RightFilter_p[ii] = HrFiltSet_p->ModelEval.hrfModR[count]; - count++; - } - - /* 4. Evaluate the ITD */ - if ( HrFiltSet_p->ModelParams.UseItdModel ) - { - GenerateITD( Elev, Azim, &HrFiltSet_p->ModelParamsITD, &HrFiltSet_p->ModelEval ); - SfxSpatBinParams_p->Itd = HrFiltSet_p->ModelEval.itdMod; - } - else - { - SfxSpatBinParams_p->Itd = 0; /* No extracted ITD */ - } - - return; -} - - -/*-------------------------------------------------------------------* - * GenerateFilter() - * - * Generate an HR filter using the B Spline model. - --------------------------------------------------------------------*/ - -static void GenerateFilter( - const float elev, /* i : Elevation angle, degrees */ - float azim, /* i : Azimuth angle, degrees */ - ModelParams_t *model, /* i : Model parameters structure */ - ModelEval_t *modelEval /* i/o: Model evaluation structure */ -) -{ - int16_t qp, p, k, i; - int32_t index; - int16_t AzIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS][HRTF_MODEL_BSPLINE_NUM_COEFFS], EvIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; /* non-zero basis functions */ - int16_t num_az_idx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - int16_t num_ev_idx; - int16_t BM_idx[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - float knot_interval; - float ETotL, ETotR, ESynL, ESynR; - float ScaleL, ScaleR; - int16_t iSec; - - getStandardBSplineSampVec( modelEval->elevBfVec, EvIdx, &num_ev_idx, model->elevDim3, elev, model->elevKSeq, - model->elevSegSamples, model->elevBsLen, model->elevBsStart, model->elevBsShape ); - - for ( p = 0; p < num_ev_idx; p++ ) - { - /* Wrap the requested azimuth to the range of the BSplines */ - azim = fmodf( azim + model->azimKSeq[p][0], 360 ); - if ( azim < 0 ) - { - azim += 360.0f; - } - azim = azim - model->azimKSeq[p][0]; - - if ( model->azimDim3[EvIdx[p]] == 1 ) /* Constant basis function */ - { - num_az_idx[p] = 1; - AzIdx[p][0] = 0; - modelEval->azimBfVec[p][0] = 1.0f; - } - else - { - k = EvIdx[p]; - knot_interval = ( model->azimKSeq[k][model->azimDim3[k]] - model->azimKSeq[k][0] ) / model->azimDim3[k]; - - getPeriodicBSplineSampVec( modelEval->azimBfVec[p], AzIdx[p], model->azimDim3[k], azim, &num_az_idx[p], - knot_interval, model->azimKSeq[k][0], model->azimSegSamples[model->azimShapeIdx[k]], - model->azimBsShape[model->azimShapeIdx[k]], model->azimShapeSampFactor[k] ); - } - } - - /* Compute BM */ - qp = 0; - for ( p = 0; p < num_ev_idx; p++ ) - { - for ( i = 0; i < num_az_idx[p]; i++ ) - { - modelEval->BM[qp + i] = modelEval->elevBfVec[p] * modelEval->azimBfVec[p][i]; - BM_idx[qp + i] = model->azim_start_idx[EvIdx[p]] + AzIdx[p][i]; - } - qp = qp + num_az_idx[p]; - } - - /* Compute HR filters, approximate optimized model evaluation */ - for ( iSec = 0; iSec < HRTF_MODEL_N_SECTIONS; iSec++ ) - { - ETotL = 0.0f; - ETotR = 0.0f; - ESynL = 0.0f; - ESynR = 0.0f; - - /* Energy is precalculated part updated with square of BM value. Store index for sorting */ - for ( i = 0; i < qp; i++ ) - { - modelEval->BMEnergiesL[i].val = modelEval->BM[i] * modelEval->BM[i] * model->EL[iSec * model->AlphaN + BM_idx[i]]; - modelEval->BMEnergiesR[i].val = modelEval->BM[i] * modelEval->BM[i] * model->ER[iSec * model->AlphaN + BM_idx[i]]; - modelEval->BMEnergiesL[i].i = i; - modelEval->BMEnergiesR[i].i = i; - ETotL += modelEval->BMEnergiesL[i].val; - ETotR += modelEval->BMEnergiesR[i].val; - } - - /* Number of basis components actually used. */ - p = min( HRTF_MODEL_N_CPTS_VAR[iSec], qp ); - SkipSmallest_ValueIndex( modelEval->UseIndsL, modelEval->BMEnergiesL, qp, qp - p ); - SkipSmallest_ValueIndex( modelEval->UseIndsR, modelEval->BMEnergiesR, qp, qp - p ); - - /* Account for lost energy */ - for ( i = 0; i < p; i++ ) - { - ESynL += modelEval->BMEnergiesL[modelEval->UseIndsL[i]].val; - ESynR += modelEval->BMEnergiesR[modelEval->UseIndsR[i]].val; - } - ScaleL = sqrtf( ETotL / ESynL ); - ScaleR = sqrtf( ETotR / ESynR ); - - /* Build using only the most energetic components. */ - for ( k = model->iSecFirst[iSec]; k <= model->iSecLast[iSec]; k++ ) - { - modelEval->hrfModL[k] = 0.0; - modelEval->hrfModR[k] = 0.0; - for ( i = 0; i < p; i++ ) - { - index = BM_idx[modelEval->BMEnergiesL[modelEval->UseIndsL[i]].i] + k * model->AlphaN; - modelEval->hrfModL[k] += modelEval->BM[modelEval->BMEnergiesL[modelEval->UseIndsL[i]].i] * model->AlphaL[index]; - index = BM_idx[modelEval->BMEnergiesR[modelEval->UseIndsR[i]].i] + k * model->AlphaN; - modelEval->hrfModR[k] += modelEval->BM[modelEval->BMEnergiesR[modelEval->UseIndsR[i]].i] * model->AlphaR[index]; - } - /* Account for lost energy */ - modelEval->hrfModL[k] *= ScaleL; - modelEval->hrfModR[k] *= ScaleR; - } - } - - return; -} - - -/*-------------------------------------------------------------------* - * GenerateITD() - * - * Generates an ITD value from the B Spline model. - --------------------------------------------------------------------*/ - -static void GenerateITD( - const float elev, /* i : Elevation angle, degrees */ - float azim, /* i : Azimuth angle, degrees */ - ModelParamsITD_t *model, /* i : ITD Model parameters structure */ - ModelEval_t *modelEval /* i/o: Model evaluation structure */ -) -{ - int16_t qp, p, i; - int32_t index; - int16_t AlphaN; - int16_t elev_offset; - float azim_itd; - int16_t AzIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS], EvIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; /* non-zero basis functions */ - int16_t num_az_idx, num_ev_idx; - int16_t BM_idx[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - - /* Wrap the requested azimuth to the range of the BSplines */ - azim = fmodf( azim + model->azimKSeq[0], 360 ); - if ( azim < 0 ) - { - azim += 360.0f; - } - azim = azim - model->azimKSeq[0]; - - if ( (int16_t) abs( (int16_t) elev ) != 90 ) - { - getStandardBSplineSampVec( modelEval->elevBfVecITD, EvIdx, &num_ev_idx, model->elevDim3, elev, model->elevKSeq, - model->elevSegSamples, model->elevBsLen, model->elevBsStart, model->elevBsShape ); - azim_itd = azim; - if ( azim > 180 ) - { - /* Flip spline functions around 180 deg */ - azim_itd = 360 - azim; - } - getStandardBSplineSampVec( modelEval->azimBfVecITD, AzIdx, &num_az_idx, ( model->azimDim3 + 1 ) / 2, azim_itd, model->azimKSeq, - model->azimSegSamples, model->azimBsLen, model->azimBsStart, model->azimBsShape ); - if ( azim > 180 ) - { - /* Flip spline functions around 180 deg */ - for ( i = 0; i < HRTF_MODEL_BSPLINE_NUM_COEFFS; i++ ) - { - AzIdx[i] = model->azimDim3 - 1 - AzIdx[i]; - } - } - } - else - { - num_az_idx = 1; - num_ev_idx = 1; - modelEval->elevBfVecITD[0] = 1.0f; - if ( elev < 0 ) - { - EvIdx[0] = 0; - } - else - { - EvIdx[0] = model->elevDim3 - 1; - } - } - - /* Compute BM_ITD */ - elev_offset = 0; - if ( model->elevKSeq[0] == -90 ) - { - elev_offset = -( model->azimDim3 - 1 ); - } - qp = 0; - for ( p = 0; p < num_ev_idx; p++ ) - { - if ( EvIdx[p] == 0 && (int16_t) ( model->elevKSeq[EvIdx[p]] ) == -90 ) - { - modelEval->BM_ITD[qp] = modelEval->elevBfVecITD[p]; - BM_idx[qp] = EvIdx[p] * model->azimDim3; - qp = qp + 1; - } - else if ( EvIdx[p] == ( model->elevDim3 - 1 ) && (int16_t) ( model->elevKSeq[EvIdx[p] - 2] ) == 90 ) - { - /* NB: -2 in if() condition above as number of knot points is numBF-2 */ - modelEval->BM_ITD[qp] = modelEval->elevBfVecITD[p]; - BM_idx[qp] = EvIdx[p] * model->azimDim3 + elev_offset; - qp = qp + 1; - } - else - { - for ( i = 0; i < num_az_idx; i++ ) - { - modelEval->BM_ITD[qp + i] = modelEval->elevBfVecITD[p] * modelEval->azimBfVecITD[i]; - BM_idx[qp + i] = EvIdx[p] * model->azimDim3 + elev_offset + AzIdx[i]; - } - qp = qp + num_az_idx; - } - } - - /* Compute ITD */ - AlphaN = model->elevDim3 * model->azimDim3 + elev_offset; - if ( model->elevKSeq[model->elevDim3 - 3] == 90 ) /* Constant azimuth basis function */ - { - AlphaN = AlphaN - ( model->azimDim3 - 1 ); - } - - /* Matrix multiplcation (row x column) */ - modelEval->itdMod = 0.0f; - for ( i = 0; i < qp; i++ ) - { - index = BM_idx[i]; - modelEval->itdMod += modelEval->BM_ITD[i] * model->W[index]; - } - - modelEval->itdMod = -(float) round_f( modelEval->itdMod * model->resamp_factor ); /* Resample and reverse sign of ITD as convention in model and renderer are opposite */ - - return; -} - - -/*-------------------------------------------------------------------* - * getStandardBSplineSampVec() - * - * Obtain a periodic sampled B Spline basis vector. - --------------------------------------------------------------------*/ - -static void getPeriodicBSplineSampVec( - float *BfVec, /* i/o: values for non-zero basis functions */ - int16_t *AzIdx, /* i/o: indices of non-zero basis functions */ - const int16_t NumBFs, /* i : the number of basis functions = third index of Bf. */ - const float t, /* i : azimuth */ - int16_t *num_az_idx, /* i : Number of azimuth indices */ - const float knot_interval, /* i : The knot interval */ - const float azimKSeq_0, /* i : Knot sequence */ - const int16_t azimSegSamples, /* i : Samples per segment */ - const float *azimBsShape, /* i : Basis shape */ - const int16_t subSampFactor /* i : Subsampling factor */ -) -{ - int16_t i, nI, d0, d; - - int16_t SegSamples = azimSegSamples / subSampFactor; - - /* index of closest sample point */ - d0 = (int16_t) round_f( ( t - azimKSeq_0 ) / ( knot_interval / SegSamples ) ); - - /* find segment */ - nI = d0 / SegSamples; - - *num_az_idx = HRTF_MODEL_BSPLINE_NUM_COEFFS; - - if ( d0 % SegSamples == 0 ) - { - ( *num_az_idx )--; /* on the knot points, the last basis function is zero */ - } - - for ( i = 0; i < *num_az_idx; i++ ) - { - d = d0 - ( i + nI - 1 ) * SegSamples; /* offset of knot_interval */ - BfVec[i] = azimBsShape[(int16_t) abs( d ) * subSampFactor]; - AzIdx[i] = ( nI + i ) % NumBFs; - } - - return; -} - - -/*-------------------------------------------------------------------* - * getStandardBSplineSampVec() - * - * Obtain a sampled B Spline basis vector. - --------------------------------------------------------------------*/ - -static void getStandardBSplineSampVec( - float *BfVec, /* i/o: values for non-zero basis functions */ - int16_t *NzIdx, /* i/o: indices of non-zero basis functions */ - int16_t *num_idx, /* i/o: number of non-zero indices */ - const int16_t NumBFs, /* i : the number of basis functions = third index of Bf */ - const float t, /* i : estimation point */ - const float *KSeq, /* i : knot sequence including multiplicities */ - const int16_t SegSamples, /* i : samples per segment */ - const int16_t *BsLen, /* i : lengths of basis shapes */ - const int16_t *BsStart, /* i : start of basis shapes */ - const float *BsShape /* i : basis shapes */ -) -{ - int16_t i, nI; - float knot_interval; - int16_t d0, d, shape_idx, start_idx; - - knot_interval = ( KSeq[NumBFs - 3] - KSeq[0] ) / ( NumBFs - 3 ); /* assuming triple knot at the first knot */ - /* index of closest sample point */ - d0 = (int16_t) round_f( ( t - KSeq[0] ) / ( knot_interval / SegSamples ) ); - /* find segment */ - nI = d0 / SegSamples; - - *num_idx = HRTF_MODEL_BSPLINE_NUM_COEFFS; - - if ( d0 % SegSamples == 0 ) - { - ( *num_idx )--; /* on the knot points, the last basis function is zero */ - } - - - for ( i = 0; i < *num_idx; i++ ) - { - start_idx = max( 0, i + nI - 3 ); - shape_idx = min( i + nI, min( 3, NumBFs - 1 - ( i + nI ) ) ); - d = d0 - start_idx * SegSamples; - - if ( i + nI > NumBFs - 4 ) /* reverse full shape */ - { - d = BsLen[shape_idx] - 1 - d; - } - else if ( d > BsLen[shape_idx] - 1 ) /* reverse half shape */ - { - d = 2 * ( BsLen[shape_idx] - 1 ) - d; - } - BfVec[i] = BsShape[BsStart[shape_idx] + (int16_t) abs( d )]; /*TT, verify if abs is needed */ - NzIdx[i] = nI + i; - } - - return; -} - - -/*-------------------------------------------------------------------* - * HRTF_model_precalc() - * - * Set precalculated parameters for HRTF model - --------------------------------------------------------------------*/ - -void HRTF_model_precalc( - ModelParams_t *model /* i/o: HRTF model parameters */ -) -{ - int16_t sec_length; - int16_t i, k, j; - float *pEL; - float *pER; - const float *pAlphaL; - const float *pAlphaR; - float tmp; - int16_t AlphaN; - - sec_length = model->K / HRTF_MODEL_N_SECTIONS; - - for ( i = 0; i < HRTF_MODEL_N_SECTIONS; i++ ) - { - model->iSecFirst[i] = i * sec_length; - } - for ( i = 0; i < HRTF_MODEL_N_SECTIONS - 1; i++ ) - { - model->iSecLast[i] = ( i + 1 ) * sec_length - 1; - } - model->iSecLast[HRTF_MODEL_N_SECTIONS - 1] = model->K - 1; /* Final section is longer if (K % nSec) > 0 */ - - maximum_s( model->azimDim3, model->elevDim3, &model->azimDim3Max ); - - if ( !model->modelROM ) - { - AlphaN = model->AlphaN; - - /* Precalculated energies for each section and each row of the alpha matrices */ - model->EL_dyn = (float *) count_malloc( HRTF_MODEL_N_SECTIONS * AlphaN * sizeof( float ) ); - model->ER_dyn = (float *) count_malloc( HRTF_MODEL_N_SECTIONS * AlphaN * sizeof( float ) ); - pEL = model->EL_dyn; - pER = model->ER_dyn; - for ( i = 0; i < HRTF_MODEL_N_SECTIONS; i++ ) - { - for ( j = 0; j < AlphaN; j++ ) /* rows of Alpha matrices */ - { - *pEL = 0.0f; - *pER = 0.0f; - - pAlphaL = &model->AlphaL[model->iSecFirst[i] * AlphaN + j]; - pAlphaR = &model->AlphaR[model->iSecFirst[i] * AlphaN + j]; - - for ( k = model->iSecFirst[i]; k < model->iSecLast[i]; k++ ) /* k within the sections */ - { - /* Energy calculation */ - tmp = *pAlphaL; - *pEL += tmp * tmp; - tmp = *pAlphaR; - *pER += tmp * tmp; - pAlphaL += AlphaN; - pAlphaR += AlphaN; - } - pEL++; - pER++; - } - } - model->EL = (const float *) model->EL_dyn; - model->ER = (const float *) model->ER_dyn; - } - - return; -} - - -/*-------------------------------------------------------------------* - * BSplineModelEvalDealloc() - * - * Deallocate BSpline HR Filter model - --------------------------------------------------------------------*/ - -void BSplineModelEvalDealloc( - ModelParams_t *model, /* i : Model parameters */ - ModelEval_t *modelEval /* i : Model evaluation structure */ -) -{ - /* Allocated in LoadBSplineBinary() */ - int16_t i; - - if ( !model->modelROM ) - { - count_free( model->elevKSeq_dyn ); - count_free( model->azim_start_idx_dyn ); - count_free( model->azimDim2_dyn ); - count_free( model->azimDim3_dyn ); - count_free( model->AlphaL_dyn ); - count_free( model->AlphaR_dyn ); - count_free( model->azimSegSamples_dyn ); - - count_free( model->azimShapeIdx_dyn ); - count_free( model->azimShapeSampFactor_dyn ); - count_free( model->elevBsShape_dyn ); - - count_free( model->EL_dyn ); - count_free( model->ER_dyn ); - - for ( i = 0; i < model->num_unique_azim_splines; i++ ) - { - count_free( model->azimBsShape_dyn[i] ); - } - count_free( model->azimBsShape_dyn ); - } - count_free( (void *) model->azimBsShape ); /* void* cast needed to please both gcc and Visual studio compilers. Deallocating const float** should be fine and gcc agrees, but Visual studio complains. */ - for ( i = 0; i < model->elevDim3; i++ ) - { - count_free( model->azimKSeq[i] ); - } - count_free( model->azimKSeq ); - if ( modelEval != NULL ) - { - count_free( modelEval->hrfModL ); - count_free( modelEval->hrfModR ); - } - - return; -} - - -/*-------------------------------------------------------------------* - * BSplineModelEvalITDDealloc() - * - * Deallocates the ITD model. - --------------------------------------------------------------------*/ - -void BSplineModelEvalITDDealloc( - ModelParamsITD_t *model /* i : Model parameters */ -) -{ - count_free( model->elevKSeq_dyn ); - count_free( model->azimKSeq_dyn ); - count_free( model->W_dyn ); - count_free( model->azimBsShape_dyn ); - count_free( model->elevBsShape_dyn ); - - return; -} - - -/*-------------------------------------------------------------------* - * SkipSmallest_ValueIndex() - * - * Returns indices to the largest values in a ValueIndex list, - * unordered (i.e. skip the n_smallest values, return the remainder). - --------------------------------------------------------------------*/ - -static void SkipSmallest_ValueIndex( - int16_t *use_inds, /* i/o: List of indices to use */ - const ValueIndex_t *VI, /* i : List of value-index items */ - const int16_t N, /* i : Length of list */ - const int16_t n_smallest /* i : Number of items to skip */ -) -{ - int16_t i, j, k, flag; - int16_t skip_inds[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - float candidate_max; /* Stores the max value in the shortlist (next to be kicked off) and its index */ - int16_t candidate_max_i; - - /* Initialise with first entries of VI */ - candidate_max = 0.0; - candidate_max_i = 0; - for ( j = 0; j < n_smallest; j++ ) - { - skip_inds[j] = j; - if ( candidate_max < VI[j].val ) - { - candidate_max = VI[j].val; - candidate_max_i = j; - } - } - - /* Look in the remainder of the list for smaller values */ - for ( i = n_smallest; i < N; i++ ) - { - for ( j = 0; j < n_smallest; j++ ) - { - if ( VI[i].val < VI[skip_inds[j]].val ) - { - /* Found a smaller value, so it goes into the list, replacing candidate_max. */ - skip_inds[candidate_max_i] = i; - candidate_max = VI[i].val; - /* Update candidate_max */ - for ( k = 0; k < n_smallest; k++ ) - { - if ( VI[skip_inds[k]].val > candidate_max ) - { - candidate_max = VI[skip_inds[k]].val; - candidate_max_i = k; - } - } - break; - } - } - } - - /* Build the list of indices that will not be skipped */ - k = 0; - for ( j = 0; j < N; j++ ) - { - flag = 1; - for ( i = 0; i < n_smallest; i++ ) - { - if ( skip_inds[i] == j ) - { - flag = 0; - break; - } - } - if ( flag ) - { - use_inds[k] = j; - k++; - } - } - - return; -} - - -#ifdef TDREND_HRTF_TABLE_METHODS -/*-------------------------------------------------------------------* - * GreatCircleAngleDeg() - * - * Returns the great-circle angle between two (azimuth, elevation) - * pairs - --------------------------------------------------------------------*/ - -/*! r: Angle between the two points on the sphere, degrees */ -static float GreatCircleAngleDeg( - float Az1, /* i : Azimuth angle, degrees, point 1 */ - float El1, /* i : Elevation angle, degrees, point 1 */ - float Az2, /* i : Azimuth angle, degrees, point 2 */ - float El2 /* i : Elevation angle, degrees, point 2 */ -) -{ - return acosf( sinf( El1 * PI_OVER_180 ) * sinf( El2 * PI_OVER_180 ) + - cosf( El1 * PI_OVER_180 ) * cosf( El2 * PI_OVER_180 ) * - cosf( fabsf( Az1 - Az2 ) * PI_OVER_180 ) ) * - PI_OVER_180; -} -#endif diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c new file mode 100644 index 0000000000000000000000000000000000000000..f1c1fc04f207070edf6ba1652ee35d1fa5fe3c77 --- /dev/null +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -0,0 +1,80 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include +#include "ivas_rom_com.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*---------------------------------------------------------------------* + * ivas_td_binaural_open() + * + * Open and initialize TD Object binaural renderer + *---------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + return ivas_td_binaural_open_unwrap( &st_ivas->hHrtfTD, st_ivas->hDecoderConfig->output_Fs, st_ivas->nchan_transport, st_ivas->ivas_format, + st_ivas->transport_config, st_ivas->hRenderConfig->directivity, st_ivas->hTransSetup, &st_ivas->hBinRendererTd, &st_ivas->binaural_latency_ns ); +} + + +/*---------------------------------------------------------------------* + * ivas_td_binaural_renderer() + * + * Receives the current frames for the object streams, updates metadata + * and renders the current frame. + *---------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ + const int16_t output_frame /* i : output frame length */ +) +{ + return ivas_td_binaural_renderer_unwrap( + st_ivas->hReverb, + st_ivas->transport_config, + st_ivas->hBinRendererTd, st_ivas->nchan_transport, LFE_CHANNEL, st_ivas->ivas_format, + st_ivas->hIsmMetaData, st_ivas->hDecoderConfig->Opt_Headrotation, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Quaternions : NULL, + ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->Pos : NULL, output, output_frame ); +} diff --git a/lib_dec/ivas_objectRenderer_sfx.c b/lib_dec/ivas_objectRenderer_sfx.c deleted file mode 100644 index 57b2d52c8005de64984d2fe2a00b3f0a06a44398..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_objectRenderer_sfx.c +++ /dev/null @@ -1,1447 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include -#include "ivas_prot.h" -#include "ivas_rom_dec.h" -#include "prot.h" -#include "wmops.h" - - -/*---------------------------------------------------------------------* - * Local constants - *---------------------------------------------------------------------*/ - -/* Sinc constants */ -#define SFX_SPAT_BIN_SINC_M 5 -#define SFX_SPAT_BIN_NUM_SUBSAMPLES_BITS 6 -#define SFX_SPAT_BIN_NUM_SUBSAMPLES ( 1 << SFX_SPAT_BIN_NUM_SUBSAMPLES_BITS ) - -/*---------------------------------------------------------------------* - * Local function prototypes - *---------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_SetParamsInitializeOn( SFX_SpatBin_t *SfxSpatBin_p, const SFX_SpatBin_Params_t *NewParam_p, const int32_t output_Fs ); -static void TDREND_SFX_SpatBin_SetParamsInitializeOff( SFX_SpatBin_t *SfxSpatBin_p, const SFX_SpatBin_Params_t *NewParam_p, const int32_t output_Fs ); -static void TDREND_SFX_SpatBin_SetParamsOn( SFX_SpatBin_t *SfxSpatBin_p, const SFX_SpatBin_Params_t *NewParam_p, const int32_t output_Fs ); -static void TDREND_SFX_SpatBin_SetParamsOff( SFX_SpatBin_t *const SfxSpatBin_p, const int32_t output_Fs ); -static void TDREND_SFX_SpatBin_Execute( SFX_SpatBin_t *SfxSpatBin_p, const float *InBuffer_p, -#ifdef DEBUGGING - const int16_t NoOfInputSamples, -#endif - const int16_t NoOfRequestedOutputSamples, - float *LeftOutBuffer_p, - float *RightOutBuffer_p, - int16_t *NoOfUsedInputSamples_p, - int16_t *NoOfDeliveredOutputSamples_p, - const int32_t output_Fs ); -static void TDREND_FirFilterRev( float *OutputFrame_p, float *FirFilterRev_p, const int16_t FirFilterLength, float *InputFrame_p, const int16_t NumOfSamples ); -#ifdef TDREND_HRTF_TABLE_METHODS -static void TDREND_FirFilterRevInterp( float *OutputFrame_p, float *FirFilterRev_p, const int16_t FirFilterLength, float *InputFrame_p, const int16_t NumOfSamples, float *FilterStored ); -#endif -static ivas_error TDREND_SFX_SpatBin_Clear( SFX_SpatBin_t *SfxSpatBin_p, const int32_t output_Fs ); - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_Resampling() - * - * Resamples input data with a given resampling factor and returns the - * resampled data. - * - --------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_Resampling( - const float *const InputBuffer_p, /* i : The input buffer with audio samples. */ - const int16_t NoOfInputSamples, /* i : Length of input buffer */ - float *const ResampleOutBuffer_p, /* o : Resampled output */ - const int16_t NoOfResampledSamples, /* i : Length of resampled output */ - float *const OldBuffer_p, /* i/o: Samples from previous input buffer (in case of buffer surplus) */ - int16_t *const NoOfOldBufferSamples_p, /* i/o: Length of OldBuffer_p */ - const float Alpha, /* i : Resampling factor */ - float *const Tf_p /* i/o: Old fractional time value / updated time value 0.0 <= Tf < 1.0 */ -) -{ - int16_t i, k, n, n0; - float AlphaInv; - float T; - int16_t nt, snc0, SubsamplesSteps; - const float *SamplePointer_p, *SincPointer_p; - float Temp; - int16_t NoOfSamplesToCopy, MaximumIndInOldBuffer, Ind; - - T = *Tf_p; - - /* The inverse of the resampling factor */ - AlphaInv = 1 / Alpha; - - /* Check how many input samples we have */ - if ( NoOfInputSamples < 2 * SFX_SPAT_BIN_SINC_M ) - { - NoOfSamplesToCopy = NoOfInputSamples; - MaximumIndInOldBuffer = *NoOfOldBufferSamples_p - ( 2 * SFX_SPAT_BIN_SINC_M - NoOfInputSamples ); - } - else - { - NoOfSamplesToCopy = 2 * SFX_SPAT_BIN_SINC_M; - MaximumIndInOldBuffer = *NoOfOldBufferSamples_p; - } - - /* 1. Append min(2M,N_input) samples from input buffer to old buffer */ - for ( i = 0; i < NoOfSamplesToCopy; i++ ) - { - OldBuffer_p[*NoOfOldBufferSamples_p + i] = InputBuffer_p[i]; - } - - /* 2. Resampling */ - nt = 0; - n0 = SFX_SPAT_BIN_SINC_M - 1; - k = 0; - if ( Alpha <= 1.0 ) - { - /* 2.1 Resample (without scaling) old buffer */ - while ( nt <= MaximumIndInOldBuffer ) - { - /* Calculate the sinc-index for the center value of the sinc */ - snc0 = (int16_t) ( ( T + EPSILON - nt ) * SFX_SPAT_BIN_NUM_SUBSAMPLES + 0.5 ); - - /* The convolution of the sinc and the data */ - SamplePointer_p = &OldBuffer_p[n0 + nt - ( SFX_SPAT_BIN_SINC_M - 1 )]; - SincPointer_p = &SincTable[snc0 - SFX_SPAT_BIN_NUM_SUBSAMPLES * ( -( SFX_SPAT_BIN_SINC_M - 1 ) )]; - - Temp = *SamplePointer_p * *SincPointer_p; - for ( i = -( SFX_SPAT_BIN_SINC_M - 2 ); i <= 0; i++ ) - { - SamplePointer_p++; - SincPointer_p -= SFX_SPAT_BIN_NUM_SUBSAMPLES; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - - SamplePointer_p++; - SincPointer_p = &SincTable[SFX_SPAT_BIN_NUM_SUBSAMPLES - snc0]; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - for ( i = 2; i <= SFX_SPAT_BIN_SINC_M; i++ ) - { - SamplePointer_p++; - SincPointer_p += SFX_SPAT_BIN_NUM_SUBSAMPLES; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - - ResampleOutBuffer_p[k] = Temp; - - /* Update the time index */ - T = T + Alpha; - /* Update the time index for the old buffer data */ - nt = (int16_t) ( T + EPSILON ); - /* Update the resampled buffer index */ - k++; - - /* Make sure we don't process too many samples. This check is needed for the cases */ - /* when all resampled samples are obtained from the old buffer. */ - if ( k >= NoOfResampledSamples ) - { - /* We have processed enough data. Jump out of the while-loop! */ - break; - } - } - - /* 2.2 Resample (without scaling) input buffer */ - n0 = ( SFX_SPAT_BIN_SINC_M - 1 ) - *NoOfOldBufferSamples_p; - for ( n = k; n < NoOfResampledSamples; n++ ) - { - /* Calculate the sinc-index for the center value of the sinc */ - snc0 = (int16_t) ( ( T + EPSILON - nt ) * SFX_SPAT_BIN_NUM_SUBSAMPLES + 0.5 ); - - /* The convolution of the sinc and the data */ - SamplePointer_p = &InputBuffer_p[n0 + nt - ( SFX_SPAT_BIN_SINC_M - 1 )]; - SincPointer_p = &SincTable[snc0 - SFX_SPAT_BIN_NUM_SUBSAMPLES * ( -( SFX_SPAT_BIN_SINC_M - 1 ) )]; - - Temp = *SamplePointer_p * *SincPointer_p; - for ( i = -( SFX_SPAT_BIN_SINC_M - 2 ); i <= 0; i++ ) - { - SamplePointer_p++; - SincPointer_p -= SFX_SPAT_BIN_NUM_SUBSAMPLES; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - - SamplePointer_p++; - SincPointer_p = &SincTable[SFX_SPAT_BIN_NUM_SUBSAMPLES - snc0]; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - for ( i = 2; i <= SFX_SPAT_BIN_SINC_M; i++ ) - { - SamplePointer_p++; - SincPointer_p += SFX_SPAT_BIN_NUM_SUBSAMPLES; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - ResampleOutBuffer_p[n] = Temp; - - /* Update the time index */ - T = T + Alpha; - /* Update the time index for the input buffer data */ - nt = (int16_t) ( T + EPSILON ); - } - } - else - { - /* Calculate the constant step length in subsamples for the sinc */ - SubsamplesSteps = (int16_t) ( AlphaInv * SFX_SPAT_BIN_NUM_SUBSAMPLES ); - - /* 2.3 Resample (with scaling) old buffer */ - while ( nt <= MaximumIndInOldBuffer ) - { - /* Calculate the sinc-index for the center value of the sinc */ - snc0 = (int16_t) ( ( T + EPSILON - nt ) * SubsamplesSteps + 0.5f ); - - /* The convolution of the sinc and the data */ - - SamplePointer_p = &OldBuffer_p[n0 + nt - ( SFX_SPAT_BIN_SINC_M - 1 )]; - SincPointer_p = &SincTable[snc0 - SubsamplesSteps * ( -( SFX_SPAT_BIN_SINC_M - 1 ) )]; - - Temp = *SamplePointer_p * *SincPointer_p; - for ( i = -( SFX_SPAT_BIN_SINC_M - 2 ); i <= 0; i++ ) - { - SamplePointer_p++; - SincPointer_p -= SubsamplesSteps; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - - SamplePointer_p++; - SincPointer_p = &SincTable[SubsamplesSteps - snc0]; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - for ( i = 2; i <= SFX_SPAT_BIN_SINC_M; i++ ) - { - SamplePointer_p++; - SincPointer_p += SubsamplesSteps; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - /* Multiply by the inverse of the resampling factor */ - Temp = Temp * AlphaInv; - ResampleOutBuffer_p[k] = Temp; - - /* Update the time index */ - T = T + Alpha; - /* Update the time index for the input buffer data */ - nt = (int16_t) ( T + EPSILON ); - /* Update the resampled buffer index */ - k++; - - /* Make sure we don't process too many samples. This check is needed for the cases */ - /* when all resampled samples are obtained from the old buffer. */ - if ( k >= NoOfResampledSamples ) - { - /* We have processed enough data. Jump out of the while-loop! */ - break; - } - } - - /* 2.4 Resample (with scaling) input buffer */ - n0 = ( SFX_SPAT_BIN_SINC_M - 1 ) - *NoOfOldBufferSamples_p; - for ( n = k; n < NoOfResampledSamples; n++ ) - { - /* Calculate the sinc-index for the center value of the sinc */ - snc0 = (int16_t) ( ( T + EPSILON - nt ) * SubsamplesSteps + 0.5 ); - - /* The convolution of the sinc and the data */ - - SamplePointer_p = &InputBuffer_p[n0 + nt - ( SFX_SPAT_BIN_SINC_M - 1 )]; - SincPointer_p = &SincTable[snc0 - SubsamplesSteps * ( -( SFX_SPAT_BIN_SINC_M - 1 ) )]; - - Temp = *SamplePointer_p * *SincPointer_p; - for ( i = -( SFX_SPAT_BIN_SINC_M - 2 ); i <= 0; i++ ) - { - SamplePointer_p++; - SincPointer_p -= SubsamplesSteps; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - - SamplePointer_p++; - SincPointer_p = &SincTable[SubsamplesSteps - snc0]; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - for ( i = 2; i <= SFX_SPAT_BIN_SINC_M; i++ ) - { - SamplePointer_p++; - SincPointer_p += SubsamplesSteps; - Temp = Temp + *SamplePointer_p * *SincPointer_p; - } - /* Multiply by the inverse of the resampling factor */ - Temp = Temp * AlphaInv; - ResampleOutBuffer_p[n] = Temp; - - /* Update the time index */ - T = T + Alpha; - /* Update the time index for the input buffer data */ - nt = (int16_t) ( T + EPSILON ); - } - } - - /* 3. Update old buffer */ - Ind = (int16_t) ( n0 + nt - ( SFX_SPAT_BIN_SINC_M - 1 ) ); - if ( Ind < 0 ) - { - /* Must save some samples from the old buffer */ - for ( i = 0; i < -Ind; i++ ) - { - OldBuffer_p[i] = OldBuffer_p[i + *NoOfOldBufferSamples_p + Ind]; - } - /* Copy the input samples */ - for ( i = 0; i < NoOfInputSamples; i++ ) - { - OldBuffer_p[i - Ind] = InputBuffer_p[i]; - } - *NoOfOldBufferSamples_p = NoOfInputSamples - Ind; - } - else - { - *NoOfOldBufferSamples_p = NoOfInputSamples - (int16_t) ( n0 + nt - ( SFX_SPAT_BIN_SINC_M - 1 ) ); - - SamplePointer_p = &InputBuffer_p[n0 + nt - ( SFX_SPAT_BIN_SINC_M - 1 )]; - for ( i = 0; i < *NoOfOldBufferSamples_p; i++ ) - { - OldBuffer_p[i] = *( SamplePointer_p + i ); - } - } - - /* 4. Update Tf_p */ - *Tf_p = T - nt; - /* Due to the EPSILON factor and rounding problems t_new may be a little negative, ~ -10^-7. This should in theory not be possible so we need to */ - /* make sure that Tf_p is greater than or equal to 0. This problem is not present for fix-code, though. */ - if ( *Tf_p < 0 ) - { - *Tf_p = 0; - } - - return; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_SetParams() - * - * Updates the ITD increment, HR-filters increments - * and volumes increments that are used by SFX_SPAT_BIN_UpdateParams(). - * - --------------------------------------------------------------------*/ - -/*! r: TD Renderer result code. */ -ivas_error TDREND_SFX_SpatBin_SetParams( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct to be updated */ - const SFX_SpatBin_Params_t *NewParam_p, /* i : New parameters struct */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - if ( NewParam_p->Reset == TRUE ) - { - /* Calling TDREND_SFX_SpatBin_Clear will clear buffers and sets SfxSpatBin_p->InitializeParams = TRUE, which forces all */ - /* rendering parameters to be set directly without any transition period. */ - TDREND_SFX_SpatBin_Clear( SfxSpatBin_p, output_Fs ); - } - - if ( NewParam_p->TurnOn == TRUE ) - { - /* Turn on the effect if it is not already on. */ - if ( SfxSpatBin_p->InitializeParams == TRUE ) - { - TDREND_SFX_SpatBin_SetParamsInitializeOn( SfxSpatBin_p, NewParam_p, output_Fs ); - } - else - { - TDREND_SFX_SpatBin_SetParamsOn( SfxSpatBin_p, NewParam_p, output_Fs ); - } - - SfxSpatBin_p->OpMode = SFX_TRANSIENT; - } - else - { - /* Turn off the effect if it is not already off. */ - if ( SfxSpatBin_p->InitializeParams == TRUE ) - { - TDREND_SFX_SpatBin_SetParamsInitializeOff( SfxSpatBin_p, NewParam_p, output_Fs ); - } - else - { - /* Turn off the effect */ - - TDREND_SFX_SpatBin_SetParamsOff( SfxSpatBin_p, output_Fs ); - } - - SfxSpatBin_p->OpMode = SFX_OFF; - } - - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_SetParamsInitializeOn() - * - * Initialize spatial parameters and turn the effect on - * - --------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_SetParamsInitializeOn( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const SFX_SpatBin_Params_t *NewParam_p, /* i : New parameters struct */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - int16_t i; - float ItdAbs; - float *LeftFilter_p, *RightFilter_p, *LeftFilterIncr_p, *RightFilterIncr_p; - int16_t mem_size; - - SfxSpatBin_p->InitializeParams = FALSE; - /* The first parameter update */ - SfxSpatBin_p->FirstUpdate = TRUE; - SfxSpatBin_p->TargetTime = 0; - - SfxSpatBin_p->ItdIncrForResampling = 0.0; - - /* Copy the HR-filters */ - SfxSpatBin_p->FilterLength = NewParam_p->FilterLength; - - mem_size = (int16_t) SfxSpatBin_p->FilterLength * sizeof( float ); - LeftFilter_p = (float *) count_malloc( mem_size ); - RightFilter_p = (float *) count_malloc( mem_size ); - LeftFilterIncr_p = (float *) count_malloc( mem_size ); - RightFilterIncr_p = (float *) count_malloc( mem_size ); - - SfxSpatBin_p->LeftFilter_p = LeftFilter_p; - SfxSpatBin_p->RightFilter_p = RightFilter_p; - SfxSpatBin_p->LeftFilterIncr_p = LeftFilterIncr_p; - SfxSpatBin_p->RightFilterIncr_p = RightFilterIncr_p; - - for ( i = 0; i < SfxSpatBin_p->FilterLength; i++ ) - { - *LeftFilter_p++ = NewParam_p->LeftVolume * ( NewParam_p->LeftFilter_p[i] ); - *RightFilter_p++ = NewParam_p->RightVolume * ( NewParam_p->RightFilter_p[i] ); - - /* Set initial increments to 0 */ - *LeftFilterIncr_p++ = 0.0; - *RightFilterIncr_p++ = 0.0; - } - - SfxSpatBin_p->TotNoOfOutputSamples = 0; - - switch ( output_Fs ) - { - case 16000: - i = 0; - break; - case 32000: - i = 1; - break; - case 48000: - i = 2; - break; - } - - /* Initialize ITD */ - if ( NewParam_p->Itd > 0.0 ) - { - SfxSpatBin_p->NoOfLeftOldBufferSamples = SFX_SPAT_BIN_SINC_M - 1 + TDREND_MaxITD[i] - (int16_t) floor( NewParam_p->Itd ); - SfxSpatBin_p->Left_Tf = ( NewParam_p->Itd ) - floorf( NewParam_p->Itd ); - SfxSpatBin_p->NoOfRightOldBufferSamples = SFX_SPAT_BIN_SINC_M - 1 + TDREND_MaxITD[i]; - } - else - { - ItdAbs = -NewParam_p->Itd; - SfxSpatBin_p->NoOfLeftOldBufferSamples = SFX_SPAT_BIN_SINC_M - 1 + TDREND_MaxITD[i] + (int16_t) ceil( ItdAbs ); - SfxSpatBin_p->Left_Tf = ceilf( ItdAbs ) - ( ItdAbs ); - SfxSpatBin_p->NoOfRightOldBufferSamples = SFX_SPAT_BIN_SINC_M - 1 + TDREND_MaxITD[i]; - } - - return; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_SetParamsInitializeOff() - * - * Initialize spatial parameters and turn the effect off - * - --------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_SetParamsInitializeOff( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const SFX_SpatBin_Params_t *NewParam_p, /* i : New parameters struct */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - int16_t i; - float *LeftFilter_p, *RightFilter_p, *LeftFilterIncr_p, *RightFilterIncr_p; - int16_t mem_size; - - SfxSpatBin_p->InitializeParams = FALSE; - /* The first parameter update */ - SfxSpatBin_p->FirstUpdate = TRUE; - SfxSpatBin_p->TargetTime = 0; - SfxSpatBin_p->ItdIncrForResampling = 0.0; - - /* Set the HR-filters */ - SfxSpatBin_p->FilterLength = NewParam_p->FilterLength; - - mem_size = (int16_t) SfxSpatBin_p->FilterLength * sizeof( float ); - LeftFilter_p = (float *) count_malloc( mem_size ); - RightFilter_p = (float *) count_malloc( mem_size ); - LeftFilterIncr_p = (float *) count_malloc( mem_size ); - RightFilterIncr_p = (float *) count_malloc( mem_size ); - - SfxSpatBin_p->LeftFilter_p = LeftFilter_p; - SfxSpatBin_p->RightFilter_p = RightFilter_p; - SfxSpatBin_p->LeftFilterIncr_p = LeftFilterIncr_p; - SfxSpatBin_p->RightFilterIncr_p = RightFilterIncr_p; - - *LeftFilter_p++ = 0.5; - *RightFilter_p++ = 0.5; - /* Set initial increments to 0 */ - *LeftFilterIncr_p++ = 0.0; - *RightFilterIncr_p++ = 0.0; - - for ( i = 1; i < SfxSpatBin_p->FilterLength; i++ ) - { - *LeftFilter_p++ = 0.0; - *RightFilter_p++ = 0.0; - /* Set initial increments to 0 */ - *LeftFilterIncr_p++ = 0.0; - *RightFilterIncr_p++ = 0.0; - } - - SfxSpatBin_p->TotNoOfOutputSamples = 0; - - /* Initialize ITD to 0 */ - switch ( output_Fs ) - { - case 16000: - i = 0; - break; - case 32000: - i = 1; - break; - case 48000: - i = 2; - break; - } - SfxSpatBin_p->NoOfLeftOldBufferSamples = SFX_SPAT_BIN_SINC_M - 1 + TDREND_MaxITD[i]; - SfxSpatBin_p->NoOfRightOldBufferSamples = SFX_SPAT_BIN_SINC_M - 1 + TDREND_MaxITD[i]; - SfxSpatBin_p->Left_Tf = 0.0; - return; -} - - -/*-------------------------------------------------------------------* - * void TDREND_SFX_SpatBin_SetParamsOn() - * - * Turn the effect on - * - --------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_SetParamsOn( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const SFX_SpatBin_Params_t *NewParam_p, /* i : New parameters struct */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - int16_t i; - float *LeftFilterIncr_p, *RightFilterIncr_p; - float MaxITDIncr = TDREND_MaxITD_Incr[2]; - /* Set FirstUpdate to FALSE, which makes SFX_SPAT_BIN_UpdateParams to start */ - /* updating the parameters. */ - SfxSpatBin_p->FirstUpdate = FALSE; - - /* Update TargetTime */ - if ( SfxSpatBin_p->OpMode == SFX_OFF ) - { - /* Start turning on the effect */ - SfxSpatBin_p->TurningOnEffect = TRUE; - /* Stop turning off the effect */ - SfxSpatBin_p->TurningOffEffect = FALSE; - /* Use the transient time instead of the target time */ - SfxSpatBin_p->TargetTime = (int16_t) SfxSpatBin_p->MaxTargetTime; - } - else - { - if ( SfxSpatBin_p->TurningOnEffect == FALSE ) - { - /* The effect is already on. Use the target time. */ - SfxSpatBin_p->TargetTime = (int16_t) SfxSpatBin_p->TotNoOfOutputSamples; - } - else if ( SfxSpatBin_p->TotNoOfOutputSamples > SfxSpatBin_p->TargetTime ) - { - /* The effect has already been turned on or will be turned on now. */ - /* If SfxSpatBin_p->TargetTime > SfxSpatBin_p->TotNoOfOutputSamples then continue with SfxSpatBin_p->TargetTime. */ - SfxSpatBin_p->TargetTime = (int16_t) SfxSpatBin_p->TotNoOfOutputSamples; - SfxSpatBin_p->TurningOnEffect = FALSE; - } - } - - /* Restart the counting of output samples */ - SfxSpatBin_p->TotNoOfOutputSamples = 0; - - /* 1. Calculate the new ITD increment. Here the half ITD increment is calculated due to that */ - /* half of it should be applied on the left channel and half on the right channel. */ - /* However, since doppler is not supported anymore resampling is only applied to the left */ - /* channel so the division by 2 could now be removed. */ - if ( SfxSpatBin_p->TargetTime > 0 ) - { - SfxSpatBin_p->ItdIncrForResampling = ( NewParam_p->Itd - ( SfxSpatBin_p->NoOfRightOldBufferSamples - ( SfxSpatBin_p->NoOfLeftOldBufferSamples - SfxSpatBin_p->Left_Tf ) ) ) / SfxSpatBin_p->TargetTime / 2; - } - - switch ( output_Fs ) - { - case 16000: - MaxITDIncr = TDREND_MaxITD_Incr[0]; - break; - case 32000: - MaxITDIncr = TDREND_MaxITD_Incr[1]; - break; - case 48000: - MaxITDIncr = TDREND_MaxITD_Incr[2]; - break; - } - /* Check that ItdIncrForResampling is within limits */ - if ( SfxSpatBin_p->ItdIncrForResampling > MaxITDIncr ) - { -#ifdef DEBUGGING - printf( "ItdIncrForResampling too large: %f > %f\n", SfxSpatBin_p->ItdIncrForResampling, MaxITDIncr ); - printf( " ParamsOn : TargetTime = %5d\n", SfxSpatBin_p->TargetTime ); -#endif - SfxSpatBin_p->ItdIncrForResampling = MaxITDIncr; - } - else if ( SfxSpatBin_p->ItdIncrForResampling < ( -MaxITDIncr ) ) - { -#ifdef DEBUGGING - printf( "ItdIncrForResampling too small: %f < %f\n", SfxSpatBin_p->ItdIncrForResampling, ( -MaxITDIncr ) ); -#endif - SfxSpatBin_p->ItdIncrForResampling = ( -MaxITDIncr ); - } - - /* 2. Calculate the HR-filter increments. Includes the left and right volume. */ - LeftFilterIncr_p = SfxSpatBin_p->LeftFilterIncr_p; - RightFilterIncr_p = SfxSpatBin_p->RightFilterIncr_p; - - for ( i = 0; i < SfxSpatBin_p->FilterLength; i++ ) - { - *LeftFilterIncr_p++ = ( NewParam_p->LeftFilter_p[i] * NewParam_p->LeftVolume - SfxSpatBin_p->LeftFilter_p[i] ) / SfxSpatBin_p->TargetTime; - *RightFilterIncr_p++ = ( NewParam_p->RightFilter_p[i] * NewParam_p->RightVolume - SfxSpatBin_p->RightFilter_p[i] ) / SfxSpatBin_p->TargetTime; - } - - return; -} - - -/*-------------------------------------------------------------------* - * void TDREND_SFX_SpatBin_SetParamsOff() - * - * Turn the effect off - --------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_SetParamsOff( - SFX_SpatBin_t *const SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - int16_t i; - float *LeftFilterIncr_p, *RightFilterIncr_p; - - int16_t MaxITD = TDREND_MaxITD[2]; - float MaxITDIncr = TDREND_MaxITD_Incr[2]; - switch ( output_Fs ) - { - case 16000: - MaxITD = TDREND_MaxITD[0]; - MaxITDIncr = TDREND_MaxITD_Incr[0]; - break; - case 32000: - MaxITD = TDREND_MaxITD[1]; - MaxITDIncr = TDREND_MaxITD_Incr[1]; - break; - case 48000: - MaxITD = TDREND_MaxITD[2]; - MaxITDIncr = TDREND_MaxITD_Incr[2]; - break; - } - - if ( SfxSpatBin_p->OpMode == SFX_TRANSIENT ) - { - /* The number of samples after which the ITD and HR-filters should have been reset. */ - SfxSpatBin_p->TransientTime = (int16_t) SfxSpatBin_p->MaxTargetTime; - } - - /* Set FirstUpdate to FALSE, which makes SFX_SPAT_BIN_UpdateParams to start updating the parameters. */ - SfxSpatBin_p->FirstUpdate = FALSE; - - /* Update TargetTime */ - if ( SfxSpatBin_p->OpMode == SFX_TRANSIENT ) - { - /* Start turning off the effect */ - SfxSpatBin_p->TurningOffEffect = TRUE; - /* Stop turning on the effect */ - SfxSpatBin_p->TurningOnEffect = FALSE; - /* Use the transient time instead of the target time */ - SfxSpatBin_p->TargetTime = (int16_t) SfxSpatBin_p->MaxTargetTime; - } - else - { - if ( SfxSpatBin_p->TurningOffEffect == FALSE ) - { - /* The effect is already off. Use the target time. */ - SfxSpatBin_p->TargetTime = (int16_t) SfxSpatBin_p->TotNoOfOutputSamples; - } - else if ( SfxSpatBin_p->TotNoOfOutputSamples > SfxSpatBin_p->TargetTime ) - { - /* The effect has already been turned off or will be turned off now. */ - /* If SfxSpatBin_p->TargetTime > SfxSpatBin_p->TotNoOfOutputSamples then continue */ - /* with SfxSpatBin_p->TargetTime. */ - SfxSpatBin_p->TargetTime = (int16_t) SfxSpatBin_p->TotNoOfOutputSamples; - } - } - - /* Restart the counting of output samples */ - SfxSpatBin_p->TotNoOfOutputSamples = 0; - - /* 1. Calculate the new ITD increment. Here the half ITD increment is calculated due to that */ - /* half of it should be applied on the left channel and half on the right channel. */ - /* if (SfxSpatBin_p->TurnedOn == FALSE) */ - if ( SfxSpatBin_p->OpMode == SFX_OFF ) - { - /* The effect has already been turned off */ - SfxSpatBin_p->ItdIncrForResampling = ( 0.0f - ( SfxSpatBin_p->NoOfRightOldBufferSamples - - ( SfxSpatBin_p->NoOfLeftOldBufferSamples - SfxSpatBin_p->Left_Tf ) ) ) / - SfxSpatBin_p->TargetTime / 2.0f; - - /* Check that ItdIncrForResampling is within limits */ - if ( SfxSpatBin_p->ItdIncrForResampling > MaxITDIncr ) - { -#ifdef DEBUGGING - printf( "ItdIncrForResampling too large: %f > %f\n", SfxSpatBin_p->ItdIncrForResampling, MaxITDIncr ); - printf( " ParamsOff : TargetTime = %5d\n", SfxSpatBin_p->TargetTime ); -#endif - SfxSpatBin_p->ItdIncrForResampling = MaxITDIncr; - } - else if ( SfxSpatBin_p->ItdIncrForResampling < ( -MaxITDIncr ) ) - { -#ifdef DEBUGGING - printf( "ItdIncrForResampling too small: %f < %f\n", SfxSpatBin_p->ItdIncrForResampling, ( -MaxITDIncr ) ); -#endif - SfxSpatBin_p->ItdIncrForResampling = ( -MaxITDIncr ); - } - } - else /*if (SfxSpatBin_p->TurnedOn == TRUE && NewParam_p->TurnOn == FALSE) */ - { - /* The effect is about to be turned off */ - SfxSpatBin_p->ItdIncrForResampling = ( 0.0f - ( SfxSpatBin_p->NoOfRightOldBufferSamples - - ( SfxSpatBin_p->NoOfLeftOldBufferSamples - SfxSpatBin_p->Left_Tf ) ) ) / - SfxSpatBin_p->TransientTime / 2.0f; - - /* Check that ItdIncrForResampling is within limits */ - if ( SfxSpatBin_p->ItdIncrForResampling > MaxITDIncr ) - { -#ifdef DEBUGGING - printf( "ItdIncrForResampling too large: %f > %f\n", SfxSpatBin_p->ItdIncrForResampling, MaxITDIncr ); - printf( " ParamsOff : TransientTime = %5d\n", SfxSpatBin_p->TransientTime ); -#endif - SfxSpatBin_p->ItdIncrForResampling = MaxITD; - } - else if ( SfxSpatBin_p->ItdIncrForResampling < ( -MaxITDIncr ) ) - { -#ifdef DEBUGGING - printf( "ItdIncrForResampling too small: %f < %f\n", SfxSpatBin_p->ItdIncrForResampling, ( -MaxITDIncr ) ); -#endif - SfxSpatBin_p->ItdIncrForResampling = ( -MaxITDIncr ); - } - - /* 2. Calculate the HR-filter increments. Includes the left and right volume. */ - LeftFilterIncr_p = SfxSpatBin_p->LeftFilterIncr_p; - RightFilterIncr_p = SfxSpatBin_p->RightFilterIncr_p; - - *LeftFilterIncr_p++ = ( 0.5f - SfxSpatBin_p->LeftFilter_p[0] ) / SfxSpatBin_p->TransientTime; - *RightFilterIncr_p++ = ( 0.5f - SfxSpatBin_p->RightFilter_p[0] ) / SfxSpatBin_p->TransientTime; - - for ( i = 1; i < SfxSpatBin_p->FilterLength; i++ ) - { - *LeftFilterIncr_p++ = ( 0.0f - SfxSpatBin_p->LeftFilter_p[i] ) / SfxSpatBin_p->TransientTime; - *RightFilterIncr_p++ = ( 0.0f - SfxSpatBin_p->RightFilter_p[i] ) / SfxSpatBin_p->TransientTime; - } - } - - return; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_UpdateParams() - * - * Updates the ITD, HR-filters and volumes, - * which are to be used when processing the next data - * block. - * - --------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_UpdateParams( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const int32_t NoOfOutputSamples /* i : Number of output samples */ -) -{ - int16_t i; - float *LeftFilter_p, *RightFilter_p, *LeftFilterIncr_p, *RightFilterIncr_p; - - LeftFilter_p = SfxSpatBin_p->LeftFilter_p; - RightFilter_p = SfxSpatBin_p->RightFilter_p; - LeftFilterIncr_p = SfxSpatBin_p->LeftFilterIncr_p; - RightFilterIncr_p = SfxSpatBin_p->RightFilterIncr_p; - - /* 1. Update the total number of output samples that has been rendered since the */ - /* last ARM update. This value is zeroed in the SetParams function. */ - SfxSpatBin_p->TotNoOfOutputSamples = SfxSpatBin_p->TotNoOfOutputSamples + NoOfOutputSamples; - if ( SfxSpatBin_p->TotNoOfOutputSamples > SfxSpatBin_p->MaxTargetTime ) - { - /* We need to limit TotNoOfOutputSamples in order to avoid wrap around as well */ - /* as when it is used in SetParams its maximum allowed value is MaxTargetTime. */ - SfxSpatBin_p->TotNoOfOutputSamples = SfxSpatBin_p->MaxTargetTime; - } - - /* No need to update if FirstUpdate is not true. All increments are zero. */ - if ( SfxSpatBin_p->FirstUpdate == FALSE ) - { - SfxSpatBin_p->TargetTime -= (int16_t) NoOfOutputSamples; - if ( SfxSpatBin_p->TargetTime < 0 ) - { - /* This is instead of using sub with saturation in order to */ - /* avoid wrap around. */ - SfxSpatBin_p->TargetTime = -1; - } - - if ( SfxSpatBin_p->TurningOffEffect == TRUE ) - { - SfxSpatBin_p->TransientTime -= (int16_t) NoOfOutputSamples; - if ( SfxSpatBin_p->TransientTime <= 0 ) - { - /* The effect has now been turned off */ - - SfxSpatBin_p->ItdIncrForResampling = 0.0; - - /* Set the default HR-filters */ - /* - SfxSpatBin_p->LeftFilter[0] = 0.5; - SfxSpatBin_p->RightFilter[0] = 0.5; - for (i = 1; i < SfxSpatBin_p->FilterLength; i++) - { - SfxSpatBin_p->LeftFilter[i] = 0.0; - SfxSpatBin_p->RightFilter[i] = 0.0; - }*/ - - *LeftFilter_p++ = 0.5; - *RightFilter_p++ = 0.5; - for ( i = 1; i < SfxSpatBin_p->FilterLength; i++ ) - { - *LeftFilter_p++ = 0.0; - *RightFilter_p++ = 0.0; - } - - /* Put HR-filter increments to zero */ - /* - for (i = 0; i < SfxSpatBin_p->FilterLength; i++) - { - SfxSpatBin_p->LeftFilterIncr[i] = 0.0; - SfxSpatBin_p->RightFilterIncr[i] = 0.0; - }*/ - - for ( i = 0; i < SfxSpatBin_p->FilterLength; i++ ) - { - *LeftFilterIncr_p++ = 0.0; - *RightFilterIncr_p++ = 0.0; - } - - /* The effect is now off */ - SfxSpatBin_p->TurningOffEffect = FALSE; - } - } - - /* 2. Check whether increments should continue to be updated. */ - if ( SfxSpatBin_p->TargetTime < 0 ) - { - /* Put ItdIncrForResampling to zero if TargetTime<0 */ - SfxSpatBin_p->ItdIncrForResampling = 0.0; - /* The effect has been turned on if it was being turned on */ - SfxSpatBin_p->TurningOnEffect = FALSE; - } - else - { - /* 3. Update the HR-filters. */ - /* Don't update if the effect is off. */ - if ( SfxSpatBin_p->OpMode == SFX_TRANSIENT || SfxSpatBin_p->TurningOffEffect == TRUE ) - { - /* - for (i = 0; i < SfxSpatBin_p->FilterLength; i++) - { - SfxSpatBin_p->LeftFilter[i] += SfxSpatBin_p->LeftFilterIncr[i] * NoOfOutputSamples; - SfxSpatBin_p->RightFilter[i] += SfxSpatBin_p->RightFilterIncr[i] * NoOfOutputSamples; - }*/ - - for ( i = 0; i < SfxSpatBin_p->FilterLength; i++ ) - { - *LeftFilter_p++ += ( *LeftFilterIncr_p++ ) * NoOfOutputSamples; - *RightFilter_p++ += ( *RightFilterIncr_p++ ) * NoOfOutputSamples; - } - } - } - } - - return; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_Execute_Main() - * - * The main rendering function that is called from the Audio Mixer. - * - --------------------------------------------------------------------*/ - -/*! r: TD Renderer result code. */ -ivas_error TDREND_SFX_SpatBin_Execute_Main( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const float *InBuffer_p, /* i : Input buffer */ - const int16_t output_frame, /* i : frame length */ - float *LeftOutBuffer_p, /* o : Rendered left channel */ - float *RightOutBuffer_p, /* o : Rendered right channel */ - int16_t *NoOfUsedInputSamples_p, /* o : Number of input samples actually used */ - int16_t *NoOfDeliveredOutputSamples_p, /* o : Number of output samples actually rendered */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - int16_t i; - const float *InBufferPointer_p; - float *LeftOutBufferPointer_p, *RightOutBufferPointer_p; - int16_t TempNoOfRequestedOutputSamples, TempNoOfUsedInputSamples, TempNoOfDeliveredOutputSamples; - int16_t TempNoOfInputSamples; - int16_t NoOfBlocks; - - /* Make sure the blocks are not longer than 6 msec. */ - - NoOfBlocks = 1; - TempNoOfRequestedOutputSamples = output_frame; - while ( TempNoOfRequestedOutputSamples > SfxSpatBin_p->MaxBlockLength ) - { - NoOfBlocks = NoOfBlocks << 1; - /* Shift with rounding */ - TempNoOfRequestedOutputSamples = ( TempNoOfRequestedOutputSamples >> 1 ) + ( TempNoOfRequestedOutputSamples & 1 ); - } - - /* Divide the output_frame into NoOfBlocks blocks. */ - InBufferPointer_p = InBuffer_p; - LeftOutBufferPointer_p = LeftOutBuffer_p; - RightOutBufferPointer_p = RightOutBuffer_p; - *NoOfUsedInputSamples_p = 0; - *NoOfDeliveredOutputSamples_p = 0; - TempNoOfInputSamples = output_frame; - - for ( i = 0; i < NoOfBlocks; i++ ) - { - /* The effect is not being turned off or on. Normal rendering. */ - if ( SfxSpatBin_p->TargetTime < TempNoOfRequestedOutputSamples ) - { - /* Put ITD increment to zero. This prevents the ITD to become too large. */ - SfxSpatBin_p->ItdIncrForResampling = 0.0; - } - - TDREND_SFX_SpatBin_Execute( SfxSpatBin_p, InBufferPointer_p, -#ifdef DEBUGGING - TempNoOfInputSamples, -#endif - TempNoOfRequestedOutputSamples, LeftOutBufferPointer_p, RightOutBufferPointer_p, &TempNoOfUsedInputSamples, &TempNoOfDeliveredOutputSamples, output_Fs ); - - /* DSP update */ - TDREND_SFX_SpatBin_UpdateParams( SfxSpatBin_p, TempNoOfDeliveredOutputSamples ); - - /* Update the temp pointers */ - InBufferPointer_p += TempNoOfUsedInputSamples; - LeftOutBufferPointer_p += TempNoOfDeliveredOutputSamples; - RightOutBufferPointer_p += TempNoOfDeliveredOutputSamples; - - *NoOfDeliveredOutputSamples_p = *NoOfDeliveredOutputSamples_p + TempNoOfDeliveredOutputSamples; - if ( i == NoOfBlocks - 2 ) - { - /* The last block should produce the remaining number of samples */ - TempNoOfRequestedOutputSamples = output_frame - *NoOfDeliveredOutputSamples_p; - } - *NoOfUsedInputSamples_p = *NoOfUsedInputSamples_p + TempNoOfUsedInputSamples; - TempNoOfInputSamples = TempNoOfInputSamples - TempNoOfUsedInputSamples; - } - - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_Execute() - * - * Run renderer for one block - * - --------------------------------------------------------------------*/ - -static void TDREND_SFX_SpatBin_Execute( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const float *InBuffer_p, /* i : Input buffer */ -#ifdef DEBUGGING - const int16_t NoOfInputSamples, /* i : Length of input buffer */ -#endif - const int16_t NoOfRequestedOutputSamples, /* i : Length of output */ - float *LeftOutBuffer_p, /* o : Rendered left channel */ - float *RightOutBuffer_p, /* o : Rendered right channel */ - int16_t *NoOfUsedInputSamples_p, /* o : Number of input samples actually used */ - int16_t *NoOfDeliveredOutputSamples_p, /* o : Number of output samples actually rendered */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - int16_t i = 0; - int16_t NoOfInputSamplesForLeft, NoOfInputSamplesForRight; - float TotalLeftFlp; - int16_t NoOfSamplesToCopy, Ind; - - /* 1. Calculate the resampling factors for the left channel. */ - TotalLeftFlp = 1.0f + 2.0f * SfxSpatBin_p->ItdIncrForResampling; - - /* 2. Calculate the number of input samples needed for the left and right channel. */ - NoOfInputSamplesForLeft = 2 * SFX_SPAT_BIN_SINC_M - SfxSpatBin_p->NoOfLeftOldBufferSamples + - (int16_t) ( SfxSpatBin_p->Left_Tf + TotalLeftFlp * ( NoOfRequestedOutputSamples - 1 ) ); - - switch ( output_Fs ) - { - case 16000: - i = 0; - break; - case 32000: - i = 1; - break; - case 48000: - i = 2; - break; - } - NoOfInputSamplesForRight = NoOfRequestedOutputSamples + SFX_SPAT_BIN_SINC_M - 1 + TDREND_MaxITD[i] - - SfxSpatBin_p->NoOfRightOldBufferSamples; - /* Set the number of used Input samples to the maximum. */ - if ( NoOfInputSamplesForLeft > NoOfInputSamplesForRight ) - { - *NoOfUsedInputSamples_p = NoOfInputSamplesForLeft; - } - else - { - *NoOfUsedInputSamples_p = NoOfInputSamplesForRight; - } - /* Set the number of used input samples to zero if it is negative. */ - if ( *NoOfUsedInputSamples_p < 0 ) - { -#ifdef DEBUGGING - printf( "2. *NoOfUsedInputSamples_p < 0\n" ); -#endif - *NoOfUsedInputSamples_p = 0; - } - -#ifdef DEBUGGING - /* The following should never happen */ - if ( *NoOfUsedInputSamples_p > NoOfInputSamples ) - { - printf( "2. *NoOfUsedInputSamples_p > NoInputSamples %d %d \n", *NoOfUsedInputSamples_p, NoOfInputSamples ); - } -#endif - - *NoOfDeliveredOutputSamples_p = NoOfRequestedOutputSamples; - - /* 3. Resample the left channel. */ - TDREND_SFX_SpatBin_Resampling( InBuffer_p, - *NoOfUsedInputSamples_p, - &( SfxSpatBin_p->ResampledBufferLeft[SfxSpatBin_p->FilterLength - 1] ), - *NoOfDeliveredOutputSamples_p, - SfxSpatBin_p->LeftOldBuffer, - &( SfxSpatBin_p->NoOfLeftOldBufferSamples ), - TotalLeftFlp, - &( SfxSpatBin_p->Left_Tf ) ); - - /* 4. Prepare the right input buffer for the HR-filtering. */ - NoOfSamplesToCopy = SfxSpatBin_p->NoOfRightOldBufferSamples - ( SFX_SPAT_BIN_SINC_M - 1 ); - if ( NoOfSamplesToCopy > *NoOfDeliveredOutputSamples_p ) - { - NoOfSamplesToCopy = *NoOfDeliveredOutputSamples_p; - } - - for ( i = 0; i < NoOfSamplesToCopy; i++ ) - { - SfxSpatBin_p->ResampledBufferRight[SfxSpatBin_p->FilterLength - 1 + i] = - SfxSpatBin_p->RightOldBuffer[( SFX_SPAT_BIN_SINC_M - 1 ) + i]; - } - - for ( i = NoOfSamplesToCopy; i < *NoOfDeliveredOutputSamples_p; i++ ) - { - SfxSpatBin_p->ResampledBufferRight[SfxSpatBin_p->FilterLength - 1 + i] = - InBuffer_p[i - SfxSpatBin_p->NoOfRightOldBufferSamples + ( SFX_SPAT_BIN_SINC_M - 1 )]; - } - - /* 5. HR-filtering on the left and right channel. */ -#ifdef TDREND_HRTF_TABLE_METHODS - if ( SfxSpatBin_p->HrFilterInterpOn ) - { - TDREND_FirFilterRevInterp( LeftOutBuffer_p, - SfxSpatBin_p->LeftFilter_p, - SfxSpatBin_p->FilterLength, - SfxSpatBin_p->ResampledBufferLeft, - *NoOfDeliveredOutputSamples_p, - SfxSpatBin_p->LeftFilterStored ); - TDREND_FirFilterRevInterp( RightOutBuffer_p, - SfxSpatBin_p->RightFilter_p, - SfxSpatBin_p->FilterLength, - SfxSpatBin_p->ResampledBufferRight, - *NoOfDeliveredOutputSamples_p, - SfxSpatBin_p->RightFilterStored ); - } - else - { - /* First time - filter without interpolation, and set filter to use as previous. */ - TDREND_FirFilterRev( LeftOutBuffer_p, - SfxSpatBin_p->LeftFilter_p, - SfxSpatBin_p->FilterLength, - SfxSpatBin_p->ResampledBufferLeft, - *NoOfDeliveredOutputSamples_p ); - TDREND_FirFilterRev( RightOutBuffer_p, - SfxSpatBin_p->RightFilter_p, - SfxSpatBin_p->FilterLength, - SfxSpatBin_p->ResampledBufferRight, - *NoOfDeliveredOutputSamples_p ); - for ( i = 0; i < SfxSpatBin_p->FilterLength; i++ ) - { - SfxSpatBin_p->LeftFilterStored[i] = SfxSpatBin_p->LeftFilter_p[i]; - SfxSpatBin_p->RightFilterStored[i] = SfxSpatBin_p->RightFilter_p[i]; - } - } -#else - TDREND_FirFilterRev( LeftOutBuffer_p, - SfxSpatBin_p->LeftFilter_p, - SfxSpatBin_p->FilterLength, - SfxSpatBin_p->ResampledBufferLeft, - *NoOfDeliveredOutputSamples_p ); - TDREND_FirFilterRev( RightOutBuffer_p, - SfxSpatBin_p->RightFilter_p, - SfxSpatBin_p->FilterLength, - SfxSpatBin_p->ResampledBufferRight, - *NoOfDeliveredOutputSamples_p ); -#endif - - /* Store the samples needed for next block */ - Ind = *NoOfDeliveredOutputSamples_p - SfxSpatBin_p->NoOfRightOldBufferSamples; - if ( Ind < 0 ) - { - /* Must store some samples from the OldBuffer */ - for ( i = Ind; i < 0; i++ ) - { - SfxSpatBin_p->RightOldBuffer[i - Ind] = SfxSpatBin_p->RightOldBuffer[i + SfxSpatBin_p->NoOfRightOldBufferSamples]; - } - - /* Store all samples in the InputBuffer that has been used by either channel */ - for ( i = 0; i < *NoOfUsedInputSamples_p; i++ ) - { - SfxSpatBin_p->RightOldBuffer[i - Ind] = InBuffer_p[i]; - } - } - else - { - /* Store samples from the InputBuffer */ - for ( i = Ind; i < *NoOfUsedInputSamples_p; i++ ) - { - SfxSpatBin_p->RightOldBuffer[i - Ind] = InBuffer_p[i]; - } - } - - /* Update number of old samples */ - SfxSpatBin_p->NoOfRightOldBufferSamples = *NoOfUsedInputSamples_p - (int16_t) Ind; - - return; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_Initialize() - * - * Initializes the spatial parameters struct - * - --------------------------------------------------------------------*/ - -/*! r: TD Renderer result code. */ -ivas_error TDREND_SFX_SpatBin_Initialize( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const int32_t output_Fs /* i : Output sampling rate */ -) -{ - int16_t i; - - SfxSpatBin_p->OpMode = SFX_OFF; - SfxSpatBin_p->TurningOffEffect = FALSE; - SfxSpatBin_p->TurningOnEffect = FALSE; - /* Init during next SetParams-call */ - SfxSpatBin_p->InitializeParams = TRUE; - - /* Init MaxTargetTime and MaxBlockLength */ - switch ( output_Fs ) - { - case 16000: - SfxSpatBin_p->MaxTargetTime = TDREND_SRC_REND_MaxTargetTimes[0]; - SfxSpatBin_p->MaxBlockLength = TDREND_SRC_REND_MaxBlockLengths[0]; - SfxSpatBin_p->LeftOldBuffer = count_malloc( ( SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[0] ) * sizeof( float ) ); - SfxSpatBin_p->RightOldBuffer = count_malloc( ( SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[0] ) * sizeof( float ) ); - /* Fill old buffers with zeros */ - for ( i = 0; i < SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[0]; i++ ) - { - SfxSpatBin_p->LeftOldBuffer[i] = 0.0f; - SfxSpatBin_p->RightOldBuffer[i] = 0.0f; - } - break; - case 32000: - SfxSpatBin_p->MaxTargetTime = TDREND_SRC_REND_MaxTargetTimes[1]; - SfxSpatBin_p->MaxBlockLength = TDREND_SRC_REND_MaxBlockLengths[1]; - SfxSpatBin_p->LeftOldBuffer = count_malloc( ( SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[1] ) * sizeof( float ) ); - SfxSpatBin_p->RightOldBuffer = count_malloc( ( SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[1] ) * sizeof( float ) ); - /* Fill old buffers with zeros */ - for ( i = 0; i < SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[1]; i++ ) - { - SfxSpatBin_p->LeftOldBuffer[i] = 0.0f; - SfxSpatBin_p->RightOldBuffer[i] = 0.0f; - } - break; - case 48000: - SfxSpatBin_p->MaxTargetTime = TDREND_SRC_REND_MaxTargetTimes[2]; - SfxSpatBin_p->MaxBlockLength = TDREND_SRC_REND_MaxBlockLengths[2]; - SfxSpatBin_p->LeftOldBuffer = count_malloc( ( SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[2] ) * sizeof( float ) ); - SfxSpatBin_p->RightOldBuffer = count_malloc( ( SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[2] ) * sizeof( float ) ); - /* Fill old buffers with zeros */ - for ( i = 0; i < SFX_SPAT_BIN_SINC_M * 4 + 2 * TDREND_MaxITD[2]; i++ ) - { - SfxSpatBin_p->LeftOldBuffer[i] = 0.0f; - SfxSpatBin_p->RightOldBuffer[i] = 0.0f; - } - break; -#ifdef DEBUGGING - default: - IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Error: Unrecognised output_Fs in TDREND_SFX_SpatBin_Initialize()" ); -#endif - } - - /* Fill the beginning of the resampled buffers with zeros */ - for ( i = 0; i < SFX_SPAT_BIN_MAX_FILTER_LENGTH; i++ ) - { - SfxSpatBin_p->ResampledBufferLeft[i] = 0.0f; - SfxSpatBin_p->ResampledBufferRight[i] = 0.0f; - } - - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * TDREND_SFX_SpatBin_Clear() - * - * Clear spatial parameters - * - --------------------------------------------------------------------*/ - -/*! r: TD Renderer result code. */ -static ivas_error TDREND_SFX_SpatBin_Clear( - SFX_SpatBin_t *SfxSpatBin_p, /* i/o: Spatial parameters struct */ - const int32_t output_Fs /* i : Output sample rate */ -) -{ - int16_t i; - int16_t MaxITD = TDREND_MaxITD[2]; - SfxSpatBin_p->OpMode = SFX_OFF; - SfxSpatBin_p->TurningOffEffect = FALSE; - SfxSpatBin_p->TurningOnEffect = FALSE; - /* Init during next SetParams-call */ - SfxSpatBin_p->InitializeParams = TRUE; - /* Fill old buffers with zeros */ - switch ( output_Fs ) - { - case 16000: - MaxITD = TDREND_MaxITD[0]; - break; - case 32000: - MaxITD = TDREND_MaxITD[1]; - break; - case 48000: - MaxITD = TDREND_MaxITD[2]; - break; - } - for ( i = 0; i < SFX_SPAT_BIN_SINC_M * 4 + 2 * MaxITD; i++ ) - { - SfxSpatBin_p->LeftOldBuffer[i] = 0.0f; - SfxSpatBin_p->RightOldBuffer[i] = 0.0f; - } - /* Fill the beginning of the resampled buffers with zeros */ - for ( i = 0; i < SFX_SPAT_BIN_MAX_FILTER_LENGTH; i++ ) - { - SfxSpatBin_p->ResampledBufferLeft[i] = 0.0f; - SfxSpatBin_p->ResampledBufferRight[i] = 0.0f; - } - - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * TDREND_FirFilterRev() - * - * FIR filtering function with reversed filter sequence. - * The FIR filter seqeunce is reversed, i.e. - * FirFilterRev(n) = FirFilter(N-1-n) for n=0:N-1 - * The first N-1 samples of the input buffer store the last N-1 - * samples from the previous input buffer. - * - --------------------------------------------------------------------*/ - -static void TDREND_FirFilterRev( - float *OutputFrame_p, /* o : Filtered samples */ - float *FirFilterRev_p, /* i/o: Reversed FIR filter */ - const int16_t FirFilterLength, /* i : Filter length */ - float *InputFrame_p, /* i : Input samples */ - const int16_t NumOfSamples /* i : Number of input samples */ -) -{ - /* In this function we assume that the last FirFilterLength-1 samples from */ - /* the previous InputBuffer starts this new InputBuffer. */ - int16_t n, k; - int16_t FirFilterLengthMinusOne; - float Acc; - float *InputBuffer_nk_p, *InputBuffer_n_p, *FirFilterRev_k_p, *OutputBuffer_n_p; - - FirFilterLengthMinusOne = FirFilterLength - 1; - - /* 1. Filter the input buffer. NOTE: Reversed filter sequence */ - InputBuffer_n_p = InputFrame_p; - OutputBuffer_n_p = OutputFrame_p; - - for ( n = NumOfSamples; n > 0; n-- ) - { - - Acc = 0.0f; - FirFilterRev_k_p = FirFilterRev_p; - InputBuffer_nk_p = InputBuffer_n_p; - - for ( k = FirFilterLength; k > 0; k-- ) - { - Acc += *( FirFilterRev_k_p++ ) * *( InputBuffer_nk_p++ ); - } - - InputBuffer_n_p++; - *( OutputBuffer_n_p++ ) = Acc; - } - - /* 2. Copy the last FirFilterLength-1 samples of the InputFrame to the beginning of the InputFrame */ - mvr2r( InputFrame_p + NumOfSamples, InputFrame_p, FirFilterLengthMinusOne ); - - return; -} - -#ifdef TDREND_HRTF_TABLE_METHODS -/*-------------------------------------------------------------------* - * TDREND_FirFilterRevInterp() - * - * FIR filtering function with reversed filter sequence. - * The FIR filter seqeunce is reversed, i.e. - * FirFilterRev(n) = FirFilter(N-1-n) for n=0:N-1 - * The first N-1 samples of the input buffer store the last N-1 - * samples from the previous input buffer. - * - --------------------------------------------------------------------*/ - -static void TDREND_FirFilterRevInterp( - float *OutputFrame_p, /* o : Filtered samples */ - float *FirFilterRev_p, /* i/o: Reversed FIR filter */ - const int16_t FirFilterLength, /* i : Filter length */ - float *InputFrame_p, /* i : Input samples */ - const int16_t NumOfSamples, /* i : Number of input samples */ - float *FilterStored /* i/o: Old filter memory for interpolation */ -) -{ - /* In this function we assume that the last FirFilterLength-1 samples from */ - /* the previous InputBuffer starts this new InputBuffer. */ - int16_t n, k; - int16_t FirFilterLengthMinusOne; - float Acc1; - float Acc2; - - float *InputBuffer_nk_p, *InputBuffer_n_p, *FirFilterRev_k_p, *OutputBuffer_n_p; - float interpFactor, interpComplement; - float *FilterStored_n_p; - float inv_NumOfSamples; - - FirFilterLengthMinusOne = FirFilterLength - 1; - inv_NumOfSamples = 1.0f / NumOfSamples; - - /* 1. Filter the input buffer */ - /* NOTE: Reversed filter sequence */ - InputBuffer_n_p = InputFrame_p; - OutputBuffer_n_p = OutputFrame_p; - - interpFactor = 1.0f; - interpComplement = 0.0f; - for ( n = NumOfSamples; n > 0; n-- ) - { - - Acc1 = 0.0f; - Acc2 = 0.0f; - FirFilterRev_k_p = FirFilterRev_p; - FilterStored_n_p = FilterStored; - InputBuffer_nk_p = InputBuffer_n_p; - - for ( k = FirFilterLength; k > 0; k-- ) - { - Acc1 += *( FirFilterRev_k_p++ ) * *( InputBuffer_nk_p ); - Acc2 += *( FilterStored_n_p++ ) * *( InputBuffer_nk_p++ ); - } - - InputBuffer_n_p++; - *( OutputBuffer_n_p++ ) = Acc1 * interpComplement + Acc2 * interpFactor; - interpFactor -= inv_NumOfSamples; - interpComplement += inv_NumOfSamples; - } - - /* Store the old filter for interpolation next time */ - for ( k = 0; k < FirFilterLength; k++ ) - { - FilterStored[k] = FirFilterRev_p[k]; - } - - /* 2. Copy the last FirFilterLength-1 samples of the InputFrame to */ - /* the beginning of the InputFrame */ - mvr2r( InputFrame_p + NumOfSamples, InputFrame_p, FirFilterLengthMinusOne ); - - return; -} -#endif diff --git a/lib_dec/ivas_orient_trk.c b/lib_dec/ivas_orient_trk.c deleted file mode 100644 index 4754062b561520c46c0516fc1a51beb0be5c1fe0..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_orient_trk.c +++ /dev/null @@ -1,313 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include "prot.h" -#include "ivas_prot.h" -#include "ivas_cnst.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include -#include -#include "wmops.h" - - -/*------------------------------------------------------------------------------------------* - * Local constants - *------------------------------------------------------------------------------------------*/ - -#define MAX_TRACKED_ANGLE_AVG_ORIENT PI_OVER_2 -#define MAX_TRACKED_ANGLE_REF_ORIENT EVS_PI - -/* TODO relate to frame rate - assumed here 50Hz, i.e. 20ms frame length */ -#define OTR_UPDATE_RATE ( 50.0f ) /* rate of the Process() calls [Hz]; 1x per IVAS frame */ - - -/*------------------------------------------------------------------------------------------* - * Local functions - *------------------------------------------------------------------------------------------*/ - -static float ClipAngle( - const float angle, - const float min_angle, - const float max_angle ) -{ - float result = angle; - - /* wrap angle modulo 2*pi into range of [-pi, pi> radians */ - /* 'while' assumed to use comparison to 0 */ - while ( result > EVS_PI ) - { - result -= PI2; - } - /* 'while' assumed to use comparison to 0 */ - while ( result <= -EVS_PI ) - { - result += PI2; - } - - /* Next, clip angle into range */ - /* 'if' assumed to use comparison to 0 */ - if ( result < min_angle ) - { - result = min_angle; - } - else - { - /* 'if' assumed to use comparison to 0 */ - if ( result > max_angle ) - { - result = max_angle; - } - } - - return result; -} - - -/*-------------------------------------------------------------------* - * ivas_orient_trk_Init() - * - * - *-------------------------------------------------------------------*/ - -void ivas_orient_trk_Init( - ivas_orient_trk_state_t *pOTR ) -{ - /* Track relative to a reference orientation */ - pOTR->trackingType = OTR_TRACKING_REF_ORIENT; - - /* configuration parameters */ - pOTR->centerAdaptationRate = 1.0f / 30.0f; - pOTR->offCenterAdaptationRate = 1.0f / 8.0f; - pOTR->adaptationAngle = PI_OVER_2; /* Excursion angle relative to center at which maximum adaptation rate shall be applied */ - - /* initial adaptivity filter coefficient, will be auto-adapted */ - pOTR->alpha = sinf( PI2 * pOTR->offCenterAdaptationRate / OTR_UPDATE_RATE ); /* start adaptation at off-center rate = fastest rate */ - - pOTR->absYaw = 0.0f; - pOTR->absPitch = 0.0f; - pOTR->absRoll = 0.0f; - - pOTR->absAvgYaw = 0.0f; - pOTR->absAvgPitch = 0.0f; - pOTR->absAvgRoll = 0.0f; - - /* Use frontal and horiontal orientation as reference orientation, - unless/until overridden by ivas_orient_trk_SetAbsoluteOrientation() */ - pOTR->refYaw = 0.0f; - pOTR->refPitch = 0.0f; - pOTR->refRoll = 0.0f; - - pOTR->trkYaw = 0.0f; - pOTR->trkPitch = 0.0f; - pOTR->trkRoll = 0.0f; -} - - -/*-------------------------------------------------------------------* - * ivas_orient_trk_SetTrackingType() - * - * - *-------------------------------------------------------------------*/ - -ivas_error ivas_orient_trk_SetTrackingType( - ivas_orient_trk_state_t *pOTR, - OTR_TRACKING_T trackingType ) -{ - pOTR->trackingType = trackingType; - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * ivas_orient_trk_SetAbsoluteOrientation() - * - * - *-------------------------------------------------------------------*/ - -ivas_error ivas_orient_trk_SetAbsoluteOrientation( - ivas_orient_trk_state_t *pOTR, - float yaw, - float pitch, - float roll ) -{ - /* TODO implement condition checks */ - pOTR->absYaw = yaw; - pOTR->absPitch = pitch; - pOTR->absRoll = roll; - - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * ivas_orient_trk_Process() - * - * - *-------------------------------------------------------------------*/ - -ivas_error ivas_orient_trk_Process( - ivas_orient_trk_state_t *pOTR ) -{ - float yaw; - float pitch; - float roll; - - if ( pOTR->trackingType == OTR_TRACKING_AVG_ORIENT ) - { - float normalizedOrientation; - float relativeOrientationRate; - float rateRange; - float cutoffFrequency; - float alpha = pOTR->alpha; - - /* Copy absolute orientation as input to compute further on */ - yaw = pOTR->absYaw; - pitch = pOTR->absPitch; - roll = pOTR->absRoll; - - /* Compute average (low-pass filtered) absolute orientation */ - pOTR->absAvgYaw = ( 1.0f - alpha ) * pOTR->absAvgYaw + alpha * yaw; - pOTR->absAvgPitch = ( 1.0f - alpha ) * pOTR->absAvgPitch + alpha * pitch; - pOTR->absAvgRoll = ( 1.0f - alpha ) * pOTR->absAvgRoll + alpha * roll; - - /* Compute relative orientation = (absolute orientation) - (average absolute orientation) */ - yaw -= pOTR->absAvgYaw; - pitch -= pOTR->absAvgPitch; - roll -= pOTR->absAvgRoll; - - /* Clip tracked relative orientation to avoid wrap around */ - yaw = ClipAngle( yaw, -MAX_TRACKED_ANGLE_AVG_ORIENT, MAX_TRACKED_ANGLE_AVG_ORIENT ); - pitch = ClipAngle( pitch, -MAX_TRACKED_ANGLE_AVG_ORIENT, MAX_TRACKED_ANGLE_AVG_ORIENT ); - roll = ClipAngle( roll, -MAX_TRACKED_ANGLE_AVG_ORIENT, MAX_TRACKED_ANGLE_AVG_ORIENT ); - - /* Store relative orientation result as output */ - pOTR->trkYaw = yaw; - pOTR->trkPitch = pitch; - pOTR->trkRoll = roll; - - /* Reconstruct the mean absolute orientation, compensating for non-linear computation of relative orientation: - take absolute orientation and subtract the *clipped* mean relative orientation */ - pOTR->absAvgYaw = pOTR->absYaw - yaw; - pOTR->absAvgPitch = pOTR->absPitch - pitch; - pOTR->absAvgRoll = pOTR->absRoll - roll; - - /* Adapt LPF constant based on orientation excursion relative to current mean: - - low cutoff (slow adaptation) for small excursions (around center) - - high cutoff (fast adaptation) for large excursions (off-center) - */ - - normalizedOrientation = yaw * yaw; - normalizedOrientation += pitch * pitch; - normalizedOrientation += roll * roll; - - relativeOrientationRate = sqrtf( normalizedOrientation ) / pOTR->adaptationAngle; - /* 'if' assumed to perform comparison to 0 */ - if ( relativeOrientationRate > 1.0f ) - { - relativeOrientationRate = 1.0f; - } - - /* Compute range of the adaptation rate between center = lower rate and off-center = higher rate */ - rateRange = pOTR->offCenterAdaptationRate - pOTR->centerAdaptationRate; - /* 'if' assumed to perform comparison to 0 */ - if ( rateRange < 0.0f ) - { - rateRange = 0.0f; - } - - /* Compute adaptivity cutoff frequency: interpolate between minimum (center) and maximum (off-center) values */ - cutoffFrequency = pOTR->centerAdaptationRate + ( relativeOrientationRate * rateRange ); - - /* Compute filter coefficient corresponding to desired cutoff frequency */ - pOTR->alpha = sinf( 2.0f * EVS_PI * cutoffFrequency / OTR_UPDATE_RATE ); - } - else - { - /* 'if' assumed to perform comparison to 0 */ - if ( pOTR->trackingType == OTR_TRACKING_REF_ORIENT ) - { - /* Reset average orientation */ - pOTR->absAvgYaw = pOTR->absYaw; - pOTR->absAvgPitch = pOTR->absPitch; - pOTR->absAvgRoll = pOTR->absRoll; - - /* Reset adaptation filter - start adaptation at center rate */ - pOTR->alpha = sinf( 2.0f * EVS_PI * pOTR->centerAdaptationRate / OTR_UPDATE_RATE ); - - /* Copy absolute orientation as input to compute further on */ - yaw = pOTR->absYaw; - pitch = pOTR->absPitch; - roll = pOTR->absRoll; - - /* Compute relative orientation = (absolute orientation) - (reference orientation) */ - yaw -= pOTR->refYaw; - pitch -= pOTR->refPitch; - roll -= pOTR->refRoll; - - /* Clip computed relative orientation to avoid wrap around and store as output */ - pOTR->trkYaw = ClipAngle( yaw, -MAX_TRACKED_ANGLE_REF_ORIENT, MAX_TRACKED_ANGLE_REF_ORIENT ); - pOTR->trkPitch = ClipAngle( pitch, -MAX_TRACKED_ANGLE_REF_ORIENT, MAX_TRACKED_ANGLE_REF_ORIENT ); - pOTR->trkRoll = ClipAngle( roll, -MAX_TRACKED_ANGLE_REF_ORIENT, MAX_TRACKED_ANGLE_REF_ORIENT ); - } - - else - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Non-supported orientation tracking adaptation type" ); - } - } - - return IVAS_ERR_OK; -} - - -/*-------------------------------------------------------------------* - * ivas_orient_trk_GetTrackedOrientation() - * - * - *-------------------------------------------------------------------*/ - -ivas_error ivas_orient_trk_GetTrackedOrientation( - ivas_orient_trk_state_t *pOTR, - float *yaw, - float *pitch, - float *roll ) -{ - *yaw = pOTR->trkYaw; - *pitch = pOTR->trkPitch; - *roll = pOTR->trkRoll; - - return IVAS_ERR_OK; -} diff --git a/lib_dec/ivas_out_setup_conversion.c b/lib_dec/ivas_out_setup_conversion.c index c8008fa12976d821b6662e509157efa40f408623..b396fa415cd01ad0317602d5a58df9ce417d48b0 100644 --- a/lib_dec/ivas_out_setup_conversion.c +++ b/lib_dec/ivas_out_setup_conversion.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,18 +30,19 @@ *******************************************************************************************************/ -#include #include #include "options.h" #include -#include "ivas_prot.h" +#include #include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_com.h" +#include "ivas_rom_rend.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" -#include "ivas_rom_com.h" -#include "ivas_rom_dec.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* @@ -312,14 +313,12 @@ ivas_error ivas_ls_setup_conversion_open( int32_t output_Fs; int16_t nchan_out; - wmops_sub_start( "LS_Renderer" ); - output_Fs = st_ivas->hDecoderConfig->output_Fs; nchan_out = st_ivas->hDecoderConfig->nchan_out; output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); /* Allocate memory to the handle */ - if ( ( hLsSetUpConversion = (LSSETUP_CONVERSION_HANDLE) count_malloc( sizeof( LSSETUP_CONVERSION_STRUCT ) ) ) == NULL ) + if ( ( hLsSetUpConversion = (LSSETUP_CONVERSION_HANDLE) malloc( sizeof( LSSETUP_CONVERSION_STRUCT ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) ); } @@ -333,8 +332,14 @@ ivas_error ivas_ls_setup_conversion_open( hLsSetUpConversion->sfbCnt = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); for ( chIdx = 0; chIdx < outChannels; chIdx++ ) { - hLsSetUpConversion->targetEnergyPrev[chIdx] = (float *) count_malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ); - hLsSetUpConversion->dmxEnergyPrev[chIdx] = (float *) count_malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ); + if ( ( hLsSetUpConversion->targetEnergyPrev[chIdx] = (float *) malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) ); + } + if ( ( hLsSetUpConversion->dmxEnergyPrev[chIdx] = (float *) malloc( ( hLsSetUpConversion->sfbCnt ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) ); + } set_f( hLsSetUpConversion->targetEnergyPrev[chIdx], 0.0f, hLsSetUpConversion->sfbCnt ); set_f( hLsSetUpConversion->dmxEnergyPrev[chIdx], 0.0f, hLsSetUpConversion->sfbCnt ); } @@ -349,8 +354,15 @@ ivas_error ivas_ls_setup_conversion_open( inChannels = st_ivas->nchan_transport; /*Initialization of MDCT bands with TCX20 resolution */ ivas_lssetupconversion_mdct_init_bands( output_frame, TCX_20_CORE, &hLsSetUpConversion->sfbOffset[0], &hLsSetUpConversion->sfbCnt ); - hLsSetUpConversion->targetEnergyPrev[0] = (float *) count_malloc( ( MAX_SFB + 2 ) * sizeof( float ) ); - hLsSetUpConversion->dmxEnergyPrev[0] = (float *) count_malloc( ( MAX_SFB + 2 ) * sizeof( float ) ); + if ( ( hLsSetUpConversion->targetEnergyPrev[0] = (float *) malloc( ( MAX_SFB + 2 ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) ); + } + if ( ( hLsSetUpConversion->dmxEnergyPrev[0] = (float *) malloc( ( MAX_SFB + 2 ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LS configuration Conversion Handle \n" ) ); + } + for ( chIdx = 1; chIdx < MAX_CICP_CHANNELS; chIdx++ ) { hLsSetUpConversion->targetEnergyPrev[chIdx] = NULL; @@ -365,7 +377,7 @@ ivas_error ivas_ls_setup_conversion_open( for ( chIdx = 0; chIdx < inChannels; chIdx++ ) { /* Allocate memory depending on the number of output channels */ - if ( ( hLsSetUpConversion->dmxMtx[chIdx] = (float *) count_malloc( outChannels * sizeof( float ) ) ) == NULL ) + if ( ( hLsSetUpConversion->dmxMtx[chIdx] = (float *) malloc( outChannels * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for temp dmx matrix \n" ) ); } @@ -420,24 +432,24 @@ void ivas_ls_setup_conversion_close( { if ( ( *hLsSetUpConversion )->dmxMtx[idx] != NULL ) { - count_free( ( *hLsSetUpConversion )->dmxMtx[idx] ); + free( ( *hLsSetUpConversion )->dmxMtx[idx] ); ( *hLsSetUpConversion )->dmxMtx[idx] = NULL; } if ( ( *hLsSetUpConversion )->targetEnergyPrev[idx] != NULL ) { - count_free( ( *hLsSetUpConversion )->targetEnergyPrev[idx] ); + free( ( *hLsSetUpConversion )->targetEnergyPrev[idx] ); ( *hLsSetUpConversion )->targetEnergyPrev[idx] = NULL; } if ( ( *hLsSetUpConversion )->dmxEnergyPrev[idx] != NULL ) { - count_free( ( *hLsSetUpConversion )->dmxEnergyPrev[idx] ); + free( ( *hLsSetUpConversion )->dmxEnergyPrev[idx] ); ( *hLsSetUpConversion )->dmxEnergyPrev[idx] = NULL; } } - count_free( *hLsSetUpConversion ); + free( *hLsSetUpConversion ); *hLsSetUpConversion = NULL; return; @@ -462,7 +474,7 @@ void ivas_ls_setup_conversion( float dmxCoeff, tmpVal; float output_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - wmops_sub_start( "LS_Renderer" ); + push_wmops( "LS_Renderer" ); hLsSetUpConversion = st_ivas->hLsSetUpConversion; @@ -501,7 +513,7 @@ void ivas_ls_setup_conversion( mvr2r( output_tmp[chOutIdx], output[chOutIdx], output_frame ); } - wmops_sub_end(); + pop_wmops(); return; } @@ -537,7 +549,7 @@ void ivas_ls_setup_conversion_process_mdct( LSSETUP_CONVERSION_HANDLE hLsSetUpConversion; CPE_DEC_HANDLE hCPE[MCT_MAX_BLOCKS]; - wmops_sub_start( "LS_Renderer_MDCT" ); + push_wmops( "LS_Renderer_MDCT" ); /* Assign all the declared variables */ inChannels = st_ivas->nchan_transport; @@ -588,7 +600,13 @@ void ivas_ls_setup_conversion_process_mdct( { dmxCoeff = hLsSetUpConversion->dmxMtx[chInIdx][chOutIdx]; - if ( !( chInIdx == LFE_CHANNEL && st_ivas->hMCT->LFE_off ) && mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + !( chInIdx == LFE_CHANNEL && st_ivas->hMCT->LFE_off ) && +#else + chInIdx != LFE_CHANNEL && +#endif + mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE ) { /* Step 1: Compute the target energy and DMX signal (possible since we have all signals in TCX20 resolution) */ if ( dmxCoeff ) @@ -681,7 +699,13 @@ void ivas_ls_setup_conversion_process_mdct( /* Step 4: Perform equalization */ for ( chInIdx = 0; chInIdx < inChannels; chInIdx++ ) { - if ( !( chInIdx == LFE_CHANNEL && st_ivas->hMCT->LFE_off ) && mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + !( chInIdx == LFE_CHANNEL && st_ivas->hMCT->LFE_off ) && +#else + chInIdx != LFE_CHANNEL && +#endif + mct_chan_mode[chInIdx] != MCT_CHAN_MODE_IGNORE ) { if ( transform_type[chInIdx][0] == TCX_20 ) { @@ -738,7 +762,7 @@ void ivas_ls_setup_conversion_process_mdct( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -1072,8 +1096,6 @@ void ivas_ls_setup_conversion_process_mdct_param_mc( } } - wmops_sub_end(); - return; } @@ -1100,7 +1122,7 @@ void ivas_lssetupconversion_process_param_mc( float Cldfb_ImagBuffer_tmp[MAX_CICP_CHANNELS][CLDFB_NO_CHANNELS_MAX]; LSSETUP_CONVERSION_HANDLE hLsSetUpConversion; - wmops_sub_start( "LS_Renderer_Process_Param_MC" ); + push_wmops( "LS_Renderer_Process_Param_MC" ); /* inits */ inChannels = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; @@ -1203,6 +1225,6 @@ void ivas_lssetupconversion_process_param_mc( } } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_dec/ivas_output_init.c b/lib_dec/ivas_output_config.c similarity index 66% rename from lib_dec/ivas_output_init.c rename to lib_dec/ivas_output_config.c index 86dc17d1741114cc31cf37bf7a41a42c6859fd48..f522a3217d2e9fff9e0422e6dea667e4697ca3a9 100644 --- a/lib_dec/ivas_output_init.c +++ b/lib_dec/ivas_output_config.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,222 +30,16 @@ *******************************************************************************************************/ -#include #include #include "options.h" #include "ivas_cnst.h" #include "ivas_prot.h" -#include "prot.h" #include "ivas_stat_dec.h" -#include "ivas_rom_dec.h" -#include "ivas_rom_com.h" #ifdef DEBUGGING #include "debug.h" #include #endif -#include "wmops.h" - -/*-------------------------------------------------------------------------* - * audioCfg2channels() - * - * Map Audio configuration to number of channels - *-------------------------------------------------------------------------*/ - -/*! r: number of audio channels */ -int16_t audioCfg2channels( - AUDIO_CONFIG output_config /* i : output audio configuration */ -) -{ - int16_t nchan_out; - - switch ( output_config ) - { - case AUDIO_CONFIG_MONO: - nchan_out = 1; - break; - case AUDIO_CONFIG_STEREO: - nchan_out = 2; - break; - case AUDIO_CONFIG_5_1: - nchan_out = 6; - break; - case AUDIO_CONFIG_7_1: - nchan_out = 8; - break; - case AUDIO_CONFIG_5_1_2: - nchan_out = 8; - break; - case AUDIO_CONFIG_5_1_4: - nchan_out = 10; - break; - case AUDIO_CONFIG_7_1_4: - nchan_out = 12; - break; - case AUDIO_CONFIG_FOA: - nchan_out = 4; - break; - case AUDIO_CONFIG_HOA2: - nchan_out = 9; - break; - case AUDIO_CONFIG_HOA3: - nchan_out = 16; - break; - case AUDIO_CONFIG_OBA: - nchan_out = 8; - break; - case AUDIO_CONFIG_BINAURAL: - case AUDIO_CONFIG_BINAURAL_ROOM: - nchan_out = 2; - break; - case AUDIO_CONFIG_ISM1: - nchan_out = 1; - break; - case AUDIO_CONFIG_ISM2: - nchan_out = 2; - break; - case AUDIO_CONFIG_ISM3: - nchan_out = 3; - break; - case AUDIO_CONFIG_ISM4: - nchan_out = 4; - break; - default: - IVAS_ERROR( IVAS_ERR_INTERNAL, "Error: illegal output configuration\n" ); - nchan_out = -1; - break; - } - - return ( nchan_out ); -} - - -/*-------------------------------------------------------------------------* - * ivas_output_init() - * - * Initialize and configure IVAS output parameters - *-------------------------------------------------------------------------*/ - -void ivas_output_init( - IVAS_OUTPUT_SETUP *hOutSetup, /* o : IVAS output setup structure */ - const AUDIO_CONFIG output_config /* i : output audio configuration */ -) -{ - int16_t nchan_out; - - /* set general default values */ - hOutSetup->output_config = output_config; - hOutSetup->is_loudspeaker_setup = 0; - hOutSetup->is_binaural_setup = 0; - hOutSetup->ambisonics_order = -1; - hOutSetup->separateChannelEnabled = 0; - hOutSetup->separateChannelIndex = 0; - - if ( output_config == AUDIO_CONFIG_LS_CUSTOM ) - { - hOutSetup->is_loudspeaker_setup = 1; - /* set in ivas_init_decoder: */ - /* hOutSetup->ls_azimuth */ - /* hOutSetup->ls_elevation */ - /* hOutSetup->num_lfe */ - /* hOutSetup->index_lfe[0] */ - /* hOutSetup->is_planar_setup */ - } - else - { - /* Set default values for all other than custom LS setup */ - hOutSetup->ls_azimuth = NULL; - hOutSetup->ls_elevation = NULL; - hOutSetup->num_lfe = 0; - hOutSetup->index_lfe[0] = -1; - hOutSetup->is_planar_setup = 0; - - /* set output setup specific values */ - switch ( output_config ) - { - case AUDIO_CONFIG_MONO: - hOutSetup->is_loudspeaker_setup = 1; - break; - case AUDIO_CONFIG_STEREO: - hOutSetup->is_loudspeaker_setup = 1; - hOutSetup->ls_azimuth = ls_azimuth_CICP2; - hOutSetup->ls_elevation = ls_elevation_CICP2; - break; - case AUDIO_CONFIG_FOA: - hOutSetup->ambisonics_order = 1; - break; - case AUDIO_CONFIG_HOA2: - hOutSetup->ambisonics_order = 2; - break; - case AUDIO_CONFIG_HOA3: - hOutSetup->ambisonics_order = 3; - break; - case AUDIO_CONFIG_5_1: - hOutSetup->num_lfe = 1; - hOutSetup->index_lfe[0] = 3; - hOutSetup->is_loudspeaker_setup = 1; - hOutSetup->ls_azimuth = ls_azimuth_CICP6; - hOutSetup->ls_elevation = ls_elevation_CICP6; - hOutSetup->is_planar_setup = 1; - break; - case AUDIO_CONFIG_7_1: - hOutSetup->num_lfe = 1; - hOutSetup->index_lfe[0] = 3; - hOutSetup->is_loudspeaker_setup = 1; - hOutSetup->ls_azimuth = ls_azimuth_CICP12; - hOutSetup->ls_elevation = ls_elevation_CICP12; - hOutSetup->is_planar_setup = 1; - break; - case AUDIO_CONFIG_5_1_2: - hOutSetup->num_lfe = 1; - hOutSetup->index_lfe[0] = 3; - hOutSetup->is_loudspeaker_setup = 1; - hOutSetup->ls_azimuth = ls_azimuth_CICP14; - hOutSetup->ls_elevation = ls_elevation_CICP14; - hOutSetup->is_planar_setup = 0; - break; - case AUDIO_CONFIG_5_1_4: - hOutSetup->num_lfe = 1; - hOutSetup->index_lfe[0] = 3; - hOutSetup->is_loudspeaker_setup = 1; - hOutSetup->ls_azimuth = ls_azimuth_CICP16; - hOutSetup->ls_elevation = ls_elevation_CICP16; - hOutSetup->is_planar_setup = 0; - break; - case AUDIO_CONFIG_7_1_4: - hOutSetup->num_lfe = 1; - hOutSetup->index_lfe[0] = 3; - hOutSetup->is_loudspeaker_setup = 1; - hOutSetup->ls_azimuth = ls_azimuth_CICP19; - hOutSetup->ls_elevation = ls_elevation_CICP19; - hOutSetup->is_planar_setup = 0; - break; - case AUDIO_CONFIG_BINAURAL: - case AUDIO_CONFIG_BINAURAL_ROOM: - case AUDIO_CONFIG_ISM1: - case AUDIO_CONFIG_ISM2: - case AUDIO_CONFIG_ISM3: - case AUDIO_CONFIG_ISM4: - hOutSetup->is_binaural_setup = 1; - case AUDIO_CONFIG_EXTERNAL: - /* Default values are used */ - break; - default: -#ifdef DEBUGGING - /* error */ - assert( !"Error: Unknown output setup!\n" ); -#endif - return; - } - } - - if ( output_config != AUDIO_CONFIG_EXTERNAL && output_config != AUDIO_CONFIG_LS_CUSTOM ) - { - nchan_out = audioCfg2channels( output_config ); - hOutSetup->nchan_out_woLFE = nchan_out - hOutSetup->num_lfe; - } - - return; -} +#include "wmc_auto.h" /*-------------------------------------------------------------------------* @@ -263,6 +57,8 @@ void ivas_renderer_select( AUDIO_CONFIG output_config; AUDIO_CONFIG transport_config; + int16_t nchan_internal; + renderer_type = &( st_ivas->renderer_type ); internal_config = &( st_ivas->intern_config ); output_config = st_ivas->hDecoderConfig->output_config; @@ -352,21 +148,24 @@ void ivas_renderer_select( { *renderer_type = RENDERER_BINAURAL_FASTCONV_ROOM; } + if ( st_ivas->hDecoderConfig->Opt_Headrotation ) { - if ( st_ivas->nchan_transport == 2 ) + + nchan_internal = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order ); + if ( nchan_internal == 2 ) { st_ivas->hHeadTrackData->shd_rot_max_order = 1; } - else if ( st_ivas->nchan_transport == 4 || st_ivas->nchan_transport == 3 ) + else if ( nchan_internal == 4 || nchan_internal == 3 ) { st_ivas->hHeadTrackData->shd_rot_max_order = 0; } - else if ( st_ivas->nchan_transport == 6 || st_ivas->nchan_transport == 5 ) + else if ( nchan_internal == 6 || nchan_internal == 5 ) { st_ivas->hHeadTrackData->shd_rot_max_order = 2; } - else if ( st_ivas->nchan_transport == 8 || st_ivas->nchan_transport == 7 ) + else if ( nchan_internal == 8 || nchan_internal == 7 ) { st_ivas->hHeadTrackData->shd_rot_max_order = 3; } @@ -437,7 +236,7 @@ void ivas_renderer_select( { *renderer_type = RENDERER_BINAURAL_FASTCONV_ROOM; } -#if defined( DEBUGGING ) +#ifdef DEBUGGING if ( st_ivas->hRenderConfig->renderer_type_override == RENDER_TYPE_OVERRIDE_CREND ) { *renderer_type = RENDERER_BINAURAL_MIXER_CONV_ROOM; @@ -504,17 +303,36 @@ void ivas_renderer_select( *renderer_type = RENDERER_DIRAC; if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR && +#ifdef SBA2MONO + ( output_config != AUDIO_CONFIG_5_1 && output_config != AUDIO_CONFIG_5_1_2 && output_config != AUDIO_CONFIG_5_1_4 && output_config != AUDIO_CONFIG_7_1 && output_config != AUDIO_CONFIG_7_1_4 && output_config != AUDIO_CONFIG_LS_CUSTOM && output_config != AUDIO_CONFIG_MONO && output_config != AUDIO_CONFIG_STEREO ) ) +#else ( output_config != AUDIO_CONFIG_5_1 && output_config != AUDIO_CONFIG_5_1_2 && output_config != AUDIO_CONFIG_5_1_4 && output_config != AUDIO_CONFIG_7_1 && output_config != AUDIO_CONFIG_7_1_4 && output_config != AUDIO_CONFIG_LS_CUSTOM ) ) +#endif { - *internal_config = AUDIO_CONFIG_HOA3; + if ( output_config == AUDIO_CONFIG_HOA2 || output_config == AUDIO_CONFIG_FOA ) + { + *internal_config = output_config; + } + else if ( output_config == AUDIO_CONFIG_MONO || output_config == AUDIO_CONFIG_STEREO ) + { + *internal_config = AUDIO_CONFIG_FOA; + } + else + { + *internal_config = AUDIO_CONFIG_HOA3; + } st_ivas->renderer_type = RENDERER_SBA_LINEAR_DEC; } else if ( ( st_ivas->ivas_format == MASA_FORMAT && output_config == AUDIO_CONFIG_MONO && st_ivas->nchan_transport == 1 ) || +#ifdef SBA2MONO + ( st_ivas->ivas_format == SBA_FORMAT && ( output_config == AUDIO_CONFIG_STEREO || output_config == AUDIO_CONFIG_MONO ) ) ) +#else ( st_ivas->ivas_format == SBA_FORMAT && output_config == AUDIO_CONFIG_STEREO && st_ivas->nchan_transport == 1 ) ) +#endif { *renderer_type = RENDERER_DISABLE; } - else if ( ( st_ivas->ivas_format == MASA_FORMAT && output_config == AUDIO_CONFIG_MONO && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_4k4 ) ) + else if ( ( st_ivas->ivas_format == MASA_FORMAT && output_config == AUDIO_CONFIG_MONO && st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE && st_ivas->hDecoderConfig->ivas_total_brate > IVAS_SID_5k2 ) ) { *renderer_type = RENDERER_DISABLE; } @@ -526,26 +344,9 @@ void ivas_renderer_select( { *renderer_type = RENDERER_DISABLE; } - else if ( st_ivas->ivas_format == SBA_FORMAT ) + else if ( st_ivas->ivas_format == SBA_FORMAT && output_config == AUDIO_CONFIG_MONO ) { - int16_t nchan_max; - - if ( ( output_config == AUDIO_CONFIG_MONO ) || ( output_config == AUDIO_CONFIG_STEREO ) ) - { - nchan_max = st_ivas->hDecoderConfig->nchan_out; - } - else if ( st_ivas->hOutSetup.ambisonics_order > 0 ) - { - nchan_max = ivas_sba_get_nchan( st_ivas->hOutSetup.ambisonics_order, st_ivas->sba_planar ); - } - else - { - nchan_max = ivas_sba_get_nchan( 3, st_ivas->sba_planar ); - } - if ( st_ivas->nchan_transport >= nchan_max ) - { - *renderer_type = RENDERER_SBA_LINEAR_DEC; - } + *renderer_type = RENDERER_SBA_LINEAR_DEC; } } else if ( st_ivas->ivas_format == MC_FORMAT ) diff --git a/lib_dec/ivas_pca_dec.c b/lib_dec/ivas_pca_dec.c index 8ceb6ae0e57a96fb074dfad1a939be2144fd259f..4444a73cee237441b406bcbce27b60ff7adff240 100644 --- a/lib_dec/ivas_pca_dec.c +++ b/lib_dec/ivas_pca_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #endif #include #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -62,25 +62,6 @@ static int32_t ivas_bitstream_read_int32( } -void ivas_pca_read_bits( - Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ - PCA_DEC_STATE *hPCA ) -{ - /*first bit in the PCA payload (first bit after 3 header bits) signals bypass/active*/ - hPCA->pca_bypass = get_next_indice( st0, 1 ); - - if ( hPCA->pca_bypass == PCA_MODE_INACTIVE ) - { - return; - } - - hPCA->index[0] = ivas_bitstream_read_int32( st0, IVAS_PCA_QBITS - 1 ); - hPCA->index[1] = ivas_bitstream_read_int32( st0, IVAS_PCA_QBITS ); - - return; -} - - static void pca_dec_reset_dquat( float *ql, float *qr ) @@ -126,6 +107,7 @@ static void pca_inv_transform_sub( { buffer_data[k] = transformed_data[k][j + start]; } + for ( k = 0; k < n_channels; k++ ) { temp = 0.0f; @@ -158,14 +140,16 @@ static void pca_dec_inv_transform( pca_interp_preproc( hPCA->prev_ql, hPCA->prev_qr, ql, qr, IVAS_PCA_N_SLOTS, ql_interp, qr_interp ); slot_len = (int16_t) ( n_samples / IVAS_PCA_N_SLOTS ); + for ( j = 0; j < IVAS_PCA_N_SLOTS; j++ ) { /* convert from double quaternion to 4D matrix */ dquat2mat( &ql_interp[4 * j], &qr_interp[4 * j], &hPCA->mem_eigVec_interp[16 * j + IVAS_PCA_DELAY_CMP * 16] ); - pca_inv_transform_sub( &hPCA->mem_eigVec_interp[16 * j], decoded_data, - slot_len * j, slot_len, n_channels ); + pca_inv_transform_sub( &hPCA->mem_eigVec_interp[16 * j], decoded_data, slot_len * j, slot_len, n_channels ); } + + return; } @@ -183,12 +167,12 @@ static void pca_dec_update_dquat( /*------------------------------------------------------------------------- - * init_pca_dec() + * ivas_pca_dec_init() * - * initialize PCA decoder + * Initialize PCA decoder *------------------------------------------------------------------------*/ -void init_pca_dec( +void ivas_pca_dec_init( PCA_DEC_STATE *hPCA /* i/o: PCA decoder structure */ ) { @@ -202,6 +186,31 @@ void init_pca_dec( } +/*------------------------------------------------------------------------- + * ivas_pca_read_bits() + * + * Decode PCA indexes + *------------------------------------------------------------------------*/ + +void ivas_pca_read_bits( + Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ + PCA_DEC_STATE *hPCA ) +{ + /*first bit in the PCA payload (first bit after 3 header bits) signals bypass/active*/ + hPCA->pca_bypass = get_next_indice( st0, 1 ); + + if ( hPCA->pca_bypass == PCA_MODE_INACTIVE ) + { + return; + } + + hPCA->index[0] = ivas_bitstream_read_int32( st0, IVAS_PCA_QBITS - 1 ); + hPCA->index[1] = ivas_bitstream_read_int32( st0, IVAS_PCA_QBITS ); + + return; +} + + /*------------------------------------------------------------------------- * ivas_pca_dec() * @@ -218,8 +227,9 @@ void ivas_pca_dec( float pcm_out[][L_FRAME48k] /* o : output audio channels */ ) { - float ql[4], qr[4]; + float ql[IVAS_PCA_INTERP], qr[IVAS_PCA_INTERP]; int16_t pca_bypass; + mvr2r( &hPCA->mem_eigVec_interp[IVAS_PCA_N_SLOTS * 16], hPCA->mem_eigVec_interp, IVAS_PCA_DELAY_CMP * 16 ); /* @@@TODO: check how ivas_total_brate is set if bfi == 1 */ // VE: and what happens in DTX where "ivas_total_brate" can be close to zero? diff --git a/lib_dec/ivas_post_proc.c b/lib_dec/ivas_post_proc.c index a295a8b2a285ca96e3eea6d52382c601b7991924..da00426116a6db051a81bcc68a4994b85b15ebe6 100644 --- a/lib_dec/ivas_post_proc.c +++ b/lib_dec/ivas_post_proc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- * ivas_post_proc() @@ -81,7 +81,7 @@ void ivas_post_proc( output_Fs = sts[0]->output_Fs; - if ( ( sts[n]->element_mode != IVAS_CPE_DFT && !sba_dirac_stereo_flag ) || ( sts[n]->element_mode == IVAS_CPE_DFT && hCPE->nchan_out == 1 && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) ) + if ( ( sts[n]->element_mode != IVAS_CPE_DFT && !( sba_dirac_stereo_flag && sts[n]->element_mode != IVAS_CPE_MDCT ) ) || ( sts[n]->element_mode == IVAS_CPE_DFT && hCPE->nchan_out == 1 && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) ) { if ( sts[n]->hTcxLtpDec != NULL ) { @@ -102,6 +102,11 @@ void ivas_post_proc( mvr2r( sts[n]->prev_synth_buffer, sts[n]->hTcxDec->FBTCXdelayBuf, 0 ); mvr2r( sts[n]->delay_buf_out, sts[n]->hTcxDec->FBTCXdelayBuf + 0, delay_comp ); } + else if ( sba_dirac_stereo_flag && sts[n]->element_mode == IVAS_CPE_MDCT ) + { + int16_t numZeros = (int16_t) ( NS2SA( output_Fs, N_ZERO_MDCT_NS ) ); + mvr2r( sts[n]->hHQ_core->old_out + numZeros, sts[n]->hTcxDec->FBTCXdelayBuf, delay_comp ); + } tcx_ltp_post( sts[n], hTcxLtpDec, sts[n]->core, output_frame, NS2SA( output_Fs, ACELP_LOOK_NS ) + delay_comp, synth, sts[n]->hTcxDec->FBTCXdelayBuf ); } @@ -478,7 +483,7 @@ void stereo_dft_dec_core_switching( mvr2r( output, pAp_input, st->L_frame ); } - if ( st->last_core == ACELP_CORE && !( st->prev_bfi == 1 && st->last_core == ACELP_CORE && st->last_con_tcx == 1 ) ) /* ACELP -> TCX/HQ-Core */ + if ( st->last_core == ACELP_CORE && !( st->prev_bfi == 1 && st->last_core == ACELP_CORE && st->last_con_tcx == 1 ) && !st->tcxonly ) /* ACELP -> TCX/HQ-Core */ { mvr2r( tcx_core_buf, tmp_fade, ap_fade_len ); for ( i = 0; i < ap_fade_len; i++ ) diff --git a/lib_dec/ivas_qmetadata_dec.c b/lib_dec/ivas_qmetadata_dec.c index e8b3ca4d7c4bbd36a629428a0d1784e37913f902..9c6597fdcb881530b248d221ae0934ea93b22882 100644 --- a/lib_dec/ivas_qmetadata_dec.c +++ b/lib_dec/ivas_qmetadata_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" /*-----------------------------------------------------------------------* @@ -406,11 +406,11 @@ int16_t ivas_qmetadata_dec_decode( } } - /* Read 2D signalling*/ + /* Read 2D signaling*/ q_direction->not_in_2D = bitstream[( *index )--]; signal_bits = 1; - /* Read EC signalling */ + /* Read EC signaling */ ec_flag = 0; if ( total_bits_1dir + bits_sur_coherence <= hQMetaData->qmetadata_max_bit_req ) { @@ -513,7 +513,7 @@ int16_t ivas_qmetadata_dec_decode( int16_t dummy; ec_flag = 2; - if ( hQMetaData->is_masa_type_format == 0 ) + if ( hQMetaData->is_masa_ivas_format == 0 ) { reduce_bits = bits_dir_raw - ( total_bits_1dir - bits_diff - bits_coherence - signal_bits ); ind_order[0] = -1; @@ -721,17 +721,20 @@ int16_t ivas_qmetadata_dec_sid_decode( { if ( sba_mode == SBA_MODE_SPAR ) { - metadata_sid_bits = (int16_t) ( IVAS_SID_5k - SID_2k40 ) / FRAMES_PER_SEC - ( SPAR_DTX_BANDS * 18 ) - 1; /* -1 for inactive mode header bit*/ + /* TODO: still use old sid frame size to keep bitexactness */ + metadata_sid_bits = (int16_t) ( 5000 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - ( SPAR_DTX_BANDS * 18 ) - 1; /* -1 for inactive mode header bit*/ } else { /* keep 13.2 and 16.4 sid bitrate as 4.4 kbps for now*/ - metadata_sid_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + /* TODO: still use old sid frame size to keep bitexactness */ + metadata_sid_bits = ( 4400 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; } } else { - metadata_sid_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + /* TODO: still use old sid frame size to keep bitexactness */ + metadata_sid_bits = ( 4400 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; } start_index = *index; @@ -765,7 +768,7 @@ int16_t ivas_qmetadata_dec_sid_decode( nblocks = q_direction->cfg.nblocks; /* only 1 block transmitted but up to 4 blocks re-generated */ start_band = 0; /* start from band 0 */ - /* Read 2D signalling*/ + /* Read 2D signaling*/ if ( sba_mode != SBA_MODE_SPAR ) { q_direction->not_in_2D = bitstream[( *index )--]; @@ -850,6 +853,18 @@ int16_t ivas_qmetadata_dec_sid_decode( } } } + /* TODO: temporary hack to keep BE */ + if ( ivas_format == SBA_FORMAT ) + { + if ( sba_mode != SBA_MODE_SPAR ) + { + metadata_sid_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - 1; /* -1 for spar/dirac indicator*/ + } + } + else + { + metadata_sid_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + } /*Read filling bits*/ while ( start_index - *index < metadata_sid_bits ) @@ -860,9 +875,9 @@ int16_t ivas_qmetadata_dec_sid_decode( #ifdef DEBUG_MODE_QMETADATA fprintf( pF, "frame %d: all %d ", frame, start_index - *index ); - fprintf( pF_azi, "frame %d sid: ", frame ); - fprintf( pF_ele, "frame %d sid: ", frame ); - fprintf( pF_ratio, "frame %d sid: ", frame ); + fprintf( pF_azi, "frame %d SID: ", frame ); + fprintf( pF_ele, "frame %d SID: ", frame ); + fprintf( pF_ratio, "frame %d SID: ", frame ); for ( b = start_band; b < nbands; b++ ) { @@ -3099,7 +3114,7 @@ int16_t read_surround_coherence( float error_ratio_surr; int16_t idx_ER[MASA_MAXIMUM_CODING_SUBBANDS]; int16_t bits_sur_coherence, bits_GR; - int16_t j, d, k; + int16_t j, d, k, idx; uint16_t byteBuffer; uint16_t idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; IVAS_QDIRECTION *q_direction; @@ -3118,7 +3133,8 @@ int16_t read_surround_coherence( if ( hQMetaData->no_directions == 2 ) { d += hQMetaData->twoDirBands[j]; - error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[0] - q_direction[1].band_data[max( d - 1, 0 )].energy_ratio[0] * hQMetaData->twoDirBands[j]; + idx = max( d - 1, 0 ); + error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[0] - q_direction[1].band_data[idx].energy_ratio[0] * hQMetaData->twoDirBands[j]; } else { diff --git a/lib_dec/ivas_qspherical_dec.c b/lib_dec/ivas_qspherical_dec.c index c37d03e5a983c0f41312c90d693311c5678fb2f0..c56217326aac1c743585e35add5386c69977c4ba 100644 --- a/lib_dec/ivas_qspherical_dec.c +++ b/lib_dec/ivas_qspherical_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,7 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include "ivas_stat_dec.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" diff --git a/lib_dec/ivas_range_uni_dec.c b/lib_dec/ivas_range_uni_dec.c index de9b3a4559adf745e081a6f4d3030ed102adbf35..db0fbddeabd1d3f83ef2df5908f290383289bac9 100644 --- a/lib_dec/ivas_range_uni_dec.c +++ b/lib_dec/ivas_range_uni_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUGGING #include "debug.h" #endif diff --git a/lib_dec/ivas_reverb.c b/lib_dec/ivas_reverb.c deleted file mode 100644 index 12dec394dfe24a1715842de7833bae71e43082b4..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_reverb.c +++ /dev/null @@ -1,1513 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include "prot.h" -#include "ivas_prot.h" -#include "ivas_cnst.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "math.h" -#include "ivas_rom_dec.h" -#include -#include "wmops.h" - - -/*------------------------------------------------------------------------------------------* - * Local constants - *------------------------------------------------------------------------------------------*/ - -#define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */ - /* should be a divisor of the frame length at any sampling rate and an even number*/ -#define USE_SR_INDEPENDENT_FIT_FOR_T60_FILTERS /* use sample-rate independent ref. frequency ranges for T60 filters */ -#define FFT_FILTER_WND_FLAT_REGION ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */ -#define FFT_FILTER_WND_TRANS_REGION ( 0.15f ) /* transition (1->0) length of FFT filter window, in proportion to overlap */ -#ifdef USE_SR_INDEPENDENT_FIT_FOR_T60_FILTERS -#define REF_LF_MIN ( 100.0f ) -#define REF_LF_MAX ( 250.0f ) -#define REF_HF_MIN ( 5000.0f ) -#define REF_HF_MAX ( 7950.0f ) -#define LF_BIAS ( 0.5f ) -#else /* settings for previous version of improved 1st order filter design, somewhat dependent on the sampling rate */ -#define REF_LF_MIN ( 0.0f ) -#define REF_LF_MAX ( 200.0f ) -#define REF_HF_MIN ( 6000.0f ) -#define REF_HF_MAX ( 48000.0f ) -#define LF_BIAS ( 0.75f ) -#endif - -#define DEFAULT_SRC_DIST ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */ - -#define IVAS_REVERB_FFT_SIZE_48K ( 512 ) -#define IVAS_REVERB_FFT_SIZE_32K ( 512 ) -#define IVAS_REVERB_FFT_SIZE_16K ( 256 ) -#define IVAS_REVERB_FFT_N_SUBBLOCKS_48K ( 1 ) -#define IVAS_REVERB_FFT_N_SUBBLOCKS_32K ( 1 ) -#define IVAS_REVERB_FFT_N_SUBBLOCKS_16K ( 1 ) - -const int16_t init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 }; -const int16_t default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 }; -const int16_t default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 }; -const int16_t default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 }; - -#define MAX_NR_OUTPUTS 2 -#define MAX_T60_FILTER_ORDER 12 - - -/*------------------------------------------------------------------------------------------* - * Local Struct definition - *------------------------------------------------------------------------------------------*/ - -typedef struct ivas_reverb_params_t -{ - float dmx_gain; /* (for now, fullband) gain to apply at input to realize diffuse-to-source energy ratio */ - int16_t pre_delay; /* Delay of the FDC reverb, first peak after pre_delay samples. Note that */ - /* there may be non-zero samples earlier due to the filters being */ - /* linear-phase. */ - int16_t nr_loops; /* Number of feedback loops (= L) */ - int16_t pLoop_delays[IVAS_REV_MAX_NR_BRANCHES]; /* Delay for each feedback loop in samples. */ - float pLoop_feedback_matrix[IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_NR_BRANCHES]; /* Feedback [L][L] matrix that mixes the signals of the loops. */ - int16_t nr_outputs; /* Nr of signals extracted from the loops (= S). */ - /* Currently this is fixed to 2. */ - float pLoop_extract_matrix[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES]; /* Mix [S][L] matrix from feedback loops to outputs. */ - /* In Matlab: [S x L] - Currently S=2, later may be more than 2 for speaker playback. */ - int16_t t60_is_iir; /* Flag indicates whether T60 filters are IIR. */ - int16_t t60_filter_order; /* Filter order (length of vector) */ - float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * ( MAX_T60_FILTER_ORDER + 1 )]; /* Filters [][] in feedback loops, controlling T60. */ - /* In Matlab: IIR: [(2 * L) x ( + 1)] (odd: b-vector, even: a-vector) */ - /* In Matlab: FIR: [L x ] */ - float *pFc; /* Center frequencies for FFT filter design */ - float *pRt60; /* RT60 values at these frequencies */ - float *pDsr; /* DSR values at these frequencies */ - int16_t do_corr_filter; /* Flag indicating whether correlation filters should be used. */ - /* Correlation only supported and needed for binaural playback (i.e. */ - /* when nr_outputs != 2 correlation filtering is never supported). */ - -} ivas_reverb_params_t; - -typedef struct ivas_reverb_sizes_t -{ - int16_t max_nr_loops; /* 4, 6, 8 or 16 */ - int16_t max_nr_outputs; /* 2, ... */ - int16_t max_t60_filter_order; /* 1..128 */ - -} ivas_reverb_sizes_t; - - -/*------------------------------------------------------------------------------------------* - * Static functions declarations - *------------------------------------------------------------------------------------------*/ - -static ivas_error design_iir2_1st_order( ivas_reverb_params_t *pParams, const uint16_t nrLoop, const uint16_t nrFrequencies, float frequencies[], float amplitudes[], const int32_t output_Fs ); - - -/*-----------------------------------------------------------------------------------------* - * Function set_max_sizes() - * - * - *-----------------------------------------------------------------------------------------*/ - -static void set_max_sizes( - ivas_reverb_sizes_t *pRevSizes ) -{ - pRevSizes->max_nr_loops = IVAS_REV_MAX_NR_BRANCHES; - pRevSizes->max_nr_outputs = MAX_NR_OUTPUTS; - pRevSizes->max_t60_filter_order = MAX_T60_FILTER_ORDER; - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function compute_feedback_matrix() - * - * Compute the N x N matrix for the mixing the N feedback loop outputs into the N inputs again - *-----------------------------------------------------------------------------------------*/ - -static ivas_error compute_feedback_matrix( - float *pFeedbackMatrix, - const int16_t n ) -{ - float u, v; - int16_t i, j, x; - - if ( n == 6 ) - { - /* special case (there is no 6 x 6 Hadamard matrix in set R) */ - u = -1.0f / 3; - v = 1.0f + u; - for ( i = 0; i < n; i++ ) - { - for ( j = 0; j < n; j++ ) - { - if ( i == j ) - { - pFeedbackMatrix[i * n + j] = v; - } - else - { - pFeedbackMatrix[i * n + j] = u; - } - } - } - } - else - { - if ( !( n == 4 || n == 8 || n == 16 ) ) - { - return IVAS_ERR_INTERNAL; /* n must be 4, 6, 8 or 16, else ERROR */ - } - u = 1.0f / sqrtf( n ); - if ( n == 4 ) - { - u = -u; - } - - pFeedbackMatrix[0] = u; - for ( x = 1; x < n; x += x ) - { - for ( i = 0; i < x; i++ ) - { - for ( j = 0; j < x; j++ ) - { - pFeedbackMatrix[( i + x ) * n + j] = pFeedbackMatrix[i * n + j]; - pFeedbackMatrix[i * n + j + x] = pFeedbackMatrix[i * n + j]; - pFeedbackMatrix[( i + x ) * n + j + x] = -pFeedbackMatrix[i * n + j]; - } - } - } - - if ( n == 4 ) - { - /* special case */ - for ( j = 12; j < 16; j++ ) - { - pFeedbackMatrix[j] = -pFeedbackMatrix[j]; - } - } - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function compute_2_out_extract_matrix() - * - * Compute the N x 2 matrix for mixing the N Jot feedback loops to 2 outputs - *-----------------------------------------------------------------------------------------*/ - -static void compute_2_out_extract_matrix( - float *pExtractMatrix, - const int16_t n ) -{ - float ff; - int16_t i; - - ff = 1.0; - for ( i = 0; i < n; i++ ) - { - pExtractMatrix[i] = 1.0; - pExtractMatrix[i + n] = ff; - ff = -ff; - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_base_config() - * - * Set all jot reverb parameters that are independent of the input reverb configuration - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_base_config( - ivas_reverb_params_t *pParams, - const int32_t output_Fs, - ivas_reverb_sizes_t *pRevSizes ) -{ - ivas_error error; - int16_t loop; - const int16_t *selected_loop_delay = NULL; - - if ( pParams == NULL ) - { - return IVAS_ERR_INTERNAL; - } - - if ( pRevSizes == NULL ) - { - return IVAS_ERR_INTERNAL; - } - - /* TODO: values below could be reconsidered, and/or be made variable */ - pParams->pre_delay = 0; - pParams->nr_outputs = 2; - - if ( pParams->nr_outputs > pRevSizes->max_nr_outputs ) - { - return IVAS_ERR_INTERNAL; - } - - pParams->nr_loops = IVAS_REV_MAX_NR_BRANCHES; - - if ( pParams->nr_loops > pRevSizes->max_nr_loops ) - { - return IVAS_ERR_INTERNAL; - } - - /* set loop delays to default */ - if ( output_Fs == 48000 ) - { - selected_loop_delay = default_loop_delay_48k; - } - else if ( output_Fs == 32000 ) - { - selected_loop_delay = default_loop_delay_32k; - } - else if ( output_Fs == 16000 ) - { - selected_loop_delay = default_loop_delay_16k; - } - - for ( loop = 0; loop < pParams->nr_loops; loop++ ) - { - pParams->pLoop_delays[loop] = selected_loop_delay[loop]; - } - - /* set feedback and output matrices */ - if ( ( error = compute_feedback_matrix( pParams->pLoop_feedback_matrix, pParams->nr_loops ) ) != IVAS_ERR_OK ) - { - return error; - } - - compute_2_out_extract_matrix( pParams->pLoop_extract_matrix, pParams->nr_loops ); - - /* pre-set the various filters; they will be set later based on reverb configuration */ - pParams->t60_is_iir = TRUE; - pParams->t60_filter_order = 1; /* set to 1 in base config. */ - - if ( pParams->t60_filter_order > pRevSizes->max_t60_filter_order ) - { - return IVAS_ERR_INTERNAL; - } - - if ( pParams->nr_outputs == 2 ) - { - pParams->do_corr_filter = 1; - } - else - { - pParams->do_corr_filter = 0; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_dmx_gain() - * - * Computes and sets the downmix gain - *-----------------------------------------------------------------------------------------*/ - -static void calc_dmx_gain( - ivas_reverb_params_t *pParams ) -{ - const float dist = DEFAULT_SRC_DIST; - - pParams->dmx_gain = sqrtf( 4.0f * EVS_PI * dist * dist / 0.001f ); - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_predelay() - * - * Calculate the predelay, taking shortest jot loop delay into account - *-----------------------------------------------------------------------------------------*/ - -static void calc_predelay( - ivas_reverb_params_t *pParams, - float acoustic_predelay_sec, - const int32_t output_Fs ) -{ - int16_t i, predelay; - int16_t fbdelay; - int16_t output_frame; - - fbdelay = (int16_t) pParams->pLoop_delays[0]; - predelay = (int16_t) round( acoustic_predelay_sec * output_Fs ); - output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); - - fbdelay = pParams->pLoop_delays[0]; - for ( i = 1; i < pParams->nr_loops; i++ ) - { - if ( fbdelay > pParams->pLoop_delays[i] ) - { - fbdelay = pParams->pLoop_delays[i]; - } - } - predelay -= fbdelay; - - if ( predelay < 0 ) - { - predelay = 0; - } - - if ( output_frame < predelay ) - { - predelay = output_frame; - } - - pParams->pre_delay = predelay; - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function compute_t60_coeffs() - * - * Calculate Jot reverb's T60 filter coefficients - *-----------------------------------------------------------------------------------------*/ - -static ivas_error compute_t60_coeffs( - ivas_reverb_params_t *pParams, - int16_t nr_fc_fft_filter, - const int32_t output_Fs ) -{ - int16_t i, j, tf_T60_len; - int16_t len; - float c, d; - float H_b[RV_LENGTH_NR_FC]; - float norm_f[RV_LENGTH_NR_FC]; - float inv_hfs; - float *targetT60 = pParams->pRt60; - float *freqT60 = pParams->pFc; - ivas_error error; - - error = IVAS_ERR_OK; - tf_T60_len = nr_fc_fft_filter; - - - if ( pParams->t60_is_iir == FALSE ) - { - return IVAS_ERR_INTERNAL; /* only IIR supported */ - } - - /* normalize pFrequencies: 0 .. 1/2 output_Fs --> 0.0 .. 1.0 */ - inv_hfs = 2.0f / (float) output_Fs; - for ( i = 0; i < tf_T60_len; i++ ) - { - norm_f[i] = freqT60[i] * inv_hfs; - } - - c = -3.0f * LOG_10 / (float) output_Fs; /* 10^(x) == exp(LOG_10 * x) */ - - for ( j = 0; j < pParams->nr_loops; j++ ) - { - d = c * pParams->pLoop_delays[j]; - for ( i = 0; i < tf_T60_len; i++ ) - { - H_b[i] = expf( d / targetT60[i] ); /* using EXP(x) instead of 10^x */ - } - - if ( ( error = design_iir2_1st_order( pParams, j, tf_T60_len, norm_f, H_b, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - len = pParams->t60_filter_order + 1; - for ( i = 0; i < pParams->nr_loops; i++ ) - { - if ( pParams->pT60_filter_coeff[( i + i ) * len] < 0.0f ) - { - for ( j = 0; j < len; j++ ) - { - pParams->pT60_filter_coeff[( i + i ) * len + j] *= ( -1.0f ); - } - } - } - - // TODO: Compute proper (group) Delay from IIR filter - len = ( pParams->t60_filter_order + 1 ) >> 1; /* == floor( (order+1) / 2) */ - for ( i = 0; i < pParams->nr_loops; i++ ) - { - pParams->pLoop_delays[i] -= len; - } - - return error; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_low_shelf_first_order_filter() - * - * Calculate 1st order low shelf filter - *-----------------------------------------------------------------------------------------*/ - -static void calc_low_shelf_first_order_filter( - float *pNum, - float *pDen, - const float f0, - const float g ) -{ - float w0; - - w0 = tanf( EVS_PI * f0 / 2.0f ); - - if ( g < 1.0f ) - { - pNum[0] = 1 + w0 * g; - pNum[1] = w0 * g - 1; - pDen[0] = 1 + w0; - pDen[1] = w0 - 1; - } - else - { - pNum[0] = 1 + w0; - pNum[1] = w0 - 1; - pDen[0] = 1 + w0 / g; - pDen[1] = w0 / g - 1; - } - pNum[0] = pNum[0] / pDen[0]; - pNum[1] = pNum[1] / pDen[0]; - pDen[1] = pDen[1] / pDen[0]; - pDen[0] = 1.0f; - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_jot_t60_coeffs() - * - * Calculate Jot reverb's T60 filters - *-----------------------------------------------------------------------------------------*/ - -static ivas_error calc_jot_t60_coeffs( - float *pAmplitudes, - const uint16_t nrFrequencies, - float *pFrequencies, - float *pCoeffA, - float *pCoeffB, - float fNyquist ) -{ - const float ref_lf_min_norm = REF_LF_MIN / fNyquist; - const float ref_lf_max_norm = REF_LF_MAX / fNyquist; - const float ref_hf_min_norm = REF_HF_MIN / fNyquist; - const float ref_hf_max_norm = REF_HF_MAX / fNyquist; - int16_t f_idx; - int16_t minidx = nrFrequencies - 1; - float f0, gain, tmp; - float minval = 1000000.0f; - float lf_target_gain_dB = 0.0f; - float hf_target_gain_dB = 0.0f; - float mid_crossing_gain_dB; - uint16_t n_points_lf = 0; - uint16_t n_points_hf = 0; - float lin_gain_lf, lin_gain_hf; - float pH_dB[RV_LENGTH_NR_FC]; - - if ( pAmplitudes[0] < pAmplitudes[nrFrequencies - 1] ) - { - /* amplitude response has to have low-pass characteristic */ - return IVAS_ERR_INTERNAL; - } - - for ( f_idx = 0; f_idx < nrFrequencies; f_idx++ ) - { - pH_dB[f_idx] = 20.0f * log10f( pAmplitudes[f_idx] ); - if ( ( pFrequencies[f_idx] >= ref_lf_min_norm ) && ( pFrequencies[f_idx] <= ref_lf_max_norm ) ) - { - lf_target_gain_dB += pH_dB[f_idx]; - n_points_lf++; - } - if ( ( pFrequencies[f_idx] >= ref_hf_min_norm ) && ( pFrequencies[f_idx] <= ref_hf_max_norm ) ) - { - hf_target_gain_dB += pH_dB[f_idx]; - n_points_hf++; - } - } - - if ( ( n_points_lf == 0 ) || ( n_points_hf == 0 ) ) - { - return IVAS_ERR_INTERNAL; - } - - lf_target_gain_dB = lf_target_gain_dB / (float) n_points_lf; - hf_target_gain_dB = hf_target_gain_dB / (float) n_points_hf; - mid_crossing_gain_dB = hf_target_gain_dB + LF_BIAS * ( lf_target_gain_dB - hf_target_gain_dB ); - - for ( f_idx = 1; f_idx < nrFrequencies - 1; f_idx++ ) - { - tmp = fabsf( pH_dB[f_idx] - mid_crossing_gain_dB ); - if ( tmp < minval ) - { - minval = tmp; - minidx = f_idx; - } - } - - f0 = pFrequencies[minidx]; - lin_gain_lf = powf( 10.0f, lf_target_gain_dB * 0.05f ); - lin_gain_hf = powf( 10.0f, hf_target_gain_dB * 0.05f ); - - gain = lin_gain_lf / lin_gain_hf; - - /* call low-pass iir shelf */ - calc_low_shelf_first_order_filter( pCoeffB, pCoeffA, f0, gain ); - - /* adjust gain to match pAmplitudes */ - pCoeffB[0] = pCoeffB[0] * lin_gain_hf; - pCoeffB[1] = pCoeffB[1] * lin_gain_hf; - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function design_iir2_1st_order() - * - * Design 1st order IIR filter - *-----------------------------------------------------------------------------------------*/ - -static ivas_error design_iir2_1st_order( - ivas_reverb_params_t *pParams, - const uint16_t nrLoop, - const uint16_t nrFrequencies, - float frequencies[], - float amplitudes[], - const int32_t output_Fs ) -{ - int16_t len, n, j; - float coefA[2] = { 1.0f, 0.0f }; - float coefB[2] = { 1.0f, 0.0f }; - ivas_error error = IVAS_ERR_OK; - - /* Get numerator and denominator coefficients */ - error = calc_jot_t60_coeffs( amplitudes, nrFrequencies, frequencies, coefA, coefB, 0.5f * output_Fs ); - - if ( error != IVAS_ERR_OK ) - { - return error; - } - - len = 2; - n = nrLoop + nrLoop; - for ( j = 0; j < len; j++ ) - { - pParams->pT60_filter_coeff[(n) *len + j] = coefB[j]; - pParams->pT60_filter_coeff[( n + 1 ) * len + j] = coefA[j]; - } - - return error; -} - - -/*-----------------------------------------------------------------------------------------* - * Function initialize_reverb() - * - * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data) - *-----------------------------------------------------------------------------------------*/ - -static ivas_error initialize_reverb( - REVERB_HANDLE pState ) -{ - ivas_error error; - - error = IVAS_ERR_OK; - - /* init correlation and coloration filters */ - if ( ( error = ivas_reverb_t2f_f2t_init( &pState->fft_filter_ols, pState->fft_size, pState->fft_subblock_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_correl_0, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_correl_1, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_color_0, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_color_1, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - return error; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_t60_filter() - * - * Sets t60 number of taps and coefficients A and B - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_t60_filter( - REVERB_HANDLE pState, - const uint16_t branch, - const uint16_t nr_taps, - float coefA[], - float coefB[] ) -{ - if ( branch >= pState->nr_of_branches ) - { - return IVAS_ERR_INTERNAL; - } - - if ( nr_taps > IVAS_REV_MAX_IIR_FILTER_LENGTH ) - { - return IVAS_ERR_INTERNAL; - } - - ivas_reverb_iir_filt_set( &( pState->t60[branch] ), nr_taps, coefA, coefB ); - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_feedback_delay() - * - * Sets Delay of feedback branch in number of samples - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_feedback_delay( - REVERB_HANDLE pState, - const uint16_t branch, - const int16_t fb_delay ) -{ - if ( branch >= pState->nr_of_branches ) - { - return IVAS_ERR_INTERNAL; - } - - pState->delay_line[branch].Delay = fb_delay; - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_feedback_gain() - * - * Sets nr_of_branches feedback gain values in feedback matrix - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_feedback_gain( - REVERB_HANDLE pState, - const uint16_t branch, - float *pGain ) -{ - if ( branch >= pState->nr_of_branches ) - { - return IVAS_ERR_INTERNAL; - } - - for ( uint16_t i = 0; i < pState->nr_of_branches; i++ ) - { - pState->gain_matrix[branch][i] = pGain[i]; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_correl_fft_filter() - * - * - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_correl_fft_filter( - REVERB_HANDLE pState, - const uint16_t channel, - rv_fftwf_type_complex *pSpectrum ) -{ - if ( channel > 1 ) - { - return IVAS_ERR_INTERNAL; - } - - if ( channel == 0 ) - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_correl_0.fft_spectrum, pState->fft_filter_correl_0.fft_size ); - } - else - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_correl_1.fft_spectrum, pState->fft_filter_correl_1.fft_size ); - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_color_fft_filter() - * - * - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_color_fft_filter( - REVERB_HANDLE pState, - const uint16_t channel, - rv_fftwf_type_complex *pSpectrum ) -{ - if ( channel > 1 ) - { - return IVAS_ERR_INTERNAL; - } - - if ( channel == 0 ) - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_color_0.fft_spectrum, pState->fft_filter_color_0.fft_size ); - } - else - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_color_1.fft_spectrum, pState->fft_filter_color_1.fft_size ); - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function post_fft_filter() - * - * - *-----------------------------------------------------------------------------------------*/ - -static void post_fft_filter( - REVERB_HANDLE pState, - float *p0, - float *p1, - float *pBuffer_0, - float *pBuffer_1 ) -{ - if ( pState->do_corr_filter ) - { - ivas_reverb_t2f_f2t_in( &pState->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 ); - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_correl_0, pBuffer_0 ); - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_correl_1, pBuffer_1 ); - ivas_reverb_fft_filter_CrossMix( pBuffer_0, pBuffer_1, pState->fft_filter_correl_0.fft_size ); - } - else - { - ivas_reverb_t2f_f2t_in( &pState->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 ); - } - - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_color_0, pBuffer_0 ); - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_color_1, pBuffer_1 ); - ivas_reverb_t2f_f2t_out( &pState->fft_filter_ols, pBuffer_0, pBuffer_1, p0, p1 ); - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_mixer_level() - * - * Sets Mixer level: to mix 2 output channels from 8 feedback branches - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_mixer_level( - REVERB_HANDLE pState, - const uint16_t channel, - float level[] ) -{ - if ( channel >= BINAURAL_CHANNELS ) - { - return IVAS_ERR_INTERNAL; - } - - for ( uint16_t i = 0; i < pState->nr_of_branches; i++ ) - { - pState->mixer[channel][i] = level[i]; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function reverb_block() - * - * Input a block (mono) and calculate the 2 output blocks. - *-----------------------------------------------------------------------------------------*/ - -static void reverb_block( - REVERB_HANDLE pState, - float *pInput, - float *pOut0, - float *pOut1 ) - -{ - uint16_t nr_branches = pState->nr_of_branches; - uint16_t bsize = pState->full_block_size; - uint16_t inner_bsize = INNER_BLK_SIZE; - uint16_t i, j, k, ns, branch_idx, blk_idx, start_sample_idx; - - float *pFFT_buf[2], FFT_buf_1[RV_FILTER_MAX_FFT_SIZE], FFT_buf_2[RV_FILTER_MAX_FFT_SIZE]; - float pFeedback_input[INNER_BLK_SIZE]; - float pTemp[INNER_BLK_SIZE]; - float *ppOutput[IVAS_REV_MAX_NR_BRANCHES]; - float Output[IVAS_REV_MAX_NR_BRANCHES][INNER_BLK_SIZE]; - - pFFT_buf[0] = &FFT_buf_1[0]; - pFFT_buf[1] = &FFT_buf_2[0]; - - for ( branch_idx = 0; branch_idx < nr_branches; branch_idx++ ) - { - ppOutput[branch_idx] = (float *) Output + branch_idx * inner_bsize; - } - for ( k = 0; k < bsize; k += inner_bsize ) - { - float *pO0 = &pOut0[k]; - float *pO1 = &pOut1[k]; - for ( i = 0; i < inner_bsize; i++ ) - { - pO0[i] = 0.0f; - pO1[i] = 0.0f; - } - - /* feedback network: */ - for ( i = 0; i < nr_branches; i++ ) - { - float *pOutput_i = &ppOutput[i][0]; - float mixer_0_i = pState->mixer[0][i]; - float mixer_1_i = pState->mixer[1][i]; - - /* output and feedback are same, get sample from delay line ... */ - ivas_rev_delay_line_get_sample_blk( &( pState->delay_line[i] ), inner_bsize, pTemp ); - ivas_reverb_iir_filt_2taps_feed_blk( &( pState->t60[i] ), inner_bsize, pTemp, ppOutput[i] ); - for ( ns = 0; ns < inner_bsize; ns++ ) - { - pO0[ns] += pOutput_i[ns] * mixer_0_i; /* mixer ch 0 */ - pO1[ns] += pOutput_i[ns] * mixer_1_i; /* mixer ch 1 */ - } - } - - for ( i = 0; i < nr_branches; i++ ) - { - float *pIn = &pInput[k]; - for ( ns = 0; ns < inner_bsize; ns++ ) - { - pFeedback_input[ns] = pIn[ns]; - } - for ( j = 0; j < nr_branches; j++ ) - { - float gain_matrix_j_i = pState->gain_matrix[j][i]; - float *pOutput = &ppOutput[j][0]; - for ( ns = 0; ns < inner_bsize; ns++ ) - { - pFeedback_input[ns] += gain_matrix_j_i * pOutput[ns]; - } - } - ivas_rev_delay_line_feed_sample_blk( &( pState->delay_line[i] ), inner_bsize, pFeedback_input ); - } - } - - /* Applying FFT filter to each sub-frame */ - for ( blk_idx = 0; blk_idx < pState->num_fft_subblocks; blk_idx++ ) - { - start_sample_idx = blk_idx * pState->fft_subblock_size; - post_fft_filter( pState, pOut0 + start_sample_idx, pOut1 + start_sample_idx, pFFT_buf[0], pFFT_buf[1] ); - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function downmix_input_block() - * - * Downmix input to mono, taking also DSR gain into account - *-----------------------------------------------------------------------------------------*/ - -static ivas_error downmix_input_block( - REVERB_HANDLE pState, - float pcm_in[][L_FRAME48k], - const AUDIO_CONFIG transport_config, - float *pPcm_out, - const int16_t input_offset ) -{ - int16_t i, s, nchan_transport; - float dmx_gain = pState->dmx_gain; - - switch ( transport_config ) - { - case AUDIO_CONFIG_STEREO: - case AUDIO_CONFIG_5_1: - case AUDIO_CONFIG_7_1: - case AUDIO_CONFIG_5_1_2: - case AUDIO_CONFIG_5_1_4: - case AUDIO_CONFIG_7_1_4: - case AUDIO_CONFIG_ISM1: - case AUDIO_CONFIG_ISM2: - case AUDIO_CONFIG_ISM3: - case AUDIO_CONFIG_ISM4: - { - nchan_transport = audioCfg2channels( transport_config ); - for ( s = 0; s < pState->full_block_size; s++ ) - { - float temp = pcm_in[0][input_offset + s]; - for ( i = 1; i < nchan_transport; i++ ) - { - temp += pcm_in[i][input_offset + s]; - } - pPcm_out[s] = dmx_gain * temp; - } - break; - } - case AUDIO_CONFIG_MONO: /* ~'ZOA_1' */ - case AUDIO_CONFIG_FOA: - case AUDIO_CONFIG_HOA2: - case AUDIO_CONFIG_HOA3: - { - for ( s = 0; s < pState->full_block_size; s++ ) - { - pPcm_out[s] = dmx_gain * pcm_in[0][input_offset + s]; - } - break; - } - default: - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" ); - break; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function predelay_block() - * - * Perform a predelay - *-----------------------------------------------------------------------------------------*/ - -static void predelay_block( - REVERB_HANDLE pState, - float *pInput, - float *pOutput ) -{ - uint16_t i, idx, n_samples, blk_size; - uint16_t max_blk_size = (uint16_t) pState->predelay_line.Delay; - - if ( max_blk_size < 2 ) - { - if ( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */ - { - for ( i = 0; i < pState->full_block_size; i++ ) - { - pOutput[i] = pInput[i]; - } - } - else /* 1-sample length delay line: feed the data sample-by-sample */ - { - for ( i = 0; i < pState->full_block_size; i++ ) - { - pOutput[i] = ivas_rev_delay_line_get_sample( &( pState->predelay_line ) ); - ivas_rev_delay_line_feed_sample( &( pState->predelay_line ), pInput[i] ); - } - } - } - else /* multiple-sample length delay line: use block processing */ - { - idx = 0; - n_samples = pState->full_block_size; - while ( n_samples > 0 ) - { - blk_size = n_samples; - if ( blk_size > max_blk_size ) - { - blk_size = max_blk_size; - } - ivas_rev_delay_line_get_sample_blk( &( pState->predelay_line ), blk_size, &pOutput[idx] ); - ivas_rev_delay_line_feed_sample_blk( &( pState->predelay_line ), blk_size, &pInput[idx] ); - idx += blk_size; - n_samples -= blk_size; - } - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function mix_output_block() - * - * mix one block of *pInL and *pInR samples into *pOutL and *pOutL respectively - *-----------------------------------------------------------------------------------------*/ - -static void mix_output_block( - REVERB_HANDLE pState, - const float *pInL, - const float *pInR, - float *pOutL, - float *pOutR ) -{ - uint16_t i; - - for ( i = 0; i < pState->full_block_size; i++ ) - { - pOutL[i] += pInL[i]; - pOutR[i] += pInR[i]; - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function clear_buffers() - * - * Clears buffers of delay lines and filters - *-----------------------------------------------------------------------------------------*/ - -static void clear_buffers( - REVERB_HANDLE pState ) -{ - int16_t i; - ivas_rev_iir_filter_t *iirFilter; - ivas_rev_delay_line_t *delay_line; - - for ( i = 0; i < IVAS_REV_MAX_NR_BRANCHES; i++ ) - { - delay_line = &( pState->delay_line[i] ); - set_f( delay_line->pBuffer, 0, delay_line->MaxDelay ); - delay_line->BufferPos = 0; - - iirFilter = &( pState->t60[i] ); - set_f( iirFilter->pBuffer, 0, iirFilter->MaxTaps ); - } - - ivas_reverb_t2f_f2t_ClearHistory( &pState->fft_filter_ols ); - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_reverb_open() - * - * Allocate and initialize Crend reverberation handle - *------------------------------------------------------------------------*/ - -ivas_error ivas_reverb_open( - REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ - const HRTFS_HANDLE hHrtf, /* i : HRTF handle */ - RENDER_CONFIG_HANDLE hRenderConfig, /* i : Renderer configuration handle */ - const int32_t output_Fs /* i : output sampling rate */ -) -{ - ivas_error error; - REVERB_HANDLE pState = NULL; - int16_t i, idx, hrtf_idx, subframe_len, output_frame, predelay_bf_len, nr_out_ch, m, channel; - ivas_reverb_sizes_t rev_sizes; - ivas_reverb_params_t params; - int16_t loop; - rv_fftwf_type_complex pFft_wf_filter_ch0[RV_LENGTH_NR_FC]; - rv_fftwf_type_complex pFft_wf_filter_ch1[RV_LENGTH_NR_FC]; - const float *pHrtf_avg_pwr_response_l_const; /* The HRTF set's average left ear power response */ - const float *pHrtf_avg_pwr_response_r_const; /* The HRTF set's average right ear power response */ - const float *pHrtf_inter_aural_coherence_const; /* The HRTF set's inter-aural coherence for diffuse sound */ - float *pHrtf_avg_pwr_response_l; /* The HRTF set's average left ear power response */ - float *pHrtf_avg_pwr_response_r; /* The HRTF set's average right ear power response */ - float *pHrtf_inter_aural_coherence; /* The HRTF set's inter-aural coherence for diffuse sound */ - float *pHrtf_set_l_re[IVAS_MAX_NUM_CH]; - float *pHrtf_set_l_im[IVAS_MAX_NUM_CH]; - float *pHrtf_set_r_re[IVAS_MAX_NUM_CH]; - float *pHrtf_set_r_im[IVAS_MAX_NUM_CH]; - float coef_a[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - float coef_b[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - float pColor_target_l[RV_LENGTH_NR_FC]; - float pColor_target_r[RV_LENGTH_NR_FC]; - float pTime_window[RV_FILTER_MAX_FFT_SIZE]; - float freq_step; - float delay_diff; - float ln_1e6_inverted; - int16_t offset; - int16_t fft_hist_size; - int16_t transitionStart; - int16_t transitionLength; - int16_t nrcoefs; - int16_t nr_fc_input, nr_fc_fft_filter; - - error = IVAS_ERR_OK; - output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); - subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; - predelay_bf_len = output_frame; - - /* Allocate main reverb. handle */ - if ( ( pState = (REVERB_HANDLE) count_malloc( sizeof( REVERB_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Reverberator " ); - } - - nr_fc_input = hRenderConfig->roomAcoustics.nBands; - set_max_sizes( &rev_sizes ); - - if ( ( error = set_base_config( ¶ms, output_Fs, &rev_sizes ) ) != IVAS_ERR_OK ) - { - return error; - } - - for ( loop = 0; loop < IVAS_REV_MAX_NR_BRANCHES; loop++ ) - { - if ( ( pState->loop_delay_buffer[loop] = (float *) count_malloc( params.pLoop_delays[loop] * sizeof( float ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" ); - } - } - - if ( ( pState->pPredelay_buffer = (float *) count_malloc( output_frame * sizeof( float ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" ); - } - pState->full_block_size = subframe_len; - pState->nr_of_branches = rev_sizes.max_nr_loops; - - if ( subframe_len == L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES ) - { - pState->fft_size = IVAS_REVERB_FFT_SIZE_48K; - pState->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K; - } - else if ( subframe_len == L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES ) - { - pState->fft_size = IVAS_REVERB_FFT_SIZE_32K; - pState->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K; - } - else if ( subframe_len == L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES ) - { - pState->fft_size = IVAS_REVERB_FFT_SIZE_16K; - pState->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K; - } - else - { - assert( 0 ); /* unsupported block size */ - } - pState->fft_subblock_size = subframe_len / pState->num_fft_subblocks; - nr_fc_fft_filter = ( pState->fft_size >> 1 ) + 1; - - /* === 'Control logic': compute the reverb processing parameters from the === */ - /* === room, source and listener acoustic information provided in the reverb config === */ - /* Setting up shared temporary buffers for fc, RT60, DSR, etc. */ - pHrtf_avg_pwr_response_l = &pFft_wf_filter_ch0[0][0]; - pHrtf_avg_pwr_response_r = pHrtf_avg_pwr_response_l + nr_fc_fft_filter; - params.pRt60 = &pFft_wf_filter_ch1[0][0]; - params.pDsr = params.pRt60 + nr_fc_fft_filter; - params.pFc = &pState->fft_filter_color_0.fft_spectrum[0]; - pHrtf_inter_aural_coherence = &pState->fft_filter_color_1.fft_spectrum[0]; - - /* Note: these temp buffers can only be used before the final step of the FFT filter design : */ - /* before calls to ivas_reverb_calc_correl_filters(...) or to ivas_reverb_calc_color_filters(...) */ - /* set the uniform frequency grid for FFT filtering */ - freq_step = 0.5f * output_Fs / ( nr_fc_fft_filter - 1 ); - for ( idx = 0; idx < nr_fc_fft_filter; idx++ ) - { - params.pFc[idx] = freq_step * idx; - } - - /* use crend hrtf filters */ - if ( hHrtf != NULL ) - { - /* Compute HRTF set properties: average left/right energies, IA coherence */ - /* First, find the offset of the frequency-domain data for the 1st frame and assign HRTF pointers */ - for ( nr_out_ch = 0; nr_out_ch < BINAURAL_CHANNELS; nr_out_ch++ ) - { - for ( hrtf_idx = 0; hrtf_idx < hHrtf->max_num_ir; hrtf_idx++ ) - { - offset = 0; - for ( m = 0; m < hHrtf->num_iterations[hrtf_idx][nr_out_ch] - 1; m++ ) - { - offset += hHrtf->pIndex_frequency_max[hrtf_idx][nr_out_ch][m]; - } - - if ( nr_out_ch == 0 ) - { - pHrtf_set_l_re[hrtf_idx] = &hHrtf->pOut_to_bin_re[hrtf_idx][0][offset]; - pHrtf_set_l_im[hrtf_idx] = &hHrtf->pOut_to_bin_im[hrtf_idx][0][offset]; - } - else - { - pHrtf_set_r_re[hrtf_idx] = &hHrtf->pOut_to_bin_re[hrtf_idx][1][offset]; - pHrtf_set_r_im[hrtf_idx] = &hHrtf->pOut_to_bin_im[hrtf_idx][1][offset]; - } - } - } - - /* Compute HRTF set properties using frequency-domain HRTF data */ - ivas_reverb_get_hrtf_set_properties( pHrtf_set_l_re, pHrtf_set_l_im, pHrtf_set_r_re, pHrtf_set_r_im, hHrtf->max_num_ir, subframe_len, - nr_fc_fft_filter, pHrtf_avg_pwr_response_l, pHrtf_avg_pwr_response_r, pHrtf_inter_aural_coherence ); - - pHrtf_avg_pwr_response_l_const = (const float *) pHrtf_avg_pwr_response_l; - pHrtf_avg_pwr_response_r_const = (const float *) pHrtf_avg_pwr_response_r; - pHrtf_inter_aural_coherence_const = (const float *) pHrtf_inter_aural_coherence; - } - else - { - pHrtf_avg_pwr_response_l_const = orange53_left_avg_power; - pHrtf_avg_pwr_response_r_const = orange53_right_avg_power; - pHrtf_inter_aural_coherence_const = orange53_coherence; - } - - /* interpolate input table data for T60 and DSR to the FFT filter grid */ - ivas_reverb_interpolate_acoustic_data( nr_fc_input, hRenderConfig->roomAcoustics.pFc_input, hRenderConfig->roomAcoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_dsr, - nr_fc_fft_filter, params.pFc, params.pRt60, params.pDsr ); - - /* adjust DSR for the delay difference */ - delay_diff = hRenderConfig->roomAcoustics.inputPreDelay - hRenderConfig->roomAcoustics.acousticPreDelay; - ln_1e6_inverted = 1.0f / logf( 1e06f ); - for ( idx = 0; idx < nr_fc_fft_filter; idx++ ) - { - const float tau = params.pRt60[idx] * ln_1e6_inverted; - params.pDsr[idx] *= expf( delay_diff / tau ); - } - - /* input downmix */ - calc_dmx_gain( ¶ms ); - - /* predelay - must be after set_base_config() and before compute_t60_coeffs() */ - calc_predelay( ¶ms, hRenderConfig->roomAcoustics.acousticPreDelay, output_Fs ); - /* jot reverb filters */ - if ( ( error = compute_t60_coeffs( ¶ms, nr_fc_fft_filter, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* === Now, copy parameters from ivas_reverb_params_t to REVERB_DATA === */ - /* === to be used for subsequent audio signal processing === */ - /* init input downmixer */ - pState->dmx_gain = params.dmx_gain; - - /* Defining appropriate windowing parameters for FFT filters to prevent aliasing */ - fft_hist_size = pState->fft_size - pState->fft_subblock_size; - - transitionStart = (int16_t) round( FFT_FILTER_WND_FLAT_REGION * fft_hist_size ); - transitionLength = (int16_t) round( FFT_FILTER_WND_TRANS_REGION * fft_hist_size ); - pState->do_corr_filter = params.do_corr_filter; - - /* Compute target levels (gains) for the coloration filters */ - ivas_reverb_calc_color_levels( output_Fs, nr_fc_fft_filter, params.nr_loops, params.pFc, params.pDsr, pHrtf_avg_pwr_response_l_const, pHrtf_avg_pwr_response_r_const, - params.pLoop_delays, params.pT60_filter_coeff, pColor_target_l, pColor_target_r ); - - /* Defining the window used for FFT filters */ - ivas_reverb_define_window_fft( pTime_window, transitionStart, transitionLength, nr_fc_fft_filter ); - - /* clear & init jot reverb (stored parameters, sample buffers etc) */ - if ( ( error = initialize_reverb( pState ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( pState->do_corr_filter ) - { - /* Computing correlation filters on the basis of target IA coherence */ - ivas_reverb_calc_correl_filters( pHrtf_inter_aural_coherence_const, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 ); - - /* Copying the computed FFT correlation filters to the fft_filter components */ - if ( ( error = set_correl_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_correl_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - /* Computing coloration filters on the basis of target responses */ - ivas_reverb_calc_color_filters( pColor_target_l, pColor_target_r, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 ); - - /* Copying the computed FFT colorations filters to the fft_filter components */ - if ( ( error = set_color_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_color_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* init predelay */ - ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer, params.pre_delay, predelay_bf_len ); - - /* initialize feedback branches */ - for ( i = 0; i < rev_sizes.max_nr_loops; i++ ) - { - ivas_rev_delay_line_init( &( pState->delay_line[i] ), pState->loop_delay_buffer[i], init_loop_delay[i], params.pLoop_delays[i] ); - ivas_reverb_iir_filt_init( &( pState->t60[i] ), IVAS_REV_MAX_IIR_FILTER_LENGTH ); - pState->mixer[0][i] = 0.0f; - pState->mixer[1][i] = 0.0f; - } - clear_buffers( pState ); - nrcoefs = params.t60_filter_order + 1; - - if ( IVAS_REV_MAX_IIR_FILTER_LENGTH < nrcoefs ) - { - return IVAS_ERR_INTERNAL; - } - else - { - for ( loop = 0; loop < params.nr_loops; loop++ ) - { - for ( i = 0; i < nrcoefs; i++ ) - { - coef_a[i] = params.pT60_filter_coeff[2 * nrcoefs * loop + i + nrcoefs]; - coef_b[i] = params.pT60_filter_coeff[2 * nrcoefs * loop + i]; - } - - if ( ( error = set_t60_filter( pState, loop, nrcoefs, coef_a, coef_b ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_feedback_delay( pState, loop, params.pLoop_delays[loop] ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_feedback_gain( pState, loop, &( params.pLoop_feedback_matrix[loop * params.nr_loops] ) ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } - - for ( channel = 0; channel < params.nr_outputs; channel++ ) - { - if ( ( error = set_mixer_level( pState, channel, &( params.pLoop_extract_matrix[channel * params.nr_loops] ) ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - *hReverb = pState; - - return error; -} - - -/*------------------------------------------------------------------------- - * ivas_reverb_close() - * - * Deallocate Crend reverberation handle - *------------------------------------------------------------------------*/ - -void ivas_reverb_close( - REVERB_HANDLE *hReverb_in /* i/o: Reverberator handle */ -) -{ - REVERB_HANDLE hReverb; - int16_t loop; - - hReverb = *hReverb_in; - - if ( hReverb != NULL ) - { - for ( loop = 0; loop < IVAS_REV_MAX_NR_BRANCHES; loop++ ) - { - if ( hReverb->loop_delay_buffer[loop] != NULL ) - { - count_free( hReverb->loop_delay_buffer[loop] ); - hReverb->loop_delay_buffer[loop] = NULL; - } - } - - count_free( hReverb->pPredelay_buffer ); - hReverb->pPredelay_buffer = NULL; - - count_free( hReverb ); - hReverb = NULL; - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * ivas_reverb_process() - * - * Process the input PCM audio into output PCM audio, applying reverb - *-----------------------------------------------------------------------------------------*/ - -ivas_error ivas_reverb_process( - REVERB_HANDLE hReverb, /* i/o: reverb state */ - const AUDIO_CONFIG transport_config, /* i : reverb. input audio configuration */ - const int16_t mix_signals, /* i : add reverb to output signal */ - float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ - float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ - const int16_t i_ts ) -{ - float tmp0[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - ivas_error error; - - if ( ( error = downmix_input_block( hReverb, pcm_in, transport_config, tmp1, i_ts * hReverb->full_block_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - predelay_block( hReverb, tmp1, tmp0 ); - - reverb_block( hReverb, tmp0, tmp1, tmp2 ); - - if ( mix_signals ) - { - mix_output_block( hReverb, tmp1, tmp2, &pcm_out[0][i_ts * hReverb->full_block_size], &pcm_out[1][i_ts * hReverb->full_block_size] ); - } - else - { - mvr2r( tmp1, &pcm_out[0][i_ts * hReverb->full_block_size], hReverb->full_block_size ); - mvr2r( tmp2, &pcm_out[1][i_ts * hReverb->full_block_size], hReverb->full_block_size ); - } - - return IVAS_ERR_OK; -} diff --git a/lib_dec/ivas_rom_dec.c b/lib_dec/ivas_rom_dec.c index 84a0db9765371b500f4347ceaa283a3e457deb98..78d4eafea1b1674fe291cdfa5026538b71dceb20 100644 --- a/lib_dec/ivas_rom_dec.c +++ b/lib_dec/ivas_rom_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "cnst.h" #include "ivas_cnst.h" #include -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_stat_dec.h" /* clang-format off */ @@ -231,11 +231,24 @@ const int16_t cna_init_bands[MAX_CNA_NBANDS + 1] = 1, 4, 14, 33, 67, 171, 320 }; -const float max_smooth_gains[SBA_DIRAC_STEREO_NUM_BANDS] = +const float max_smooth_gains1[SBA_DIRAC_STEREO_NUM_BANDS] = { - 0.98f, 0.97f, 0.95f, 0.9f, 0.9f + 0.98f, 0.97f, 0.95f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f }; +const float min_smooth_gains1[SBA_DIRAC_STEREO_NUM_BANDS] = +{ + 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f +}; + +const float max_smooth_gains2[SBA_DIRAC_STEREO_NUM_BANDS] = +{ + 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.9f, 0.9f, 0.9f}; + +const float min_smooth_gains2[SBA_DIRAC_STEREO_NUM_BANDS] = +{ + 0.5f, 0.5f, 0.5, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.3f, 0.3f, 0.3f +}; /*------------------------------------------------------------------------- * ECLVQ Stereo ROM tables @@ -512,637 +525,16 @@ const int16_t sba_map_tc[8] = 0, 1, 2, 3, 4, 8, 9, 15 }; -/*----------------------------------------------------------------------------------* - * LS Renderer ROM tables - *----------------------------------------------------------------------------------*/ - - /* All matrices are stored with dimensions nchan_in x nchan_out */ - /* Downmix matrices */ -const float ls_conversion_cicpX_mono[12][1] = -{ - {1.00000000f}, - {1.00000000f}, - {0.70710677f}, - {0.70710677f}, - {0.79999995f}, - {0.79999995f}, - {0.79999995f}, - {0.79999995f}, - {0.849999964f}, - {0.849999964f}, - {0.849999964f}, - {0.849999964f} -}; - -const float ls_conversion_cicpX_stereo[12][2] = -{ - {1.00000000f, 0.00000000f}, - {0.00000000f, 1.00000000f}, - {0.70710677f, 0.70710677f}, - {0.70710677f, 0.70710677f}, - {0.79999995f, 0.00000000f}, - {0.00000000f, 0.79999995f}, - {0.79999995f, 0.00000000f}, - {0.00000000f, 0.79999995f}, - {0.849999964f, 0.000000000f}, - {0.000000000f, 0.849999964f}, - {0.849999964f, 0.000000000f}, - {0.000000000f, 0.849999964f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp6[] = -{ - /* First row indicates the number of non-zero elements */ - {8, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {7, 1.000000000f}, - {14, 1.000000000f}, - {21, 1.000000000f}, - {28, 1.000000000f}, - {35, 1.000000000f}, - {40, 1.000000000f}, - {47, 1.000000000f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp14_cicp6[] = -{ - /* First row indicates the number of non-zero elements */ - {8, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {7, 1.000000000f}, - {14, 1.000000000f}, - {21, 1.000000000f}, - {28, 1.000000000f}, - {35, 1.000000000f}, - {36, 0.849999964f}, - {43, 0.849999964f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp6[] = -{ - /* First row indicates the number of non-zero elements */ - {10, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {7, 1.000000000f}, - {14, 1.000000000f}, - {21, 1.000000000f}, - {28, 1.000000000f}, - {35, 1.000000000f}, - {36, 0.849999964f}, - {43, 0.849999964f}, - {52, 0.849999964f}, - {59, 0.849999964f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp12[] = -{ - /* First row indicates the number of non-zero elements */ - {10, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {9, 1.000000000f}, - {18, 1.000000000f}, - {27, 1.000000000f}, - {36, 1.000000000f}, - {45, 1.000000000f}, - {48, 0.849999964f}, - {57, 0.849999964f}, - {68, 0.849999964f}, - {77, 0.849999964f} - -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp14[] = -{ - /* First row indicates the number of non-zero elements */ - {10, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {11, 1.000000000f}, - {22, 1.000000000f}, - {33, 1.000000000f}, - {44, 1.000000000f}, - {48, 0.849999964f}, - {55, 1.000000000f}, - {59, 0.849999964f}, - {66, 1.000000000f}, - {77, 1.000000000f}, -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp6[] = -{ - /* First row indicates the number of non-zero elements */ - {14, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {7, 1.000000000f}, - {14, 1.000000000f}, - {21, 1.000000000f}, - {28, 1.000000000f}, - {35, 1.000000000f}, - {36, 0.367322683f}, - {40, 0.930093586f}, - {43, 0.367322683f}, - {47, 0.930093586f}, - {48, 0.849999964f}, - {55, 0.849999964f}, - {64, 0.849999964f}, - {71, 0.849999964f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp12[] = -{ - /* First row indicates the number of non-zero elements */ - {14, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {9, 1.000000000f}, - {18, 1.000000000f}, - {27, 1.000000000f}, - {38, 1.000000000f}, - {47, 1.000000000f}, - {48, 0.367322683f}, - {52, 0.930093586f}, - {57, 0.367322683f}, - {61, 0.930093586f}, - {64, 0.849999964f}, - {73, 0.849999964f}, - {84, 0.849999964f}, - {93, 0.849999964f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp14[] = -{ - /* First row indicates the number of non-zero elements */ - {14, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {9, 1.000000000f}, - {18, 1.000000000f}, - {27, 1.000000000f}, - {36, 1.000000000f}, - {45, 1.000000000f}, - {48, 0.367322683f}, - {52, 0.930093586f}, - {57, 0.367322683f}, - {61, 0.930093586f}, - {70, 1.000000000f}, - {79, 1.000000000f}, - {84, 0.849999964f}, - {93, 0.849999964f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp16[] = -{ - /* First row indicates the number of non-zero elements */ - {14, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.000000000f}, - {11, 1.000000000f}, - {22, 1.000000000f}, - {33, 1.000000000f}, - {44, 1.000000000f}, - {55, 1.000000000f}, - {60, 0.367322683f}, - {64, 0.930093586f}, - {71, 0.367322683f}, - {75, 0.930093586f}, - {86, 1.000000000f}, - {97, 1.000000000f}, - {108, 1.000000000f}, - {119, 1.000000000f} -}; - -/* Upmix matrices */ -const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp14[] = -{ - /* First row indicates the number of non-zero elements */ - {8, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.0f}, - {9, 1.0f}, - {18, 1.0f}, - {27, 1.0f}, - {36, 1.0f}, - {45, 1.0f}, - {52, 1.0f}, - {61, 1.0f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp16[] = -{ - /* First row indicates the number of non-zero elements */ - {8, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.0f}, - {11, 1.0f}, - {22, 1.0f}, - {33, 1.0f}, - {44, 1.0f}, - {55, 1.0f}, - {64, 1.0f}, - {75, 1.0f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp14_cicp19[] = -{ - /* First row indicates the number of non-zero elements */ - {8, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.0f}, - {13, 1.0f}, - {26, 1.0f}, - {39, 1.0f}, - {52, 1.0f}, - {65, 1.0f}, - {80, 1.0f}, - {93, 1.0f} -}; - -const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp19[] = -{ - /* First row indicates the number of non-zero elements */ - {10, 0.0f}, - /* Index of non-zero element, value of non-zero element*/ - {0, 1.0f}, - {13, 1.0f}, - {26, 1.0f}, - {39, 1.0f}, - {52, 1.0f}, - {65, 1.0f}, - {80, 1.0f}, - {93, 1.0f}, - {106, 1.0f}, - {119, 1.0f} -}; - -/* - * Mapping table of input config : output config with corresponding matrix - * NULL indicates a 1:1 mapping of existing input channels to output channels ( used for upmix ) - */ - -const LS_CONVERSION_MAPPING ls_conversion_mapping[LS_SETUP_CONVERSION_NUM_MAPPINGS] = -{ - /* Dowmix mappings - NULL is a special case for MONO / STEREO downmix */ - {AUDIO_CONFIG_5_1, AUDIO_CONFIG_MONO, NULL}, - {AUDIO_CONFIG_7_1, AUDIO_CONFIG_MONO, NULL}, - {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_MONO, NULL}, - {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_MONO, NULL}, - {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_MONO, NULL}, - - {AUDIO_CONFIG_5_1, AUDIO_CONFIG_STEREO, NULL}, - {AUDIO_CONFIG_7_1, AUDIO_CONFIG_STEREO, NULL}, - {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_STEREO, NULL}, - {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_STEREO, NULL}, - {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_STEREO, NULL}, - - {AUDIO_CONFIG_7_1, AUDIO_CONFIG_5_1, ls_conversion_cicp12_cicp6}, - - {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_5_1, ls_conversion_cicp14_cicp6}, - {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_7_1, ls_conversion_cicp14_cicp6}, - - {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_5_1, ls_conversion_cicp16_cicp6}, - {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_7_1, ls_conversion_cicp16_cicp12}, - {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_5_1_2, ls_conversion_cicp16_cicp14}, - - {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_5_1, ls_conversion_cicp19_cicp6}, - {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_7_1, ls_conversion_cicp19_cicp12}, - {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_5_1_2, ls_conversion_cicp19_cicp14}, - {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_5_1_4, ls_conversion_cicp19_cicp16}, - - /* Upmix mappings - NULL implies a 1:1 upmix */ - {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_5_1, NULL}, - {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_7_1, NULL}, - {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_5_1_2, NULL}, - {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_5_1_4, NULL}, - {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_7_1_4, NULL}, - - {AUDIO_CONFIG_5_1, AUDIO_CONFIG_7_1, NULL}, - {AUDIO_CONFIG_5_1, AUDIO_CONFIG_5_1_2, NULL}, - {AUDIO_CONFIG_5_1, AUDIO_CONFIG_5_1_4, NULL}, - {AUDIO_CONFIG_5_1, AUDIO_CONFIG_7_1_4, NULL}, - - {AUDIO_CONFIG_7_1, AUDIO_CONFIG_5_1_2, ls_conversion_cicp12_cicp14}, - {AUDIO_CONFIG_7_1, AUDIO_CONFIG_5_1_4, ls_conversion_cicp12_cicp16}, - {AUDIO_CONFIG_7_1, AUDIO_CONFIG_7_1_4, NULL}, - - {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_5_1_4, NULL}, - {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_7_1_4, ls_conversion_cicp14_cicp19}, - - {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_7_1_4, ls_conversion_cicp16_cicp19}, -}; - /*----------------------------------------------------------------------------------* * FASTCONV and PARAMETRIC binaural renderer ROM tables *----------------------------------------------------------------------------------*/ -const float dmxmtx[BINAURAL_CHANNELS][11] = +const float dmxmtx_table[BINAURAL_CHANNELS][11] = { { 1.0f, 0.0f, 0.70709997f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.70709997f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f }, }; -/* -* 0 = 30,0 -* 1 = -30,0 -* 2 = 0,0 -* 3 = 135,0 -* 4 = -135,0 -* 5 = 110,0 -* 6 = -110,0 -* 7 = 90,0 -* 8 = -90,0 -* 9 = 30,35 -* 10 = -30,35 -* 11 = 110,35 -* 12 = -110,35 -* 13 = 135, 35 -* 14 = -135, 35 -*/ -const int16_t channelIndex_CICP6[5] = { 0, 1, 2, 5, 6 }; -const int16_t channelIndex_CICP12[7] = { 0, 1, 2, 5, 6, 3, 4 }; -const int16_t channelIndex_CICP14[7] = { 0, 1, 2, 5, 6, 9, 10 }; -const int16_t channelIndex_CICP16[9] = { 0, 1, 2, 5, 6, 9, 10, 11, 12 }; -const int16_t channelIndex_CICP19[11] = { 0, 1, 2, 3, 4, 7, 8, 9, 10, 13, 14 }; - -const float surCohEne[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = { 3.0903f, 2.0053f, 1.0860f, 0.8072f, 0.7079f }; - -const float spreadCohEne05[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = { 2.3988f, 1.7783f, 1.1220f, 1.1220f, 1.1220f }; - -const float spreadCohEne1[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = { 1.5975f, 1.1220f, 1.1220f, 1.1220f, 1.1220f }; - -const float lowBitRateBinauralEQ[LOW_BIT_RATE_BINAURAL_EQ_BINS] = { 0.979f, 0.893f, 0.762f, 0.615f, 0.52f, 0.48f, 0.477f, 0.477f, 0.48f, 0.501f, 0.546f, 0.602f, 0.652f, 0.664f, 0.652f, 0.639f, 0.635f }; - -const float diffuseFieldCoherenceDifferenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS] = { - 0.047421f, 0.19773f, 0.22582f, 0.10637f, 0.0087111f, 0.012028f, 0.031972f, 0.019668f, 0.0079928f -}; - -const float diffuseFieldCoherenceDifferenceY[BINAURAL_COHERENCE_DIFFERENCE_BINS] = { - -0.095628f, -0.30569f, -0.34427f, -0.15425f, -0.044628f, -0.057224f, -0.050835f, -0.035214f, -0.02215f -}; - -const float diffuseFieldCoherenceDifferenceZ[BINAURAL_COHERENCE_DIFFERENCE_BINS] = { - 0.048207f, 0.10796f, 0.11845f, 0.047886f, 0.035917f, 0.045196f, 0.018863f, 0.015547f, 0.014157f -}; - - -/*----------------------------------------------------------------------------------* - * TD ISm binaural renderer ROM tables - *----------------------------------------------------------------------------------*/ - - /* The maximum target times set to 100 msec. */ -const int16_t TDREND_SRC_REND_MaxTargetTimes[IVAS_NUM_SUPPORTED_FS] = -{ - 1600, 3200, 4800 /* Corresponds to 16kHz, 32kHz, 48kHz */ -}; - -/* The maximum lengths of the blocks internally in the effect. Corresponds to 6 msec. This means also that */ -/* if the length of the input block is just above 6 msec, the block will be divided into two 3 msec blocks. */ -const int16_t TDREND_SRC_REND_MaxBlockLengths[IVAS_NUM_SUPPORTED_FS] = -{ - 96, 192, 288 /* Corresponds to 16kHz, 32kHz, 48kHz */ -}; - -const int16_t TDREND_MaxITD[IVAS_NUM_SUPPORTED_FS] = -{ - 111, 222, 333 /* Corresponds to 16kHz, 32kHz, 48kHz */ -}; - -const float TDREND_MaxITD_Incr[IVAS_NUM_SUPPORTED_FS] = -{ - 0.0925f, 0.1850f, 0.2775f /* Corresponds to 16kHz, 32kHz, 48kHz, e.g. ( ( 2 * MaxITD ) / ( 0.05 * 48000 ) ) */ -}; - -const int16_t HRTF_MODEL_N_CPTS_VAR[HRTF_MODEL_N_SECTIONS] = -{ - 13, 12, 11 -}; - -const float SincTable[321] = -{ - 1.00000000f, 0.99957629f, 0.99830587f, 0.99619078f, 0.99323448f, 0.98944177f, 0.98481881f, 0.97937311f, - 0.97311350f, 0.96605012f, 0.95819441f, 0.94955907f, 0.94015803f, 0.93000645f, 0.91912066f, 0.90751815f, - 0.89521750f, 0.88223838f, 0.86860150f, 0.85432856f, 0.83944219f, 0.82396595f, 0.80792425f, 0.79134231f, - 0.77424608f, 0.75666226f, 0.73861817f, 0.72014174f, 0.70126144f, 0.68200624f, 0.66240553f, 0.64248906f, - 0.62228691f, 0.60182943f, 0.58114713f, 0.56027070f, 0.53923087f, 0.51805843f, 0.49678411f, 0.47543856f, - 0.45405225f, 0.43265547f, 0.41127824f, 0.38995024f, 0.36870081f, 0.34755883f, 0.32655271f, 0.30571035f, - 0.28505905f, 0.26462549f, 0.24443569f, 0.22451493f, 0.20488776f, 0.18557791f, 0.16660829f, 0.14800093f, - 0.12977695f, 0.11195656f, 0.09455895f, 0.07760236f, 0.06110400f, 0.04508003f, 0.02954554f, 0.01451456f, - 0.00000000f, -0.01398631f, -0.02743368f, -0.04033255f, -0.05267447f, -0.06445214f, -0.07565940f, -0.08629121f, - -0.09634367f, -0.10581400f, -0.11470052f, -0.12300268f, -0.13072098f, -0.13785702f, -0.14441345f, -0.15039394f, - -0.15580318f, -0.16064685f, -0.16493160f, -0.16866498f, -0.17185547f, -0.17451243f, -0.17664604f, -0.17826729f, - -0.17938796f, -0.18002054f, -0.18017822f, -0.17987486f, -0.17912493f, -0.17794347f, -0.17634608f, -0.17434883f, - -0.17196824f, -0.16922125f, -0.16612516f, -0.16269761f, -0.15895648f, -0.15491992f, -0.15060625f, -0.14603396f, - -0.14122162f, -0.13618787f, -0.13095139f, -0.12553081f, -0.11994473f, -0.11421163f, -0.10834984f, -0.10237755f, - -0.09631271f, -0.09017300f, -0.08397586f, -0.07773838f, -0.07147731f, -0.06520902f, -0.05894946f, -0.05271415f, - -0.04651815f, -0.04037601f, -0.03430179f, -0.02830902f, -0.02241063f, -0.01661904f, -0.01094605f, -0.00540284f, - -0.00000000f, 0.00525251f, 0.01034538f, 0.01526993f, 0.02001814f, 0.02458266f, 0.02895676f, 0.03313441f, - 0.03711021f, 0.04087943f, 0.04443799f, 0.04778246f, 0.05091003f, 0.05381856f, 0.05650650f, 0.05897292f, - 0.06121749f, 0.06324047f, 0.06504268f, 0.06662549f, 0.06799083f, 0.06914112f, 0.07007930f, 0.07080878f, - 0.07133343f, 0.07165755f, 0.07178588f, 0.07172352f, 0.07147595f, 0.07104902f, 0.07044886f, 0.06968193f, - 0.06875494f, 0.06767485f, 0.06644886f, 0.06508435f, 0.06358888f, 0.06197015f, 0.06023599f, 0.05839432f, - 0.05645314f, 0.05442051f, 0.05230450f, 0.05011320f, 0.04785466f, 0.04553692f, 0.04316793f, 0.04075558f, - 0.03830765f, 0.03583181f, 0.03333557f, 0.03082630f, 0.02831121f, 0.02579730f, 0.02329137f, 0.02080003f, - 0.01832963f, 0.01588629f, 0.01347589f, 0.01110403f, 0.00877607f, 0.00649705f, 0.00427175f, 0.00210467f, - 0.00000000f, -0.00203837f, -0.00400686f, -0.00590216f, -0.00772131f, -0.00946162f, -0.01112072f, -0.01269654f, - -0.01418731f, -0.01559156f, -0.01690810f, -0.01813605f, -0.01927478f, -0.02032396f, -0.02128352f, -0.02215366f, - -0.02293482f, -0.02362769f, -0.02423318f, -0.02475245f, -0.02518686f, -0.02553797f, -0.02580754f, -0.02599752f, - -0.02611000f, -0.02614728f, -0.02611175f, -0.02600597f, -0.02583262f, -0.02559449f, -0.02529446f, -0.02493550f, - -0.02452066f, -0.02405306f, -0.02353586f, -0.02297226f, -0.02236549f, -0.02171881f, -0.02103547f, -0.02031874f, - -0.01957185f, -0.01879802f, -0.01800043f, -0.01718225f, -0.01634655f, -0.01549638f, -0.01463471f, -0.01376443f, - -0.01288838f, -0.01200928f, -0.01112977f, -0.01025241f, -0.00937962f, -0.00851376f, -0.00765705f, -0.00681160f, - -0.00597942f, -0.00516238f, -0.00436225f, -0.00358068f, -0.00281917f, -0.00207914f, -0.00136185f, -0.00066846f, - -0.00000000f, 0.00064260f, 0.00125856f, 0.00184718f, 0.00240790f, 0.00294026f, 0.00344390f, 0.00391857f, - 0.00436413f, 0.00478051f, 0.00516776f, 0.00552600f, 0.00585544f, 0.00615637f, 0.00642915f, 0.00667420f, - 0.00689203f, 0.00708318f, 0.00724827f, 0.00738795f, 0.00750293f, 0.00759395f, 0.00766178f, 0.00770723f, - 0.00773114f, 0.00773435f, 0.00771774f, 0.00768218f, 0.00762857f, 0.00755779f, 0.00747075f, 0.00736831f, - 0.00725138f, 0.00712082f, 0.00697748f, 0.00682221f, 0.00665584f, 0.00647916f, 0.00629295f, 0.00609797f, - 0.00589494f, 0.00568458f, 0.00546754f, 0.00524448f, 0.00501600f, 0.00478270f, 0.00454511f, 0.00430377f, - 0.00405916f, 0.00381176f, 0.00356198f, 0.00331023f, 0.00305690f, 0.00280234f, 0.00254687f, 0.00229079f, - 0.00203440f, 0.00177795f, 0.00152168f, 0.00126584f, 0.00101062f, 0.00075625f, 0.00050289f, 0.00025075f, - 0.00000000f -}; - -const float orange53_left_avg_power[257] = { - 0.999231100f, 0.992580175f, 0.969233215f, 0.925614893f, 0.871408045f, 0.826101780f, 0.803222895f, 0.800087631f, 0.802672029f, - 0.801490188f, 0.796555817f, 0.790879488f, 0.784882724f, 0.777585745f, 0.769326210f, 0.761789441f, 0.756145239f, 0.752754092f, - 0.751703024f, 0.752594173f, 0.754317880f, 0.755515277f, 0.754378498f, 0.748860359f, 0.738919020f, 0.727488697f, 0.718792558f, - 0.714865267f, 0.713446736f, 0.711076498f, 0.706021905f, 0.697553098f, 0.684623063f, 0.667031527f, 0.647006035f, 0.627680719f, - 0.609939933f, 0.592472672f, 0.574803054f, 0.558499217f, 0.544599831f, 0.532128096f, 0.520152628f, 0.509682238f, 0.501904130f, - 0.496162385f, 0.491121918f, 0.486813396f, 0.483951330f, 0.482198298f, 0.480713189f, 0.479654074f, 0.479590476f, 0.479965866f, - 0.479589254f, 0.478181243f, 0.476334095f, 0.474199444f, 0.471616089f, 0.469089746f, 0.467486322f, 0.466943622f, 0.467153549f, - 0.468381166f, 0.470996737f, 0.474416614f, 0.477639019f, 0.480612457f, 0.483910263f, 0.487287015f, 0.489909321f, 0.491668850f, - 0.493155539f, 0.494319856f, 0.494512051f, 0.493615031f, 0.492155492f, 0.490116775f, 0.486886710f, 0.482303619f, 0.476902038f, - 0.470775038f, 0.463377595f, 0.454571068f, 0.445130944f, 0.435581058f, 0.425568998f, 0.414717495f, 0.403531373f, 0.392556936f, - 0.381436378f, 0.369506508f, 0.357099295f, 0.345049500f, 0.333368897f, 0.321326375f, 0.308959186f, 0.297232091f, 0.286592871f, - 0.276453108f, 0.266589880f, 0.257950366f, 0.251341701f, 0.246435612f, 0.242861211f, 0.241405189f, 0.242839754f, 0.246688128f, - 0.252115428f, 0.259297341f, 0.268399984f, 0.278481483f, 0.288520366f, 0.298599035f, 0.308846802f, 0.318350822f, 0.326248646f, - 0.332813978f, 0.338464528f, 0.342543274f, 0.344278336f, 0.344031811f, 0.342641503f, 0.339995682f, 0.335437506f, 0.329174429f, - 0.322237372f, 0.315035462f, 0.306967229f, 0.297821850f, 0.288482070f, 0.279766560f, 0.271234214f, 0.262228251f, 0.253214896f, - 0.245183259f, 0.237939596f, 0.230546176f, 0.223051578f, 0.216552779f, 0.211263061f, 0.206180066f, 0.200917527f, 0.196485907f, - 0.193453044f, 0.190857053f, 0.187853232f, 0.185171053f, 0.183685005f, 0.182665780f, 0.180928215f, 0.178784713f, 0.177342966f, - 0.176323384f, 0.174430951f, 0.171496049f, 0.168740034f, 0.166518897f, 0.163711995f, 0.159658119f, 0.155442193f, 0.152056932f, - 0.148795277f, 0.144545168f, 0.139905334f, 0.136263832f, 0.133493021f, 0.130194828f, 0.126240104f, 0.123071767f, 0.121281922f, - 0.119557180f, 0.117016964f, 0.114773229f, 0.114072219f, 0.114103459f, 0.113414355f, 0.112460621f, 0.112842396f, 0.114564091f, - 0.115944758f, 0.116569765f, 0.117913686f, 0.120910525f, 0.124211200f, 0.126575813f, 0.128826424f, 0.132578567f, 0.137430578f, - 0.141675219f, 0.144987956f, 0.148879051f, 0.154273912f, 0.159992099f, 0.164641231f, 0.168560207f, 0.173201621f, 0.178906262f, - 0.184429348f, 0.188756809f, 0.192309171f, 0.196154252f, 0.200732291f, 0.205381230f, 0.209404662f, 0.212832779f, 0.216197237f, - 0.220162451f, 0.225029215f, 0.230637416f, 0.236752108f, 0.243243530f, 0.249900997f, 0.256293535f, 0.261716694f, 0.265186161f, - 0.265652657f, 0.262010813f, 0.253508776f, 0.243198514f, 0.244490802f, 0.255167097f, 0.258825988f, 0.257396817f, 0.256197631f, - 0.256865948f, 0.258354962f, 0.259370565f, 0.259730458f, 0.259894609f, 0.260285556f, 0.260970831f, 0.261650831f, 0.262020200f, - 0.262095064f, 0.262225062f, 0.262741268f, 0.263585031f, 0.264350951f, 0.264654577f, 0.264539272f, 0.264409125f, 0.264633715f, - 0.265172601f, 0.265621960f, 0.265678704f, 0.265469313f, 0.265454412f, 0.265907466f, 0.266625792f, 0.267101586f, 0.266997635f, - 0.266522497f, 0.266185820f, 0.266298562f, 0.266692907f, 0.266907692f -}; - -const float orange53_right_avg_power[257] = { - 0.999231100f, 0.992580175f, 0.969233215f, 0.925614893f, 0.871408045f, 0.826101780f, 0.803222895f, 0.800087631f, 0.802672029f, - 0.801490188f, 0.796555817f, 0.790879488f, 0.784882724f, 0.777585745f, 0.769326210f, 0.761789441f, 0.756145239f, 0.752754092f, - 0.751703024f, 0.752594173f, 0.754317880f, 0.755515277f, 0.754378498f, 0.748860359f, 0.738919020f, 0.727488697f, 0.718792558f, - 0.714865267f, 0.713446736f, 0.711076498f, 0.706021905f, 0.697553098f, 0.684623063f, 0.667031527f, 0.647006035f, 0.627680719f, - 0.609939933f, 0.592472672f, 0.574803054f, 0.558499217f, 0.544599831f, 0.532128096f, 0.520152628f, 0.509682238f, 0.501904130f, - 0.496162385f, 0.491121918f, 0.486813396f, 0.483951330f, 0.482198298f, 0.480713189f, 0.479654074f, 0.479590476f, 0.479965866f, - 0.479589254f, 0.478181243f, 0.476334095f, 0.474199444f, 0.471616089f, 0.469089746f, 0.467486322f, 0.466943622f, 0.467153549f, - 0.468381166f, 0.470996737f, 0.474416614f, 0.477639019f, 0.480612457f, 0.483910263f, 0.487287015f, 0.489909321f, 0.491668850f, - 0.493155539f, 0.494319856f, 0.494512051f, 0.493615031f, 0.492155492f, 0.490116775f, 0.486886710f, 0.482303619f, 0.476902038f, - 0.470775038f, 0.463377595f, 0.454571068f, 0.445130944f, 0.435581058f, 0.425568998f, 0.414717495f, 0.403531373f, 0.392556936f, - 0.381436378f, 0.369506508f, 0.357099295f, 0.345049500f, 0.333368897f, 0.321326375f, 0.308959186f, 0.297232091f, 0.286592871f, - 0.276453108f, 0.266589880f, 0.257950366f, 0.251341701f, 0.246435612f, 0.242861211f, 0.241405189f, 0.242839754f, 0.246688128f, - 0.252115428f, 0.259297341f, 0.268399984f, 0.278481483f, 0.288520366f, 0.298599035f, 0.308846802f, 0.318350822f, 0.326248646f, - 0.332813978f, 0.338464528f, 0.342543274f, 0.344278336f, 0.344031811f, 0.342641503f, 0.339995682f, 0.335437506f, 0.329174429f, - 0.322237372f, 0.315035462f, 0.306967229f, 0.297821850f, 0.288482070f, 0.279766560f, 0.271234214f, 0.262228251f, 0.253214896f, - 0.245183259f, 0.237939596f, 0.230546176f, 0.223051578f, 0.216552779f, 0.211263061f, 0.206180066f, 0.200917527f, 0.196485907f, - 0.193453044f, 0.190857053f, 0.187853232f, 0.185171053f, 0.183685005f, 0.182665780f, 0.180928215f, 0.178784713f, 0.177342966f, - 0.176323384f, 0.174430951f, 0.171496049f, 0.168740034f, 0.166518897f, 0.163711995f, 0.159658119f, 0.155442193f, 0.152056932f, - 0.148795277f, 0.144545168f, 0.139905334f, 0.136263832f, 0.133493021f, 0.130194828f, 0.126240104f, 0.123071767f, 0.121281922f, - 0.119557180f, 0.117016964f, 0.114773229f, 0.114072219f, 0.114103459f, 0.113414355f, 0.112460621f, 0.112842396f, 0.114564091f, - 0.115944758f, 0.116569765f, 0.117913686f, 0.120910525f, 0.124211200f, 0.126575813f, 0.128826424f, 0.132578567f, 0.137430578f, - 0.141675219f, 0.144987956f, 0.148879051f, 0.154273912f, 0.159992099f, 0.164641231f, 0.168560207f, 0.173201621f, 0.178906262f, - 0.184429348f, 0.188756809f, 0.192309171f, 0.196154252f, 0.200732291f, 0.205381230f, 0.209404662f, 0.212832779f, 0.216197237f, - 0.220162451f, 0.225029215f, 0.230637416f, 0.236752108f, 0.243243530f, 0.249900997f, 0.256293535f, 0.261716694f, 0.265186161f, - 0.265652657f, 0.262010813f, 0.253508776f, 0.243198514f, 0.244490802f, 0.255167097f, 0.258825988f, 0.257396817f, 0.256197631f, - 0.256865948f, 0.258354962f, 0.259370565f, 0.259730458f, 0.259894609f, 0.260285556f, 0.260970831f, 0.261650831f, 0.262020200f, - 0.262095064f, 0.262225062f, 0.262741268f, 0.263585031f, 0.264350951f, 0.264654577f, 0.264539272f, 0.264409125f, 0.264633715f, - 0.265172601f, 0.265621960f, 0.265678704f, 0.265469313f, 0.265454412f, 0.265907466f, 0.266625792f, 0.267101586f, 0.266997635f, - 0.266522497f, 0.266185820f, 0.266298562f, 0.266692907f, 0.266907692f -}; - -const float orange53_coherence[257] = { - 0.929530263f, 0.921171963f, 0.900268972f, 0.876067519f, 0.855227590f, 0.837884128f, 0.823401272f, 0.818804145f, 0.835025251f, - 0.871971071f, 0.911253273f, 0.929330528f, 0.921199203f, 0.900894165f, 0.882577479f, 0.867001534f, 0.849280477f, 0.832460761f, - 0.824062645f, 0.823441386f, 0.820908070f, 0.811902404f, 0.802339375f, 0.798648477f, 0.797345281f, 0.791158736f, 0.779512227f, - 0.768243194f, 0.760565042f, 0.754912853f, 0.751044095f, 0.752276063f, 0.759258866f, 0.766927004f, 0.769716740f, 0.767338514f, - 0.763358235f, 0.759508014f, 0.755201221f, 0.750362694f, 0.746060252f, 0.742611766f, 0.739434779f, 0.736354828f, 0.733443379f, - 0.730109870f, 0.726028502f, 0.722365141f, 0.720153689f, 0.718220115f, 0.714793265f, 0.710619092f, 0.708084404f, 0.707218647f, - 0.705624878f, 0.702472746f, 0.700073540f, 0.699947894f, 0.700519860f, 0.699934483f, 0.699344158f, 0.700895131f, 0.704551995f, - 0.708814025f, 0.713567019f, 0.719995975f, 0.728467822f, 0.738399088f, 0.749545693f, 0.761859894f, 0.774593413f, 0.787218869f, - 0.800481200f, 0.814727187f, 0.828367889f, 0.839860320f, 0.850490928f, 0.862034321f, 0.873037636f, 0.880097568f, 0.883217216f, - 0.885473788f, 0.887664974f, 0.886511028f, 0.880120754f, 0.871120989f, 0.862524390f, 0.853262126f, 0.840783834f, 0.825854301f, - 0.811407208f, 0.798167706f, 0.784307659f, 0.769172490f, 0.754072189f, 0.739893615f, 0.726129174f, 0.712544501f, 0.699519753f, - 0.686980069f, 0.674778104f, 0.663931608f, 0.655511260f, 0.648816824f, 0.642671287f, 0.638217211f, 0.637585819f, 0.640332758f, - 0.643755615f, 0.647433281f, 0.653589368f, 0.662824631f, 0.672268033f, 0.680022597f, 0.687623680f, 0.696763635f, 0.705829978f, - 0.712574661f, 0.717432320f, 0.721986175f, 0.725707173f, 0.727064371f, 0.726255059f, 0.724350274f, 0.720927835f, 0.715189219f, - 0.708206475f, 0.701428175f, 0.693923056f, 0.684313059f, 0.674107075f, 0.666009307f, 0.659245491f, 0.650998116f, 0.641600072f, - 0.634524226f, 0.630267978f, 0.625348687f, 0.618164837f, 0.611785769f, 0.608430445f, 0.605561733f, 0.600407422f, 0.594782710f, - 0.591767371f, 0.590365708f, 0.587845862f, 0.584915996f, 0.584355533f, 0.585834682f, 0.586913347f, 0.587935925f, 0.591403484f, - 0.596784472f, 0.601111054f, 0.604539037f, 0.610374093f, 0.618451059f, 0.624519289f, 0.627448440f, 0.631859899f, 0.639748096f, - 0.646256745f, 0.647378445f, 0.647664309f, 0.652599990f, 0.659044445f, 0.659743190f, 0.656243205f, 0.656651020f, 0.662200928f, - 0.664544880f, 0.660030127f, 0.656303048f, 0.659881413f, 0.664978266f, 0.662953973f, 0.657274961f, 0.658065319f, 0.665406108f, - 0.668446958f, 0.663809955f, 0.661349833f, 0.668595374f, 0.677367866f, 0.677208483f, 0.672289610f, 0.675831020f, 0.688208520f, - 0.695776582f, 0.691749871f, 0.687812865f, 0.696674168f, 0.711764693f, 0.716045380f, 0.706839681f, 0.701565385f, 0.711955190f, - 0.726487696f, 0.723370016f, 0.700417101f, 0.677427649f, 0.670733511f, 0.671355724f, 0.654210806f, 0.608316183f, 0.549225986f, - 0.504217446f, 0.484227657f, 0.475346446f, 0.452598959f, 0.399407327f, 0.319485664f, 0.229244962f, 0.146649837f, 0.083417825f, - 0.041744832f, 0.018142883f, 0.006854009f, 0.002511850f, 0.001177550f, 0.000840970f, 0.000701097f, 0.000571384f, 0.000458581f, - 0.000376965f, 0.000320562f, 0.000278847f, 0.000245546f, 0.000218281f, 0.000195632f, 0.000176647f, 0.000160827f, 0.000147978f, - 0.000137649f, 0.000129066f, 0.000121431f, 0.000114406f, 0.000108067f, 0.000102595f, 0.000097917f, 0.000093750f, 0.000089854f, - 0.000086255f, 0.000083183f, 0.000080804f, 0.000079026f, 0.000077552f, 0.000076117f, 0.000074693f, 0.000073431f, 0.000072456f, - 0.000071701f, 0.000071002f, 0.000070286f, 0.000069692f, 0.000069457f -}; - -/*----------------------------------------------------------------------------------* - * t-design and SN3D normalization table - *----------------------------------------------------------------------------------*/ - - /* SN3D norm */ -const float norm_sn3d_hoa3[16] = -{ - 1.f, 1.7320508f, 1.7320508f, 1.7320508f, 2.2360680f, 2.2360680f, 2.2360680f, 2.2360680f, - 2.2360680f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f -}; - -/* Order 11 t-design */ -const uint16_t t_design_11_size = 70; - -const float t_design_11_azimuth[70] = -{ - 1.329273e+02f, -8.393495e+01f, 8.474100e+00f, -1.133408e+02f, -1.032659e+02f, -3.323704e+01f, 2.185643e+01f, -1.565395e+02f, - -6.426475e+01f, 1.657795e+02f, -2.520283e+01f, -9.700380e+01f, 2.785464e+01f, 1.532142e+02f, -1.550616e+02f, -1.184214e+01f, - 8.053873e+01f, -4.205616e+01f, -3.122333e+01f, 3.883790e+01f, 9.376069e+01f, -8.475602e+01f, 7.755368e+00f, -1.222769e+02f, - 4.680127e+01f, -2.476863e+01f, 9.989047e+01f, -1.347840e+02f, -8.308802e+01f, 6.012817e+01f, 1.526447e+02f, 2.975767e+01f, - 4.077932e+01f, 1.101839e+02f, 1.656521e+02f, -1.299266e+01f, 7.973599e+01f, -5.052453e+01f, 1.189239e+02f, 4.722029e+01f, - 1.719253e+02f, -6.251458e+01f, -1.111567e+01f, 1.320180e+02f, -1.353555e+02f, 1.023709e+02f, 1.127393e+02f, -1.783050e+02f, - -1.223199e+02f, 5.907635e+01f, 1.517042e+02f, 2.137634e+01f, -1.690055e+02f, 1.189808e+02f, -1.160893e+02f, 9.647679e+00f, - 6.089332e+01f, -1.560215e+02f, -6.346030e+01f, 1.749298e+02f, -1.752888e+02f, -1.059519e+02f, -5.019283e+01f, 1.313583e+02f, - -1.362968e+02f, 9.356446e+01f, -9.708401e+01f, -1.691583e+02f, -4.413238e+01f, 8.147954e+01f -}; - -const float t_design_11_elevation[70] = -{ - 7.692547e+00f, -2.373007e+01f, 2.351276e+01f, 7.042259e+01f, -9.896944e+00f, -7.075133e+01f, -2.646185e+01f, 4.777649e+01f, - -7.720470e+00f, 4.453436e+01f, 2.638979e+01f, -4.465789e+01f, 9.767035e+00f, -4.770533e+01f, 7.453029e+00f, -2.359012e+01f, - 2.371945e+01f, 7.043827e+01f, -9.835416e+00f, -7.049808e+01f, -2.629492e+01f, 4.761480e+01f, -7.517185e+00f, 4.428623e+01f, - 2.664426e+01f, -4.456937e+01f, 9.912719e+00f, -4.795996e+01f, 7.296799e+00f, -2.334460e+01f, 2.364153e+01f, 7.068431e+01f, - -9.581404e+00f, -7.039345e+01f, -2.642582e+01f, 4.775107e+01f, -7.308536e+00f, 4.426328e+01f, 2.671406e+01f, -4.431497e+01f, - 9.758997e+00f, -4.803619e+01f, 7.439651e+00f, -2.333261e+01f, 2.338690e+01f, 7.082191e+01f, -9.485964e+00f, -7.058019e+01f, - -2.667403e+01f, 4.799784e+01f, -7.382762e+00f, 4.449706e+01f, 2.650250e+01f, -4.424619e+01f, 9.518451e+00f, -4.782814e+01f, - 7.684274e+00f, -2.357068e+01f, 2.330745e+01f, 7.065865e+01f, -9.680889e+00f, -7.080268e+01f, -2.669635e+01f, 4.801363e+01f, - -7.637348e+00f, 4.466512e+01f, 2.630235e+01f, -4.445764e+01f, 9.523415e+00f, -4.762422e+01f -}; - - -/*----------------------------------------------------------------------* -* Reverberator ROM tables -*-----------------------------------------------------------------------*/ - -const float ivas_reverb_default_fc[IVAS_REVERB_DEFAULT_N_BANDS] = -{ - 20.0f, 25.0f, 31.5f, 40.0f, - 50.0f, 63.0f, 80.0f, 100.0f, - 125.0f, 160.0f, 200.0f, 250.0f, - 315.0f, 400.0f, 500.0f, 630.0f, - 800.0f, 1000.0f, 1250.0f, 1600.0f, - 2000.0f, 2500.0f, 3150.0f, 4000.0f, - 5000.0f, 6300.0f, 8000.0f, 10000.0f, - 12500.0f, 16000.0f, 20000.0f -}; - -const float ivas_reverb_default_RT60[IVAS_REVERB_DEFAULT_N_BANDS] = -{ - 1.3622f, 1.4486f, 1.3168f, 1.5787f, - 1.4766f, 1.3954f, 1.2889f, 1.3462f, - 1.0759f, 1.0401f, 1.097f, 1.085f, - 1.091f, 1.0404f, 1.0499f, 1.0699f, - 1.1028f, 1.1714f, 1.1027f, 1.0666f, - 1.055f, 1.0553f, 1.0521f, 1.0569f, - 1.0421f, 0.97822f, 0.80487f, 0.75944f, - 0.71945f, 0.61682f, 0.60031f -}; - -const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = -{ - 1.8811e-08f, 2.1428e-08f, 1.3972e-08f, 1.51e-08f, - 1.287e-08f, 1.8747e-08f, 2.413e-08f, 3.9927e-08f, - 8.9719e-08f, 1.902e-07f, 3.702e-07f, 6.1341e-07f, - 7.1432e-07f, 6.5331e-07f, 4.6094e-07f, 5.4683e-07f, - 7.0134e-07f, 6.856e-07f, 7.114e-07f, 6.9604e-07f, - 5.2939e-07f, 5.699e-07f, 6.1773e-07f, 5.7488e-07f, - 4.7748e-07f, 2.7213e-07f, 1.3681e-07f, 1.0941e-07f, - 6.2001e-08f, 2.8483e-08f, 2.6267e-08f -}; - /* clang-format on */ diff --git a/lib_dec/ivas_rom_dec.h b/lib_dec/ivas_rom_dec.h index 5979d8d64bcd367305c41f84a45a0bb65e0c1da8..4366077bbb3b45e0367057e36a01ae93c01512a5 100644 --- a/lib_dec/ivas_rom_dec.h +++ b/lib_dec/ivas_rom_dec.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -60,7 +60,6 @@ extern const float dft_ap_gains[5][3]; extern const int16_t dft_ap_delays[3][3]; extern const float dft_res_pred_weights[][STEREO_DFT_BAND_MAX]; - extern const float dft_win232ms_8k[75]; extern const float dft_win232ms_12k8[120]; extern const float dft_win232ms_16k[150]; @@ -70,7 +69,11 @@ extern const float dft_win232ms_48k[450]; extern const float dft_win_8k[70]; extern const int16_t cna_init_bands[MAX_CNA_NBANDS + 1]; -extern const float max_smooth_gains[SBA_DIRAC_STEREO_NUM_BANDS]; + +extern const float min_smooth_gains1[SBA_DIRAC_STEREO_NUM_BANDS]; +extern const float max_smooth_gains1[SBA_DIRAC_STEREO_NUM_BANDS]; +extern const float min_smooth_gains2[SBA_DIRAC_STEREO_NUM_BANDS]; +extern const float max_smooth_gains2[SBA_DIRAC_STEREO_NUM_BANDS]; /*----------------------------------------------------------------------------------* @@ -110,96 +113,12 @@ extern const float ap_split_frequencies[DIRAC_DECORR_NUM_SPLIT_BANDS + 1]; extern const int16_t sba_map_tc[8]; -/*----------------------------------------------------------------------------------* - * LS Configuration Converter ROM tables - *----------------------------------------------------------------------------------*/ - -/* Downmix matrices */ -extern const float ls_conversion_cicpX_mono[12][1]; -extern const float ls_conversion_cicpX_stereo[12][2]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp6[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp6[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp14_cicp6[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp6[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp14[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp6[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp12[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp14[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp16[]; - -/* Upmix matrices */ -extern const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp14[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp16[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp14_cicp19[]; -extern const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp19[]; - -/* Mapping table of input config : output config with corresponding matrix */ -extern const LS_CONVERSION_MAPPING ls_conversion_mapping[]; - /*----------------------------------------------------------------------------------* * FASTCONV and PARAMETRIC binaural renderer ROM tables *----------------------------------------------------------------------------------*/ -extern const float dmxmtx[BINAURAL_CHANNELS][11]; -extern const int16_t channelIndex_CICP6[5]; -extern const int16_t channelIndex_CICP12[7]; -extern const int16_t channelIndex_CICP14[9]; -extern const int16_t channelIndex_CICP16[9]; -extern const int16_t channelIndex_CICP19[11]; - -/* These are equalization values for spread and surround coherent sounds, approximating the spectrum - * for such sounds at anechoic multichannel listening. */ -extern const float surCohEne[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; -extern const float spreadCohEne05[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; -extern const float spreadCohEne1[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; - -/* Values for low-bit-rate equalization */ -extern const float lowBitRateBinauralEQ[LOW_BIT_RATE_BINAURAL_EQ_BINS]; - -/* Diffuse field binaural coherence directional adjustment values */ -extern const float diffuseFieldCoherenceDifferenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS]; -extern const float diffuseFieldCoherenceDifferenceY[BINAURAL_COHERENCE_DIFFERENCE_BINS]; -extern const float diffuseFieldCoherenceDifferenceZ[BINAURAL_COHERENCE_DIFFERENCE_BINS]; - -/*----------------------------------------------------------------------------------* - * TD ISM Object renderer - *----------------------------------------------------------------------------------*/ - -extern const int16_t TDREND_SRC_REND_MaxTargetTimes[IVAS_NUM_SUPPORTED_FS]; -extern const int16_t TDREND_SRC_REND_MaxBlockLengths[IVAS_NUM_SUPPORTED_FS]; -extern const int16_t TDREND_MaxITD[IVAS_NUM_SUPPORTED_FS]; -extern const float TDREND_MaxITD_Incr[IVAS_NUM_SUPPORTED_FS]; - -extern const int16_t HRTF_MODEL_N_CPTS_VAR[HRTF_MODEL_N_SECTIONS]; - -extern const float SincTable[321]; - -extern const float orange53_left_avg_power[257]; -extern const float orange53_right_avg_power[257]; -extern const float orange53_coherence[257]; - - -/*----------------------------------------------------------------------------------* - * t-design and SN3D normalization table - *----------------------------------------------------------------------------------*/ - -/* SN3D norm */ -extern const float norm_sn3d_hoa3[16]; - -/* Order 11 t-design */ -extern const uint16_t t_design_11_size; -extern const float t_design_11_azimuth[70]; -extern const float t_design_11_elevation[70]; - - -/*----------------------------------------------------------------------* - * Reverberator ROM tables - *-----------------------------------------------------------------------*/ - -extern const float ivas_reverb_default_fc[]; -extern const float ivas_reverb_default_RT60[]; -extern const float ivas_reverb_default_DSR[]; +extern const float dmxmtx_table[BINAURAL_CHANNELS][11]; #endif diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 5802dae2b3c3e0ce7c92948c41df42ec826e1bfa..589414556fddf5fa41d3a7d6f995e37909370026 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,411 +37,67 @@ #include "ivas_cnst.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_com.h" #include "ivas_rom_dec.h" +#include #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" -/*-----------------------------------------------------------------------* - * Local function prototypes - *-----------------------------------------------------------------------*/ - -static void ivas_sba_dmx_dec( float sba_data[][L_FRAME48k], const int16_t nchan_transport, const int16_t output_frame ); - -#ifdef DEBUG_MODE_DIRAC -static void debug_mode_dirac( float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], const int16_t nchan_transport, const int16_t output_frame ); -#endif - - -/*-------------------------------------------------------------------------* - * ivas_mc2sba() - * - * MC signals transformed into SBA in TD domain - *-------------------------------------------------------------------------*/ - -void ivas_mc2sba( - IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ - float buffer_td[][L_FRAME48k], /* i/o: MC signals (on input) and the HOA3 (on output) */ - const int16_t output_frame, /* i : output frame length per channel */ - const int16_t sba_order, /* i : Ambisonic (SBA) order */ - const float gain_lfe /* i : gain for LFE, 0 = ignore LFE */ -) -{ - int16_t i, j, k; - int16_t idx_lfe, idx_in; - float buffer_tmp[16][L_FRAME48k]; - float gains[16]; - int16_t azimuth, elevation; - int16_t sba_num_chans; - - assert( ( sba_order <= 3 ) && "Only order up to 3 is supported!" ); - - /* Init*/ - sba_num_chans = ( sba_order + 1 ) * ( sba_order + 1 ); - for ( j = 0; j < sba_num_chans; j++ ) - { - set_zero( buffer_tmp[j], output_frame ); - } - - /* HOA encoding*/ - idx_lfe = 0; - idx_in = 0; - for ( i = 0; i < hIntSetup.nchan_out_woLFE + hIntSetup.num_lfe; i++ ) - { - if ( ( hIntSetup.num_lfe > 0 ) && ( i == hIntSetup.index_lfe[idx_lfe] ) ) - { - if ( gain_lfe > 0.f ) - { - /* Add LFE to omni W with gain*/ - for ( k = 0; k < output_frame; k++ ) - { - buffer_tmp[0][k] += gain_lfe * buffer_td[i][k]; - } - } - - if ( idx_lfe < ( hIntSetup.num_lfe - 1 ) ) - { - idx_lfe++; - } - } - else - { - azimuth = (int16_t) ( hIntSetup.ls_azimuth[idx_in] ); - elevation = (int16_t) ( hIntSetup.ls_elevation[idx_in] ); - idx_in++; - - /* get HOA response for direction (ACN/SN3D)*/ - ivas_dirac_dec_get_response( - azimuth, - elevation, - gains, - sba_order ); - - for ( j = 0; j < sba_num_chans; j++ ) - { - for ( k = 0; k < output_frame; k++ ) - { - buffer_tmp[j][k] += gains[j] * buffer_td[i][k]; - } - } - } - } - - for ( j = 0; j < sba_num_chans; j++ ) - { - mvr2r( buffer_tmp[j], buffer_td[j], output_frame ); - } - - return; -} - - -/*-------------------------------------------------------------------------* - * ivas_sba2MC_cldfb() - * - * SBA signals transformed into MC in CLDFB domain - *-------------------------------------------------------------------------*/ - -void ivas_sba2mc_cldfb( - IVAS_OUTPUT_SETUP hInSetup, /* i : Format of input layout */ - float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb real part */ - float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb imag part */ - const int16_t nb_channels_out, /* i : nb of output channels */ - const int16_t nb_bands, /* i : nb of CLDFB bands to process */ - const float *hoa_dec_mtx /* i : hoa decoding mtx */ -) -{ - int16_t iBlock, iBand, n, m; - float realOut[16][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX], imagOut[16][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX]; - float g; - float *p_real, *p_imag, *p_realOut, *p_imagOut; - int16_t nb_channels_in; - - wmops_sub_start( "ivas_sba2mc_cldfb" ); - - nb_channels_in = hInSetup.nchan_out_woLFE; - assert( ( nb_channels_in == 16 ) && ( nb_channels_out == 11 ) && "ivas_sba2mc_cldfb; only HOA3 to CICP19 is for now supported!" ); - - for ( n = 0; n < nb_channels_out; n++ ) - { - set_zero( realOut[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_bands ); - set_zero( imagOut[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_bands ); - - for ( m = 0; m < nb_channels_in; m++ ) - { - g = hoa_dec_mtx[SBA_NHARM_HOA3 * n + m]; - p_realOut = realOut[n]; - p_imagOut = imagOut[n]; - for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) - { - p_real = RealBuffer[m][iBlock]; - p_imag = ImagBuffer[m][iBlock]; - for ( iBand = 0; iBand < nb_bands; iBand++ ) - { - *p_realOut = *p_realOut + g * *( p_real++ ); - *p_imagOut = *p_imagOut + g * *( p_imag++ ); - p_realOut++; - p_imagOut++; - } - } - } - } - - for ( n = 0; n < nb_channels_out; n++ ) - { - p_realOut = realOut[n]; - p_imagOut = imagOut[n]; - for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) - { - p_real = RealBuffer[n][iBlock]; - p_imag = ImagBuffer[n][iBlock]; - for ( iBand = 0; iBand < nb_bands; iBand++ ) - { - *( p_real++ ) = *p_realOut++; - *( p_imag++ ) = *p_imagOut++; - } - } - } - - wmops_sub_end(); - - return; -} - +#ifdef FIX_386_CORECODER_RECONFIG /*-------------------------------------------------------------------* - * ivas_sba_remapTCs() + * ivas_sba_set_cna_cng_flag() * - * Get TCs from Ambisonics signal in ACN + * Set CNA/CNG flags in IVAS SBA decoder *-------------------------------------------------------------------*/ -int16_t ivas_sba_remapTCs( - float sba_data[][L_FRAME48k], /* i/o: SBA signals */ - Decoder_Struct *st_ivas, /* i/o: decoder struct */ - const int16_t output_frame /* i : frame length */ -) -{ - int16_t nchan_remapped; - -#ifdef DEBUG_MODE_DIRAC - debug_mode_dirac( sba_data, st_ivas->nchan_transport, output_frame ); -#endif - - nchan_remapped = st_ivas->nchan_transport; - if ( ( st_ivas->sba_mode != SBA_MODE_SPAR && st_ivas->sba_planar && nchan_remapped >= 3 ) || - ( ( st_ivas->sba_mode == SBA_MODE_SPAR ) && nchan_remapped == 3 ) ) - { - - nchan_remapped++; - if ( st_ivas->sba_mode != SBA_MODE_SPAR ) - { - assert( ( ( st_ivas->nchan_transport == 3 ) || ( st_ivas->nchan_transport == 5 ) || ( st_ivas->nchan_transport == 7 ) ) && "Number of channels must be odd for sba planar!" ); - } - - if ( nchan_remapped == 4 ) - { - /*For planar A-format channel 2 and 3 are identical -> Z=0*/ - mvr2r( sba_data[2], sba_data[3], output_frame ); - } - } - - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) - { - int16_t i = 0; - float temp; - - if ( st_ivas->nchan_transport >= 3 ) - { - /*convert WYXZ downmix to WYZX*/ - for ( i = 0; i < output_frame; i++ ) - { - temp = sba_data[2][i]; - sba_data[2][i] = sba_data[3][i]; - sba_data[3][i] = temp; - if ( st_ivas->nchan_transport == 3 ) - { - sba_data[2][i] = 0; - } - } - } - } - else - { - ivas_sba_dmx_dec( sba_data, nchan_remapped, output_frame ); - } - - if ( st_ivas->sba_mode != SBA_MODE_SPAR ) - { - ivas_sba_zero_vert_comp( sba_data, st_ivas->sba_order, st_ivas->sba_planar, output_frame ); - } - return ( nchan_remapped ); -} - - -/*-------------------------------------------------------------------* - * ivas_sba_dmx_dec() - * - * - *-------------------------------------------------------------------*/ - -static void ivas_sba_dmx_dec( - float sba_data[][L_FRAME48k], /* i : SBA signals */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t output_frame /* i : frame length */ +void ivas_sba_set_cna_cng_flag( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { - int16_t i; - float tmp_f[DIRAC_MAX_TRANS_CHANS]; + int16_t n, cpe_id; - if ( nchan_transport >= 7 ) + if ( st_ivas->sba_mode == SBA_MODE_SPAR && st_ivas->nchan_transport == 1 ) { - for ( i = 0; i < output_frame; i++ ) - { - tmp_f[0] = 0.506415f * sba_data[0][i] + 0.506415f * sba_data[1][i] + 0.506415f * sba_data[2][i] + 0.506415f * sba_data[3][i] + 0.506415f * sba_data[4][i] + 0.506415f * sba_data[5][i] + 0.506415f * sba_data[6][i]; - tmp_f[1] = -0.000000f * sba_data[0][i] + 0.531020f * sba_data[1][i] + 0.662171f * sba_data[2][i] + 0.294694f * sba_data[3][i] + -0.294694f * sba_data[4][i] + -0.662171f * sba_data[5][i] + -0.531020f * sba_data[6][i]; - tmp_f[2] = 0.679200f * sba_data[0][i] + 0.423475f * sba_data[1][i] + -0.151136f * sba_data[2][i] + -0.611938f * sba_data[3][i] + -0.611938f * sba_data[4][i] + -0.151136f * sba_data[5][i] + 0.423475f * sba_data[6][i]; - tmp_f[3] = 0.000000f * sba_data[0][i] + 0.833385f * sba_data[1][i] + -0.370891f * sba_data[2][i] + -0.668323f * sba_data[3][i] + 0.668323f * sba_data[4][i] + 0.370891f * sba_data[5][i] + -0.833385f * sba_data[6][i]; - tmp_f[4] = 0.854817f * sba_data[0][i] + -0.190215f * sba_data[1][i] + -0.770164f * sba_data[2][i] + 0.532970f * sba_data[3][i] + 0.532970f * sba_data[4][i] + -0.770164f * sba_data[5][i] + -0.190215f * sba_data[6][i]; - tmp_f[5] = 0.000000f * sba_data[0][i] + 0.691125f * sba_data[1][i] + -1.245365f * sba_data[2][i] + 1.552944f * sba_data[3][i] + -1.552944f * sba_data[4][i] + 1.245365f * sba_data[5][i] + -0.691125f * sba_data[6][i]; - tmp_f[6] = 1.592881f * sba_data[0][i] + -1.435137f * sba_data[1][i] + 0.993145f * sba_data[2][i] + -0.354449f * sba_data[3][i] + -0.354449f * sba_data[4][i] + 0.993145f * sba_data[5][i] + -1.435137f * sba_data[6][i]; - - sba_data[0][i] = tmp_f[0]; - sba_data[1][i] = tmp_f[1]; - sba_data[2][i] = sba_data[7][i]; - sba_data[3][i] = tmp_f[2]; - sba_data[4][i] = tmp_f[3]; - sba_data[8][i] = tmp_f[4]; - sba_data[9][i] = tmp_f[5]; - sba_data[15][i] = tmp_f[6]; - } - - return; + /* skip as done in init function */ + /* st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 0; */ /* Todo: Check if these can be enabled */ + /* st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 0; */ } - else if ( nchan_transport >= 5 ) + else if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) ) { - for ( i = 0; i < output_frame; i++ ) - { - tmp_f[0] = 0.708982f * sba_data[0][i] + 0.708982f * sba_data[1][i] + 0.708982f * sba_data[2][i] + 0.708982f * sba_data[3][i] + 0.708982f * sba_data[4][i]; - tmp_f[1] = 0.000000f * sba_data[0][i] + 1.005966f * sba_data[1][i] + 0.621721f * sba_data[2][i] + -0.621721f * sba_data[3][i] + -1.005966f * sba_data[4][i]; - tmp_f[2] = 1.057735f * sba_data[0][i] + 0.326858f * sba_data[1][i] + -0.855726f * sba_data[2][i] + -0.855726f * sba_data[3][i] + 0.326858f * sba_data[4][i]; - tmp_f[3] = 0.000000f * sba_data[0][i] + 1.079884f * sba_data[1][i] + -1.747289f * sba_data[2][i] + 1.747289f * sba_data[3][i] + -1.079884f * sba_data[4][i]; - tmp_f[4] = 1.837208f * sba_data[0][i] + -1.486333f * sba_data[1][i] + 0.567729f * sba_data[2][i] + 0.567729f * sba_data[3][i] + -1.486333f * sba_data[4][i]; - - sba_data[0][i] = tmp_f[0]; - sba_data[1][i] = tmp_f[1]; - sba_data[2][i] = sba_data[5][i]; - sba_data[3][i] = tmp_f[2]; - sba_data[4][i] = tmp_f[3]; - sba_data[8][i] = tmp_f[4]; - } - - return; + st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 1; + st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag = 1; } - else if ( nchan_transport >= 3 ) + else if ( st_ivas->nchan_transport == 2 ) { - - /*A-format to ACN/SN3D*/ - for ( i = 0; i < output_frame; i++ ) + for ( n = 0; n < CPE_CHANNELS; n++ ) { - tmp_f[0] = 0.5f * ( sba_data[0][i] + sba_data[1][i] + sba_data[2][i] + sba_data[3][i] ); - tmp_f[1] = sba_data[0][i] - sba_data[1][i]; - tmp_f[2] = sba_data[2][i] - sba_data[3][i]; - tmp_f[3] = sba_data[0][i] + sba_data[1][i] - sba_data[2][i] - sba_data[3][i]; - - sba_data[0][i] = tmp_f[0]; - sba_data[1][i] = tmp_f[1]; - sba_data[2][i] = tmp_f[2]; - sba_data[3][i] = tmp_f[3]; + st_ivas->hCPE[0]->hCoreCoder[n]->cna_dirac_flag = 0; /* Todo: Check if these can be enabled */ + st_ivas->hCPE[0]->hCoreCoder[n]->cng_sba_flag = 1; } - - return; - } - else if ( nchan_transport == 2 ) - { - /* do nothing for stereo DMX, upmix done in DirAC*/ - return; - } - else if ( nchan_transport == 1 ) - { - /* do nothing; simply use omni */ - return; } else { - assert( 0 && "SBA: number of transport channels not supported." ); - } -} - - -/*-------------------------------------------------------------------------* - * ivas_ism2sba() - * - * ISM transformed into SBA in TD domain. - *-------------------------------------------------------------------------*/ - -void ivas_ism2sba( - float buffer_td[][L_FRAME48k], /* i/o: TD signal buffers */ - ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ - const ISM_METADATA_HANDLE hIsmMetaData[], /* i : object metadata */ - const int16_t num_objects, /* i : number of objects */ - const int16_t output_frame, /* i : output frame length per channel */ - const int16_t sba_order /* i : Ambisonic (SBA) order */ -) -{ - int16_t i, j, k; - float buffer_tmp[16][L_FRAME48k]; - float gains[16]; - float g1, g2; - int16_t azimuth, elevation; - int16_t sba_num_chans; - - assert( ( sba_order <= 3 ) && "Only order up to 3 is supported!" ); - assert( hIsmRendererData != NULL && "hIsmRendererData not allocated!" ); - - /* Init*/ - sba_num_chans = ( sba_order + 1 ) * ( sba_order + 1 ); - for ( j = 0; j < sba_num_chans; j++ ) - { - set_zero( buffer_tmp[j], output_frame ); - } - - for ( i = 0; i < num_objects; i++ ) - { - azimuth = (int16_t) ( hIsmMetaData[i]->azimuth + 0.5f ); - elevation = (int16_t) ( hIsmMetaData[i]->elevation + 0.5f ); - - /*get HOA gets for direction (ACN/SN3D)*/ - ivas_dirac_dec_get_response( - azimuth, - elevation, - gains, - sba_order ); - - for ( j = 0; j < sba_num_chans; j++ ) + for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { - g2 = 0.f; - for ( k = 0; k < output_frame; k++ ) + for ( n = 0; n < CPE_CHANNELS; n++ ) { - g2 += 1.f / output_frame; - g1 = 1.0f - g2; - buffer_tmp[j][k] += ( g2 * gains[j] + g1 * hIsmRendererData->prev_gains[i][j] ) * buffer_td[i][k]; + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cna_dirac_flag = 0; + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_sba_flag = 0; } - hIsmRendererData->prev_gains[i][j] = gains[j]; } } - for ( j = 0; j < sba_num_chans; j++ ) - { - mvr2r( buffer_tmp[j], buffer_td[j], output_frame ); - } - return; } +#endif /*-------------------------------------------------------------------* - * ivas_sba_dec_decoder() + * ivas_sba_dec_reconfigure() * * Reconfigure IVAS SBA decoder *-------------------------------------------------------------------*/ @@ -450,540 +106,265 @@ ivas_error ivas_sba_dec_reconfigure( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { - int16_t n; - int16_t sce_id, cpe_id; - int16_t nchan_transport; - int16_t nchan_transport_old; - int32_t sba_total_brate; - int16_t nSCE_old; - int16_t nCPE_old; + int16_t nchan_transport_old, nSCE_old, nCPE_old, nchan_hp20_old; AUDIO_CONFIG intern_config_old; - int16_t numCldfbAnalyses_old; - int16_t numCldfbAnalyses; - int16_t numCldfbSyntheses; - int16_t numCldfbSyntheses_old; + int16_t numCldfbAnalyses_old, numCldfbSyntheses_old; int16_t sba_dirac_stereo_flag_old; - uint16_t i; + SBA_MODE sba_mode_old; int32_t ivas_total_brate, last_ivas_total_brate; + RENDERER_TYPE old_renderer_type; + DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; + int16_t band_grouping[IVAS_MAX_NUM_BANDS + 1]; error = IVAS_ERR_OK; - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; - last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; + hDecoderConfig = st_ivas->hDecoderConfig; + ivas_total_brate = hDecoderConfig->ivas_total_brate; + last_ivas_total_brate = st_ivas->last_active_ivas_total_brate; +#ifndef LBR_SBA + sba_mode_old = ivas_sba_mode_select( last_ivas_total_brate ); +#else + sba_mode_old = ivas_sba_mode_select( ); +#endif + st_ivas->sba_mode = sba_mode_old; /*-----------------------------------------------------------------* - * Allocate, initalize, and configure SBA and rendering handles + * Set SBA high-level parameters + * Save old SBA high-level parameters *-----------------------------------------------------------------*/ ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); - numCldfbAnalyses = 0; - sba_total_brate = ivas_total_brate; - - - nSCE_old = st_ivas->nSCE; - nCPE_old = st_ivas->nCPE; - nchan_transport_old = st_ivas->nchan_transport; - sba_dirac_stereo_flag_old = st_ivas->sba_dirac_stereo_flag; - - ivas_sba_config( sba_total_brate, st_ivas->sba_order, -1, &nchan_transport, st_ivas->sba_planar, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, st_ivas->sba_mode ); - st_ivas->nchan_transport = nchan_transport; - - /* renderer might have changed */ - intern_config_old = st_ivas->intern_config; - ivas_renderer_select( st_ivas ); - - /* side effect of the renderer selection can be a changed internal config */ - if ( st_ivas->intern_config != intern_config_old ) - { - ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); - } - - if ( st_ivas->sba_mode != SBA_MODE_SPAR ) +#ifndef SBA_HPF_TUNING_DEC + nchan_hp20_old = getNumChanSynthesis( st_ivas ); +#else + int16_t analysis_order_old; + analysis_order_old = ivas_sba_get_analysis_order( last_ivas_total_brate, st_ivas->sba_order ); + if ( analysis_order_old > 1 ) { - st_ivas->sba_dirac_stereo_flag = ( st_ivas->nchan_transport == 1 && st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ); - if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_order, st_ivas->sba_planar, st_ivas->sba_mode, -1 ) ) != IVAS_ERR_OK ) - { - return error; - } + nchan_hp20_old = 0; } else { - int16_t sba_order_internal; - sba_order_internal = min( st_ivas->sba_order, IVAS_MAX_SBA_ORDER ); - ivas_spar_config( st_ivas->hDecoderConfig->ivas_total_brate, sba_order_internal, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->hSpar->hSparFoa->core_nominal_brate, st_ivas->sid_format ); - - if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->sba_order, st_ivas->sba_planar, - st_ivas->sba_mode, IVAS_MAX_NUM_BANDS - SPAR_DIRAC_SPLIT_START_BAND ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - if ( st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_SBA_LINEAR_DEC && - ( last_ivas_total_brate > IVAS_SID_4k4 || nchan_transport != nchan_transport_old ) && ( st_ivas->sba_mode != SBA_MODE_SPAR ) ) - { - if ( st_ivas->hDirAC != NULL ) - { - if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - if ( ( error = ivas_dirac_dec_config( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } - else if ( st_ivas->renderer_type == RENDERER_DISABLE || ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->sba_mode != SBA_MODE_SPAR ) ) - { - if ( st_ivas->hDirAC != NULL ) - { - ivas_dirac_dec_close( st_ivas->hDirAC ); - st_ivas->hDirAC = NULL; - } - - if ( st_ivas->hVBAPdata != NULL ) - { - vbap_free_data( &( st_ivas->hVBAPdata ) ); - } + nchan_hp20_old = st_ivas->nchan_transport; } +#endif + nSCE_old = st_ivas->nSCE; + nCPE_old = st_ivas->nCPE; + nchan_transport_old = st_ivas->nchan_transport; + sba_dirac_stereo_flag_old = st_ivas->sba_dirac_stereo_flag; + st_ivas->sba_analysis_order = ivas_sba_get_analysis_order( ivas_total_brate, st_ivas->sba_order ); +#ifndef LBR_SBA + st_ivas->sba_mode = ivas_sba_mode_select( ivas_total_brate ); +#else + st_ivas->sba_mode = ivas_sba_mode_select( ); +#endif /*-----------------------------------------------------------------* - * Allocate, initalize, and configure SCE/CPE/MCT handles + * Allocate, initialize, and configure SBA handles *-----------------------------------------------------------------*/ - if ( nchan_transport == nchan_transport_old ) + if ( st_ivas->sba_mode != SBA_MODE_SPAR ) { - for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) - { - st_ivas->hSCE[sce_id]->element_brate = ivas_total_brate / st_ivas->nchan_transport; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ - } + ivas_spar_dec_close( &( st_ivas->hSpar ), hDecoderConfig->output_Fs, 0 ); - for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_analysis_order, st_ivas->sba_mode, -1 ) ) != IVAS_ERR_OK ) { - st_ivas->hCPE[cpe_id]->element_brate = ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS; - - /* prepare bitstream buffers */ - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ - } + return error; } - if ( st_ivas->nCPE > 1 ) - { - if ( ( error = mct_dec_reconfigure( st_ivas, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } - } +#ifdef SBA2MONO + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#else + st_ivas->sba_dirac_stereo_flag = ( st_ivas->nchan_transport == 1 && hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ); +#endif } else { - int16_t nSCE_existing; - int16_t nCPE_existing; - - nSCE_existing = min( nSCE_old, st_ivas->nSCE ); - nCPE_existing = min( nCPE_old, st_ivas->nCPE ); - - /* destroy superfluous core coder elements */ - for ( sce_id = st_ivas->nSCE; sce_id < nSCE_old; sce_id++ ) - { - destroy_sce_dec( st_ivas->hSCE[sce_id] ); - st_ivas->hSCE[sce_id] = NULL; - - /* remove dummy CPE needed for 1TC->Stereo rendering via DFT stereo*/ - if ( sba_dirac_stereo_flag_old ) - { -#ifdef DEBUGGING - assert( st_ivas->hCPE[0] ); -#endif - st_ivas->hCPE[0]->hCoreCoder[0] = st_ivas->hCPE[0]->hCoreCoder[1] = NULL; - destroy_cpe_dec( st_ivas->hCPE[0] ); - st_ivas->hCPE[0] = NULL; - } - } - - for ( cpe_id = st_ivas->nCPE; cpe_id < nCPE_old; cpe_id++ ) - { - destroy_cpe_dec( st_ivas->hCPE[cpe_id] ); - st_ivas->hCPE[cpe_id] = NULL; - } - - if ( st_ivas->nCPE <= 1 && st_ivas->hMCT != NULL ) - { - ivas_mct_dec_close( &st_ivas->hMCT ); - } - - /* special case, if we have MCT now and had a single CPE before, remove the MDCT Stereo handles from the first CPE*/ - if ( st_ivas->nCPE > 1 && nCPE_old == 1 ) - { - count_free( st_ivas->hCPE[0]->hStereoMdct ); - st_ivas->hCPE[0]->hStereoMdct = NULL; - } - - for ( sce_id = 0; sce_id < nSCE_existing; sce_id++ ) - { - st_ivas->hSCE[sce_id]->element_brate = ivas_total_brate / st_ivas->nchan_transport; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ - } - for ( ; sce_id < st_ivas->nSCE; sce_id++ ) - { - if ( ( error = create_sce_dec( st_ivas, sce_id, ivas_total_brate / st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) - { - return error; - } - } + int16_t sba_order_internal; + SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; - for ( cpe_id = 0; cpe_id < nCPE_existing; cpe_id++ ) - { - st_ivas->hCPE[cpe_id]->element_brate = ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS; + sba_order_internal = min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ); - /* prepare bitstream buffers */ - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ - } - } - for ( ; cpe_id < st_ivas->nCPE; cpe_id++ ) + if ( hSpar != NULL ) { - if ( ( error = create_cpe_dec( st_ivas, cpe_id, ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS ) ) != IVAS_ERR_OK ) + if ( ( hSpar->hPCA != NULL ) && ( ( hDecoderConfig->ivas_total_brate != PCA_BRATE ) || ( sba_order_internal != 1 ) ) ) { - return error; + free( st_ivas->hSpar->hPCA ); + hSpar->hPCA = NULL; } - } - /* create CPE element for DFT Stereo like upmix */ - if ( st_ivas->sba_dirac_stereo_flag ) - { - if ( ( error = create_cpe_dec( st_ivas, 0, ivas_total_brate / ( st_ivas->nSCE + st_ivas->nCPE ) ) ) != IVAS_ERR_OK ) + if ( nchan_transport_old != ivas_get_sba_num_TCs( ivas_total_brate, sba_order_internal ) ) { - return error; - } - st_ivas->hCPE[0]->hCoreCoder[0] = st_ivas->hSCE[0]->hCoreCoder[0]; /* don't allocate unnecessary core coder, simply point to core coder of SCE element */ - } + ivas_spar_dec_close( &( st_ivas->hSpar ), hDecoderConfig->output_Fs, 1 ); - if ( st_ivas->nCPE > 1 && nCPE_old <= 1 ) - { - if ( nCPE_old == 1 ) - { - /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handles for MCT */ - for ( n = 0; n < CPE_CHANNELS; n++ ) + if ( ( error = ivas_spar_dec_open( st_ivas, 1 ) ) != IVAS_ERR_OK ) { - st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; - st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[0]->element_brate / FRAMES_PER_SEC ); - st_ivas->hCPE[0]->hCoreCoder[n]->igf = 0; + return error; } } - if ( ( error = create_mct_dec( st_ivas ) ) != IVAS_ERR_OK ) - { - return error; - } + ivas_spar_config( ivas_total_brate, sba_order_internal, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &hSpar->core_nominal_brate, st_ivas->sid_format ); } - else if ( st_ivas->hMCT != NULL && st_ivas->nCPE > 1 ) + else { - if ( ( error = mct_dec_reconfigure( st_ivas, st_ivas->nCPE != nCPE_old ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_spar_dec_open( st_ivas, 0 ) ) != IVAS_ERR_OK ) { return error; } } - /* special case, if we have a single CPE and had MCT before we need to init the MDCT stereo handles here */ - if ( st_ivas->nCPE == 1 && nCPE_old > 1 ) - { - if ( ( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); - } - - st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->use_itd = 0; - st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->reverse_dmx = 0; - st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->smooth_ratio = 1.f; - - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - /* reset mct_chan_mode */ - st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; - } - } - - /*-----------------------------------------------------------------* - * HP20 memories - *-----------------------------------------------------------------*/ - - if ( nchan_transport > nchan_transport_old ) - { - /* create additional hp20 mems */ - float **old_mem_hp20_out; - uint16_t n_old; - - if ( sba_dirac_stereo_flag_old ) - { - n_old = CPE_CHANNELS; - } - else - { - n_old = nchan_transport_old; - } - n = st_ivas->nchan_transport; - - /* save old mem_hp_20 pointer */ - old_mem_hp20_out = st_ivas->mem_hp20_out; - st_ivas->mem_hp20_out = NULL; - if ( ( st_ivas->mem_hp20_out = (float **) count_malloc( n * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); - } - - for ( i = 0; i < n_old; i++ ) - { - st_ivas->mem_hp20_out[i] = old_mem_hp20_out[i]; - old_mem_hp20_out[i] = NULL; - } - for ( ; i < nchan_transport; i++ ) - { - if ( ( st_ivas->mem_hp20_out[i] = (float *) count_malloc( L_HP20_MEM * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); - } - - set_f( st_ivas->mem_hp20_out[i], 0.0f, L_HP20_MEM ); - } - - count_free( old_mem_hp20_out ); - old_mem_hp20_out = NULL; - } - else if ( nchan_transport < nchan_transport_old ) - { - /* remove superfluous hp20 mems */ - float **old_mem_hp20_out; - - if ( st_ivas->sba_dirac_stereo_flag ) - { - n = CPE_CHANNELS; - } - else - { - n = st_ivas->nchan_transport; - } - - /* save old mem_hp_20 pointer */ - old_mem_hp20_out = st_ivas->mem_hp20_out; - st_ivas->mem_hp20_out = NULL; - if ( ( st_ivas->mem_hp20_out = (float **) count_malloc( n * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); - } - - for ( i = 0; i < n; i++ ) - - { - st_ivas->mem_hp20_out[i] = old_mem_hp20_out[i]; - old_mem_hp20_out[i] = NULL; - } - for ( ; i < nchan_transport_old; i++ ) - { - count_free( old_mem_hp20_out[i] ); - old_mem_hp20_out[i] = NULL; - } + hSpar = st_ivas->hSpar; +#ifdef SBA2MONO + st_ivas->sba_dirac_stereo_flag = ivas_get_sba_dirac_stereo_flag( st_ivas ); +#else + st_ivas->sba_dirac_stereo_flag = 0; +#endif + } - count_free( old_mem_hp20_out ); - old_mem_hp20_out = NULL; - } + if ( st_ivas->nchan_transport == 1 ) + { + st_ivas->element_mode_init = IVAS_SCE; + } + else + { + st_ivas->element_mode_init = IVAS_CPE_MDCT; } /*-----------------------------------------------------------------* - * CLDFB instances + * Renderer selection *-----------------------------------------------------------------*/ - ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses, &numCldfbSyntheses ); + /* renderer might have changed */ + intern_config_old = st_ivas->intern_config; + old_renderer_type = st_ivas->renderer_type; + ivas_renderer_select( st_ivas ); - /* special case, if there was one transport channel in the previous frame and more than one in the current frame, - remove the second CLDFB here, it was for CNA/CNG */ - if ( nchan_transport_old == 1 && numCldfbAnalyses_old == 2 && nchan_transport > 1 ) + /* side effect of the renderer selection can be a changed internal config */ + if ( st_ivas->intern_config != intern_config_old ) { - deleteCldfb( &( st_ivas->cldfbAnaDec[1] ) ); - st_ivas->cldfbAnaDec[1] = NULL; - numCldfbAnalyses_old--; + ivas_output_init( &( st_ivas->hIntSetup ), st_ivas->intern_config ); } - /* Analysis*/ - if ( numCldfbAnalyses_old > numCldfbAnalyses ) - { - /* delete superfluous CLDFB synthesis instances */ - for ( i = numCldfbAnalyses; i < numCldfbAnalyses_old; i++ ) - { - deleteCldfb( &( st_ivas->cldfbAnaDec[i] ) ); - st_ivas->cldfbAnaDec[i] = NULL; - } - } - else if ( numCldfbAnalyses_old < numCldfbAnalyses ) - { - /* create additional CLDFB synthesis instances */ - for ( i = numCldfbAnalyses_old; i < numCldfbAnalyses; i++ ) - { - if ( ( error = openCldfb( &( st_ivas->cldfbAnaDec[i] ), CLDFB_ANALYSIS, st_ivas->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } + /*-------------------------------------------------------------------* + * Reallocate and initialize binaural rendering handles + *--------------------------------------------------------------------*/ - /* Synthesis */ - if ( numCldfbSyntheses_old > numCldfbSyntheses ) + if ( st_ivas->hBinRenderer == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) { - /* delete superfluous CLDFB synthesis instances */ - for ( i = numCldfbSyntheses; i < numCldfbSyntheses_old; i++ ) + /* open fastconv binaural renderer */ + if ( ( error = ivas_binRenderer_open( st_ivas ) ) != IVAS_ERR_OK ) { - deleteCldfb( &( st_ivas->cldfbSynDec[i] ) ); - st_ivas->cldfbSynDec[i] = NULL; + return error; } } - else if ( numCldfbSyntheses_old < numCldfbSyntheses ) + else if ( st_ivas->hBinRenderer != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV && st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV_ROOM ) ) { - /* create additional CLDFB synthesis instances */ - for ( i = numCldfbSyntheses_old; i < numCldfbSyntheses; i++ ) - { - if ( ( error = openCldfb( &( st_ivas->cldfbSynDec[i] ), CLDFB_SYNTHESIS, st_ivas->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) - { - return error; - } - } + ivas_binRenderer_close( &st_ivas->hBinRenderer ); } - /*-----------------------------------------------------------------* - * Set CNA/CNG flags - *-----------------------------------------------------------------*/ - - if ( st_ivas->sba_mode == SBA_MODE_SPAR && st_ivas->nchan_transport == 1 ) - { - /* skip as done in init function */ - } - else if ( st_ivas->nchan_transport == 1 && ( ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirAC->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) || ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) + if ( st_ivas->renderer_type != old_renderer_type ) { - st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag = 1; - st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag = 1; - } - else if ( st_ivas->nchan_transport == 2 ) - { - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - for ( n = 0; n < CPE_CHANNELS; n++ ) + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) { - st_ivas->hCPE[0]->hCoreCoder[n]->cng_dirac_flag = 1; - st_ivas->hCPE[0]->hCoreCoder[n]->cng_spar_flag = 1; + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } } - } - else - { - for ( n = 0; n < CPE_CHANNELS; n++ ) + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) { - st_ivas->hCPE[0]->hCoreCoder[n]->cna_dirac_flag = 0; - st_ivas->hCPE[0]->hCoreCoder[n]->cng_dirac_flag = 1; + return error; } } } - else + else if ( st_ivas->hDiracDecBin != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) ) { - for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + } + + if ( ( ( st_ivas->renderer_type != RENDERER_DISABLE ) && ( st_ivas->renderer_type != RENDERER_SBA_LINEAR_DEC ) ) || ( sba_mode_old != st_ivas->sba_mode ) || ( ( st_ivas->sba_mode == SBA_MODE_SPAR ) && ( ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA ) && ( st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_STEREO ) && ( st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_MONO ) ) ) ) + { + DIRAC_CONFIG_FLAG flag_config; + + flag_config = DIRAC_OPEN; + if ( st_ivas->hDirAC != NULL ) { - for ( n = 0; n < CPE_CHANNELS; n++ ) + flag_config = DIRAC_RECONFIGURE_MODE; + if ( ( sba_mode_old == st_ivas->sba_mode ) && ( st_ivas->sba_mode != SBA_MODE_SPAR ) ) { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cna_dirac_flag = 0; - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_dirac_flag = 0; - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_spar_flag = 0; + flag_config = DIRAC_RECONFIGURE; } } - } - /* special case, if the decoder goes from 1TC DTX to 2TC active frame (in case the bitstream started with an SBA SID frame), allocate DTX mems */ - if ( last_ivas_total_brate <= IVAS_SID_4k4 && st_ivas->nCPE >= 1 ) - { - if ( ( error = initMdctStereoDtxData( st_ivas->hCPE[0] ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_dec_config( st_ivas, flag_config ) ) != IVAS_ERR_OK ) { return error; } } - /*-------------------------------------------------------------------* - * Reallocate and initialize binaural rendering handles - *--------------------------------------------------------------------*/ - - if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) && st_ivas->hBinRenderer == NULL ) + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - /* open fastconv binaural renderer */ - if ( ( error = ivas_binRenderer_open( st_ivas ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_sba_config( st_ivas->hQMetaData, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->element_mode_init, ivas_total_brate, st_ivas->sba_analysis_order, st_ivas->sba_mode, IVAS_MAX_NUM_BANDS - SPAR_DIRAC_SPLIT_START_BAND ) ) != IVAS_ERR_OK ) { return error; } } - else if ( st_ivas->hBinRenderer != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV && st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV_ROOM ) ) + + if ( ( ( hDecoderConfig->output_config == AUDIO_CONFIG_FOA ) || ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) || ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO ) ) && ( ( sba_mode_old != st_ivas->sba_mode ) && ( st_ivas->sba_mode == SBA_MODE_SPAR ) ) ) { - ivas_binRenderer_close( &st_ivas->hBinRenderer ); + ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); + + st_ivas->hSpar->enc_param_start_band = min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); + + ivas_dirac_config_bands( band_grouping, IVAS_MAX_NUM_BANDS, (int16_t) ( st_ivas->hDecoderConfig->output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ), + st_ivas->hSpar->dirac_to_spar_md_bands, st_ivas->hQMetaData->useLowerBandRes, st_ivas->hSpar->enc_param_start_band, 0 ); } - if ( st_ivas->hDiracDecBin == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) + else if ( st_ivas->renderer_type == RENDERER_DISABLE || ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->sba_mode != SBA_MODE_SPAR ) ) { - /* open parametric binaural renderer */ - if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) - { - return error; - } + ivas_dirac_dec_close( &( st_ivas->hDirAC ) ); + + vbap_free_data( &( st_ivas->hVBAPdata ) ); } - else if ( st_ivas->hDiracDecBin != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) ) + + if ( st_ivas->hDirAC != NULL && st_ivas->sba_mode == SBA_MODE_SPAR ) { - ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); + mvs2s( st_ivas->hDirAC->dirac_to_spar_md_bands, st_ivas->hSpar->dirac_to_spar_md_bands, DIRAC_MAX_NBANDS ); + st_ivas->hSpar->enc_param_start_band = st_ivas->hDirAC->hConfig->enc_param_start_band; } - return error; -} - + /*-----------------------------------------------------------------* + * Allocate, initialize, and configure SCE/CPE/MCT handles + *-----------------------------------------------------------------*/ -#ifdef DEBUG_MODE_DIRAC -/*-----------------------------------------------------------------------* - * Debugging function - *-----------------------------------------------------------------------*/ + if ( ( error = ivas_corecoder_dec_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, sba_dirac_stereo_flag_old, st_ivas->hDecoderConfig->ivas_total_brate / st_ivas->nchan_transport, ( st_ivas->hDecoderConfig->ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS ) ) != IVAS_ERR_OK ) + { + return error; + } -static void debug_mode_dirac( - float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], - const int16_t nchan_transport, - const int16_t output_frame ) -{ - int16_t i, n; - int16_t tmp[L_FRAME48k]; - char file_name[50] = { 0 }; + /*-----------------------------------------------------------------* + * HP20 memories + *-----------------------------------------------------------------*/ -#ifdef DEBUG_MODE_DIRAC_NOCORE - for ( n = 0; n < nchan_transport; n++ ) + if ( ( error = ivas_hp20_dec_reconfig( st_ivas, nchan_hp20_old ) ) != IVAS_ERR_OK ) { - sprintf( file_name, "./res/ivas_dirac_enc_%d.%d.pcm", n, (int16_t) ( output_frame * 0.05 ) ); - dbgread( tmp, sizeof( int16_t ), output_frame, file_name ); - for ( i = 0; i < output_frame; i++ ) - { - output[n][i] = (float) ( tmp[i] ); - } + return error; } -#else - for ( n = 0; n < nchan_transport; n++ ) - { - for ( i = 0; i < output_frame; i++ ) - { - tmp[i] = (int16_t) ( output[n][i] + 0.5f ); - } - sprintf( file_name, "./res/ivas_dirac_dec_%d.%d.pcm", n, (int16_t) ( output_frame * 0.05 ) ); - dbgwrite( tmp, sizeof( int16_t ), output_frame, 1, file_name ); + /*-----------------------------------------------------------------* + * CLDFB instances + *-----------------------------------------------------------------*/ + + if ( ( error = ivas_cldfb_dec_reconfig( st_ivas, nchan_transport_old, numCldfbAnalyses_old, numCldfbSyntheses_old ) ) != IVAS_ERR_OK ) + { + return error; } -#endif - return; + return error; } -#endif diff --git a/lib_dec/ivas_sba_dirac_stereo_dec.c b/lib_dec/ivas_sba_dirac_stereo_dec.c index e4ab91a7d7d531748398e61905d17472efdd0d2c..82ccaceea92e266ab569af6a080a9cb4cebebf76 100644 --- a/lib_dec/ivas_sba_dirac_stereo_dec.c +++ b/lib_dec/ivas_sba_dirac_stereo_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,47 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" + + +#ifdef SBA2MONO +/*-------------------------------------------------------------------* + * ivas_get_sba_dirac_stereo_flag() + * + * Set sba_dirac_stereo_flag + *-------------------------------------------------------------------*/ + +int16_t ivas_get_sba_dirac_stereo_flag( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + int16_t sba_dirac_stereo_flag; + AUDIO_CONFIG output_config; + + sba_dirac_stereo_flag = 0; + output_config = st_ivas->hDecoderConfig->output_config; + + if ( st_ivas->ivas_format == SBA_FORMAT || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) + { + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + if ( output_config == AUDIO_CONFIG_STEREO || ( output_config == AUDIO_CONFIG_MONO && st_ivas->nchan_transport == 1 ) ) + { + sba_dirac_stereo_flag = 1; + } + } + else + { + if ( st_ivas->nchan_transport == 1 && output_config == AUDIO_CONFIG_STEREO ) + { + sba_dirac_stereo_flag = 1; + } + } + } + + return sba_dirac_stereo_flag; +} +#endif /*-------------------------------------------------------------------* @@ -90,7 +130,8 @@ void ivas_sba_dirac_stereo_config( static int16_t ivas_sba_dirac_stereo_band_config( int16_t *band_limits, /* o : DFT band limits */ const int32_t output_Fs, /* i : output sampling rate */ - const int16_t NFFT /* i : analysis/synthesis window length */ + const int16_t NFFT, /* i : analysis/synthesis window length */ + const int16_t spar_flag /* i : SPAR or DirAC band grouping */ ) { int16_t i; @@ -98,6 +139,16 @@ static int16_t ivas_sba_dirac_stereo_band_config( int16_t nbands, num_cldfb_bands; nbands = SBA_DIRAC_STEREO_NUM_BANDS; + + if ( spar_flag ) + { + nbands = IVAS_MAX_NUM_BANDS; + } + else + { + nbands = 5; + } + num_cldfb_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); bins_per_cldfb_band = NFFT / ( 2 * num_cldfb_bands ); @@ -105,7 +156,19 @@ static int16_t ivas_sba_dirac_stereo_band_config( band_limits[0] = 1; for ( i = 1; i < nbands; i++ ) { - band_limits[i] = DirAC_band_grouping_5[i] * bins_per_cldfb_band; + if ( spar_flag ) + { + band_limits[i] = DirAC_band_grouping_12[i] * bins_per_cldfb_band; + } + else + { + band_limits[i] = DirAC_band_grouping_5[i] * bins_per_cldfb_band; + } + if ( band_limits[i] >= NFFT / 2 ) + { + nbands = i; + break; + } } band_limits[nbands] = NFFT / 2; @@ -158,33 +221,35 @@ static void map_params_dirac_to_stereo( float synth[], /* i : decoded downmix signal */ float DFT[STEREO_DFT_BUF_MAX], /* i/o: DFT buffer */ const uint8_t b_wide_panning, /* i : flag indicating wider panning */ - const int16_t L_frame /* i : core signal length */ - + const int16_t L_frame, /* i : core signal length */ + const int16_t mcmasa /* i : McMASA flag */ ) { - int16_t i, b, k, block; + int16_t i, b, k; int16_t k_offset; - int16_t nbands, nBlocks, block_len; + int16_t nbands, nBlocks; + int16_t block; + int16_t block_len; int16_t azimuth[MAX_PARAM_SPATIAL_SUBFRAMES][SBA_DIRAC_STEREO_NUM_BANDS]; int16_t elevation[MAX_PARAM_SPATIAL_SUBFRAMES][SBA_DIRAC_STEREO_NUM_BANDS]; float diffuseness[SBA_DIRAC_STEREO_NUM_BANDS]; + float block_nrg[MAX_PARAM_SPATIAL_SUBFRAMES]; + float nrg_norm1, nrg_norm2; + float *pSynth; float surrCoh[SBA_DIRAC_STEREO_NUM_BANDS]; + float *pDFT; float subframe_band_nrg[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS]; float smooth_long_avg[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS]; float smooth_short_avg[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS]; - float block_nrg[MAX_PARAM_SPATIAL_SUBFRAMES]; - float nrg_norm1, nrg_norm2; + float *side_gain, *res_pred_gain; - float *pSynth, *pDFT; IVAS_QDIRECTION *q_direction; - nBlocks = MAX_PARAM_SPATIAL_SUBFRAMES; - nbands = SBA_DIRAC_STEREO_NUM_BANDS; + nbands = hStereoDft->nbands; k_offset = STEREO_DFT_OFFSET; side_gain = hStereoDft->side_gain + k_offset * STEREO_DFT_BAND_MAX; res_pred_gain = hStereoDft->res_pred_gain + k_offset * STEREO_DFT_BAND_MAX; - q_direction = &( hQMetaData->q_direction[0] ); /* gain smoothing factor */ @@ -233,99 +298,102 @@ static void map_params_dirac_to_stereo( } /* apply upper bounds depending on band */ - hStereoDft->smooth_fac[0][b] = min( max_smooth_gains[b], hStereoDft->smooth_fac[0][b] ); - hStereoDft->smooth_fac[1][b] = min( max_smooth_gains[b], hStereoDft->smooth_fac[1][b] ); + hStereoDft->smooth_fac[0][b] = max( hStereoDft->min_smooth_gains[b], min( hStereoDft->max_smooth_gains[b], hStereoDft->smooth_fac[0][b] ) ); + hStereoDft->smooth_fac[1][b] = max( hStereoDft->min_smooth_gains[b], min( hStereoDft->max_smooth_gains[b], hStereoDft->smooth_fac[1][b] ) ); } pDFT += STEREO_DFT32MS_N_MAX; } - /* calculate block energies for side gain weighting (combine angles of 2 DirAC blocks to side gain for 1 DFT Stereo subframe; 4 blocks and 2 subframes overall) */ - pSynth = synth; - block_len = L_frame / nBlocks; - for ( block = 0; block < nBlocks; block++ ) + if ( mcmasa ) { - block_nrg[block] = 0.f; - for ( i = 0; i < block_len; i++ ) - { - block_nrg[block] += pSynth[i] * pSynth[i]; - } - block_nrg[block] = sqrtf( block_nrg[block] ); - pSynth += block_len; - } - nrg_norm1 = 1 / ( block_nrg[0] + block_nrg[1] + EPSILON ); - nrg_norm2 = 1 / ( block_nrg[2] + block_nrg[3] + EPSILON ); - - /* extract DirAC parameters from metadata */ - for ( b = 0; b < nbands; b++ ) - { - diffuseness[b] = 1.0f - q_direction->band_data[b].energy_ratio[0]; - if ( hQMetaData->surcoh_band_data != NULL ) - { - surrCoh[b] = hQMetaData->surcoh_band_data[b].surround_coherence[0] / 255.0f; - } - else - { - surrCoh[b] = 0.0f; - } - + /* calculate block energies for side gain weighting (combine angles of 2 DirAC blocks to side gain for 1 DFT Stereo subframe; 4 blocks and 2 subframes overall) */ + pSynth = synth; + block_len = L_frame / nBlocks; for ( block = 0; block < nBlocks; block++ ) { - int16_t block_metadata; - - if ( hQMetaData->useLowerRes ) - { - block_metadata = 0; - } - else - { - block_metadata = block; - } - if ( q_direction->band_data[b].azimuth[block_metadata] < 0.f ) + block_nrg[block] = 0.f; + for ( i = 0; i < block_len; i++ ) { - q_direction->band_data[b].azimuth[block_metadata] += 360.f; + block_nrg[block] += pSynth[i] * pSynth[i]; } - azimuth[block][b] = (int16_t) q_direction->band_data[b].azimuth[block_metadata]; - elevation[block][b] = (int16_t) q_direction->band_data[b].elevation[block_metadata]; + block_nrg[block] = sqrtf( block_nrg[block] ); + pSynth += block_len; } - } + nrg_norm1 = 1 / ( block_nrg[0] + block_nrg[1] + EPSILON ); + nrg_norm2 = 1 / ( block_nrg[2] + block_nrg[3] + EPSILON ); - /* map angles (azi, ele), surround coherence, and diffuseness to DFT Stereo side and prediction gains */ - for ( b = 0; b < hStereoDft->nbands; b++ ) - { - /* combine angles of first 2 blocks to side gain of first subframe */ - side_gain[b] = 0.f; - for ( block = 0; block < nBlocks / 2; block++ ) + /* extract DirAC parameters from metadata */ + for ( b = 0; b < nbands; b++ ) { - if ( b_wide_panning == 1 ) + diffuseness[b] = 1.0f - q_direction->band_data[b].energy_ratio[0]; + if ( hQMetaData->surcoh_band_data != NULL ) { - /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ - side_gain[b] += nrg_norm1 * block_nrg[block] * get_panning( azimuth[block][b], elevation[block][b] ); + surrCoh[b] = hQMetaData->surcoh_band_data[b].surround_coherence[0] / 255.0f; } else { - side_gain[b] += nrg_norm1 * block_nrg[block] * sinf( azimuth[block][b] * EVS_PI / 180 ) * cosf( elevation[block][b] * EVS_PI / 180 ); + surrCoh[b] = 0.0f; + } + + for ( block = 0; block < nBlocks; block++ ) + { + int16_t block_metadata; + + if ( hQMetaData->useLowerRes ) + { + block_metadata = 0; + } + else + { + block_metadata = block; + } + if ( q_direction->band_data[b].azimuth[block_metadata] < 0.f ) + { + q_direction->band_data[b].azimuth[block_metadata] += 360.f; + } + azimuth[block][b] = (int16_t) q_direction->band_data[b].azimuth[block_metadata]; + elevation[block][b] = (int16_t) q_direction->band_data[b].elevation[block_metadata]; } } - /* combine angles of last 2 blocks to side gain of second subframe */ - side_gain[b + STEREO_DFT_BAND_MAX] = 0.f; - for ( block = nBlocks / 2; block < nBlocks; block++ ) + /* map angles (azi, ele), surround coherence, and diffuseness to DFT Stereo side and prediction gains */ + for ( b = 0; b < hStereoDft->nbands; b++ ) { - if ( b_wide_panning == 1 ) + /* combine angles of first 2 blocks to side gain of first subframe */ + side_gain[b] = 0.f; + for ( block = 0; block < nBlocks / 2; block++ ) { - /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ - side_gain[b + STEREO_DFT_BAND_MAX] += nrg_norm2 * block_nrg[block] * get_panning( azimuth[block][b], elevation[block][b] ); + if ( b_wide_panning == 1 ) + { + /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ + side_gain[b] += nrg_norm1 * block_nrg[block] * get_panning( azimuth[block][b], elevation[block][b] ); + } + else + { + side_gain[b] += nrg_norm1 * block_nrg[block] * sinf( azimuth[block][b] * EVS_PI / 180 ) * cosf( elevation[block][b] * EVS_PI / 180 ); + } } - else + + /* combine angles of last 2 blocks to side gain of second subframe */ + side_gain[b + STEREO_DFT_BAND_MAX] = 0.f; + for ( block = nBlocks / 2; block < nBlocks; block++ ) { - side_gain[b + STEREO_DFT_BAND_MAX] += nrg_norm2 * block_nrg[block] * sinf( azimuth[block][b] * EVS_PI / 180 ) * cosf( elevation[block][b] * EVS_PI / 180 ); + if ( b_wide_panning == 1 ) + { + /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ + side_gain[b + STEREO_DFT_BAND_MAX] += nrg_norm2 * block_nrg[block] * get_panning( azimuth[block][b], elevation[block][b] ); + } + else + { + side_gain[b + STEREO_DFT_BAND_MAX] += nrg_norm2 * block_nrg[block] * sinf( azimuth[block][b] * EVS_PI / 180 ) * cosf( elevation[block][b] * EVS_PI / 180 ); + } } - } - side_gain[b] *= sqrtf( 1.f - diffuseness[b] ); - side_gain[b + STEREO_DFT_BAND_MAX] *= sqrtf( 1.f - diffuseness[b] ); - res_pred_gain[b] = diffuseness[b] * ( 1.0f - surrCoh[b] ); - res_pred_gain[b + STEREO_DFT_BAND_MAX] = diffuseness[b] * ( 1.0f - surrCoh[b] ); + side_gain[b] *= sqrtf( 1.f - diffuseness[b] ); + side_gain[b + STEREO_DFT_BAND_MAX] *= sqrtf( 1.f - diffuseness[b] ); + res_pred_gain[b] = diffuseness[b] * ( 1.0f - surrCoh[b] ); + res_pred_gain[b + STEREO_DFT_BAND_MAX] = diffuseness[b] * ( 1.0f - surrCoh[b] ); + } } hStereoDft->frame_nodata = 0; @@ -420,26 +488,146 @@ static void ivas_sba_dirac_stereo_compute_hb_gain( *-------------------------------------------------------------------*/ static void ivas_sba_dirac_stereo_upmix_hb( - float hb_stereo_synth[CPE_CHANNELS][L_FRAME48k], /* i/o: stereo HB synthesis signal */ - float hb_synth[L_FRAME48k], /* i : HB signal */ - float hb_gain[NB_DIV], /* i : side gains for HB signal */ - const int16_t output_frame /* i : output frame length per channel */ + float hb_stereo_synth[CPE_CHANNELS][L_FRAME48k], /* i/o: stereo HB synthesis signal */ + float hb_synth[L_FRAME48k], /* i : HB signal */ + float hb_gain[NB_DIV], /* i : side gains for HB signal */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t mcmasa, /* i : McMASA flag */ +#ifdef SBA2MONO + const int16_t sba_mono_flag, /* i : flag for mono output */ + const int16_t bwidth, /* i : bandwidth of signal */ +#endif + const STEREO_DFT_DEC_DATA_HANDLE hStereoDft /* i : Stereo DFT handle for mixing matrix */ ) { int16_t i; +#ifdef SBA2MONO + float gp, gm; + float gain_fac; +#endif - for ( i = 0; i < output_frame / 2; i++ ) + if ( !mcmasa ) { - hb_stereo_synth[0][i] = 0.5f * hb_synth[i] + 0.5f * hb_gain[0] * hb_synth[i]; - hb_stereo_synth[1][i] = 0.5f * hb_synth[i] - 0.5f * hb_gain[0] * hb_synth[i]; - } +#ifdef SBA2MONO + gain_fac = ( bwidth == FB ) ? 0.25f : 0.33f; /* last matrix element not used for SWB, divide by 3 instead of 4*/ + if ( sba_mono_flag ) + { + gp = hStereoDft->mixer_mat_smooth[0][0][8] + hStereoDft->mixer_mat_smooth[0][0][9] + + hStereoDft->mixer_mat_smooth[0][0][10]; + if ( bwidth == FB ) + { + gp += hStereoDft->mixer_mat_smooth[0][0][11]; + } + for ( i = 0; i < output_frame / 2; i++ ) + { + hb_stereo_synth[0][i] = hb_synth[i] * gain_fac * gp; + } + gp = hStereoDft->mixer_mat_smooth[0][0][8 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][0][9 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][10 + IVAS_MAX_NUM_BANDS]; + if ( bwidth == FB ) + { + gp += hStereoDft->mixer_mat_smooth[0][0][11 + IVAS_MAX_NUM_BANDS]; + } + for ( i = output_frame / 2; i < output_frame; i++ ) + { + hb_stereo_synth[0][i] = hb_synth[i] * gain_fac * gp; + } + } + else + { + gp = hStereoDft->mixer_mat_smooth[0][0][8] + hStereoDft->mixer_mat_smooth[1][0][8] + + hStereoDft->mixer_mat_smooth[0][0][9] + hStereoDft->mixer_mat_smooth[1][0][9] + + hStereoDft->mixer_mat_smooth[0][0][10] + hStereoDft->mixer_mat_smooth[1][0][10]; + if ( bwidth == FB ) + { + gp += hStereoDft->mixer_mat_smooth[0][0][11] + hStereoDft->mixer_mat_smooth[1][0][11]; + } + + gm = hStereoDft->mixer_mat_smooth[0][0][8] - hStereoDft->mixer_mat_smooth[1][0][8] + + hStereoDft->mixer_mat_smooth[0][0][9] - hStereoDft->mixer_mat_smooth[1][0][9] + + hStereoDft->mixer_mat_smooth[0][0][10] - hStereoDft->mixer_mat_smooth[1][0][10]; + if ( bwidth == FB ) + { + gm += hStereoDft->mixer_mat_smooth[0][0][11] - hStereoDft->mixer_mat_smooth[1][0][11]; + } + + for ( i = 0; i < output_frame / 2; i++ ) + { + hb_stereo_synth[0][i] = 0.5f * hb_synth[i] * gain_fac * gp; + hb_stereo_synth[1][i] = 0.5f * hb_synth[i] * gain_fac * gm; + } + + gp = hStereoDft->mixer_mat_smooth[0][0][8 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][8 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][9 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][9 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][10 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][10 + IVAS_MAX_NUM_BANDS]; + if ( bwidth == FB ) + { + gp += hStereoDft->mixer_mat_smooth[0][0][11 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][11 + IVAS_MAX_NUM_BANDS]; + } + + gm = hStereoDft->mixer_mat_smooth[0][0][8 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][8 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][9 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][9 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][10 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][10 + IVAS_MAX_NUM_BANDS]; + if ( bwidth == FB ) + { + gm += hStereoDft->mixer_mat_smooth[0][0][11 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][11 + IVAS_MAX_NUM_BANDS]; + } - for ( i = output_frame / 2; i < output_frame; i++ ) + for ( i = output_frame / 2; i < output_frame; i++ ) + { + hb_stereo_synth[0][i] = 0.5f * hb_synth[i] * gain_fac * gp; + hb_stereo_synth[1][i] = 0.5f * hb_synth[i] * gain_fac * gm; + } + } +#else + for ( i = 0; i < output_frame / 2; i++ ) + { + float gp = hStereoDft->mixer_mat_smooth[0][0][8] + hStereoDft->mixer_mat_smooth[1][0][8] + + hStereoDft->mixer_mat_smooth[0][0][9] + hStereoDft->mixer_mat_smooth[1][0][9] + + hStereoDft->mixer_mat_smooth[0][0][10] + hStereoDft->mixer_mat_smooth[1][0][10] + + hStereoDft->mixer_mat_smooth[0][0][11] + hStereoDft->mixer_mat_smooth[1][0][11]; + + float gm = hStereoDft->mixer_mat_smooth[0][0][8] - hStereoDft->mixer_mat_smooth[1][0][8] + + hStereoDft->mixer_mat_smooth[0][0][9] - hStereoDft->mixer_mat_smooth[1][0][9] + + hStereoDft->mixer_mat_smooth[0][0][10] - hStereoDft->mixer_mat_smooth[1][0][10] + + hStereoDft->mixer_mat_smooth[0][0][11] - hStereoDft->mixer_mat_smooth[1][0][11]; + + hb_stereo_synth[0][i] = 0.5f * hb_synth[i] * 0.25f * gp; + hb_stereo_synth[1][i] = 0.5f * hb_synth[i] * 0.25f * gm; + } + for ( i = output_frame / 2; i < output_frame; i++ ) + { + float gp = hStereoDft->mixer_mat_smooth[0][0][8 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][8 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][9 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][9 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][10 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][10 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][11 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][0][11 + IVAS_MAX_NUM_BANDS]; + + float gm = hStereoDft->mixer_mat_smooth[0][0][8 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][8 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][9 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][9 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][10 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][10 + IVAS_MAX_NUM_BANDS] + + hStereoDft->mixer_mat_smooth[0][0][11 + IVAS_MAX_NUM_BANDS] - hStereoDft->mixer_mat_smooth[1][0][11 + IVAS_MAX_NUM_BANDS]; + + hb_stereo_synth[0][i] = 0.5f * hb_synth[i] * 0.25f * gp; + hb_stereo_synth[1][i] = 0.5f * hb_synth[i] * 0.25f * gm; + } +#endif + } + else { - hb_stereo_synth[0][i] = 0.5f * hb_synth[i] + 0.5f * hb_gain[1] * hb_synth[i]; - hb_stereo_synth[1][i] = 0.5f * hb_synth[i] - 0.5f * hb_gain[1] * hb_synth[i]; + for ( i = 0; i < output_frame / 2; i++ ) + { + hb_stereo_synth[0][i] = 0.5f * hb_synth[i] + 0.5f * hb_gain[0] * hb_synth[i]; + hb_stereo_synth[1][i] = 0.5f * hb_synth[i] - 0.5f * hb_gain[0] * hb_synth[i]; + } + + for ( i = output_frame / 2; i < output_frame; i++ ) + { + hb_stereo_synth[0][i] = 0.5f * hb_synth[i] + 0.5f * hb_gain[1] * hb_synth[i]; + hb_stereo_synth[1][i] = 0.5f * hb_synth[i] - 0.5f * hb_gain[1] * hb_synth[i]; + } } + return; } @@ -451,9 +639,10 @@ static void ivas_sba_dirac_stereo_upmix_hb( *-------------------------------------------------------------------*/ static void ivas_sba_dirac_stereo_apply_td_stefi( - STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */ - float output[CPE_CHANNELS][L_FRAME48k], /* i/o: output synthesis signal */ - const int16_t output_frame /* i : output frame length per channel */ + STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */ + float output[CPE_CHANNELS][L_FRAME48k], /* i/o: output synthesis signal */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t spar_flag /* i : SPAR flag */ ) { int16_t i; @@ -462,7 +651,51 @@ static void ivas_sba_dirac_stereo_apply_td_stefi( float tmp; const float *win_dft; - if ( max( hStereoDft->td_gain[0], hStereoDft->td_gain[1] ) > 0 ) + if ( spar_flag ) + { + win_dft = hStereoDft->win32ms; + dftOvlLen = hStereoDft->dft32ms_ovl; + + float g_W_1, g_Y_1; + float g_W_2, g_Y_2; + float g_L, g_R; + float stefi_L, stefi_R; + + g_W_1 = ( hStereoDft->mixer_mat_smooth[0][1][8] + hStereoDft->mixer_mat_smooth[0][2][8] + hStereoDft->mixer_mat_smooth[0][3][8] ) + ( hStereoDft->mixer_mat_smooth[0][1][9] + hStereoDft->mixer_mat_smooth[0][2][9] + hStereoDft->mixer_mat_smooth[0][3][9] ) + ( hStereoDft->mixer_mat_smooth[0][1][10] + hStereoDft->mixer_mat_smooth[0][2][10] + hStereoDft->mixer_mat_smooth[0][3][10] ); + + g_Y_1 = ( hStereoDft->mixer_mat_smooth[1][1][8] + hStereoDft->mixer_mat_smooth[1][2][8] + hStereoDft->mixer_mat_smooth[1][3][8] ) + ( hStereoDft->mixer_mat_smooth[1][1][9] + hStereoDft->mixer_mat_smooth[1][2][9] + hStereoDft->mixer_mat_smooth[1][3][9] ) + ( hStereoDft->mixer_mat_smooth[1][1][10] + hStereoDft->mixer_mat_smooth[1][2][10] + hStereoDft->mixer_mat_smooth[1][3][10] ); + + g_W_2 = ( hStereoDft->mixer_mat_smooth[0][1][8 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][2][8 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][3][8 + IVAS_MAX_NUM_BANDS] ) + ( hStereoDft->mixer_mat_smooth[0][1][9 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][2][9 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][3][9 + IVAS_MAX_NUM_BANDS] ) + ( hStereoDft->mixer_mat_smooth[0][1][10 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][2][10 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][3][10 + IVAS_MAX_NUM_BANDS] ); + + g_Y_2 = ( hStereoDft->mixer_mat_smooth[1][1][8 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][2][8 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][3][8 + IVAS_MAX_NUM_BANDS] ) + ( hStereoDft->mixer_mat_smooth[1][1][9 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][2][9 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][3][9 + IVAS_MAX_NUM_BANDS] ) + ( hStereoDft->mixer_mat_smooth[1][1][10 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][2][10 + IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][3][10 + IVAS_MAX_NUM_BANDS] ); + + g_L = 0.16f * ( g_W_1 + g_W_2 - g_Y_1 - g_Y_2 ); + g_R = 0.16f * ( g_W_1 + g_W_2 + g_Y_1 + g_Y_2 ); + + for ( i = 0; i < dftOvlLen; i++ ) + { + win_in = win_dft[STEREO_DFT32MS_STEP * i] * win_dft[STEREO_DFT32MS_STEP * i]; + win_out = 1 - win_in; + + stefi_L = ( win_out * hStereoDft->g_L_prev + win_in * g_L ) * 0.5f * hStereoDft->hb_stefi_sig[i]; + stefi_R = ( win_out * hStereoDft->g_R_prev + win_in * g_R ) * 0.5f * hStereoDft->hb_stefi_sig[i]; + + output[0][i] += stefi_L; + output[1][i] += stefi_R; + } + for ( i = dftOvlLen; i < output_frame; i++ ) + { + + stefi_L = g_L * 0.5f * hStereoDft->hb_stefi_sig[i]; + stefi_R = g_R * 0.5f * hStereoDft->hb_stefi_sig[i]; + + output[0][i] += stefi_L; + output[1][i] += stefi_R; + } + hStereoDft->g_L_prev = g_L; + hStereoDft->g_R_prev = g_R; + } + else if ( max( hStereoDft->td_gain[0], hStereoDft->td_gain[1] ) > 0 ) { win_dft = hStereoDft->win32ms; dftOvlLen = hStereoDft->dft32ms_ovl; @@ -495,35 +728,111 @@ static void ivas_sba_dirac_stereo_apply_td_stefi( *-------------------------------------------------------------------*/ void ivas_sba_dirac_stereo_smooth_parameters( - STEREO_DFT_DEC_DATA_HANDLE hStereoDft /* i/o: decoder DFT stereo handle */ + STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */ + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD handle for upmixing */ + const int16_t cross_fade_start_offset, /* i : SPAR mixer delay compensation */ + const int32_t output_Fs /* i : Fs for delay calculation */ ) { - int16_t k_offset, b; + int16_t i, j, k, i_sf; + int16_t b; + int16_t k_offset; float *side_gain, *prev_side_gain; float *res_pred_gain, *prev_res_pred_gain; k_offset = STEREO_DFT_OFFSET; - prev_side_gain = hStereoDft->side_gain; side_gain = hStereoDft->side_gain + k_offset * STEREO_DFT_BAND_MAX; prev_res_pred_gain = hStereoDft->res_pred_gain; res_pred_gain = hStereoDft->res_pred_gain + k_offset * STEREO_DFT_BAND_MAX; - /* Smoothing of side and prediction gains between ftrames */ - for ( b = hStereoDft->res_pred_band_min; b < hStereoDft->nbands; b++ ) + if ( !hMdDec ) { - if ( hStereoDft->attackPresent ) + /* Smoothing of side and prediction gains between ftrames */ + for ( b = hStereoDft->res_pred_band_min; b < hStereoDft->nbands; b++ ) { - res_pred_gain[b] *= 0.8f; - res_pred_gain[b + STEREO_DFT_BAND_MAX] *= 0.8f; + if ( hStereoDft->attackPresent ) + { + res_pred_gain[b] *= 0.8f; + res_pred_gain[b + STEREO_DFT_BAND_MAX] *= 0.8f; + } + else + { + side_gain[b] = hStereoDft->smooth_fac[0][b] * prev_side_gain[b] + ( 1.f - hStereoDft->smooth_fac[0][b] ) * side_gain[b]; + side_gain[b + STEREO_DFT_BAND_MAX] = hStereoDft->smooth_fac[1][b] * side_gain[b] + ( 1.f - hStereoDft->smooth_fac[1][b] ) * side_gain[b + STEREO_DFT_BAND_MAX]; + res_pred_gain[b] = hStereoDft->smooth_fac[0][b] * prev_res_pred_gain[b] + ( 1.f - hStereoDft->smooth_fac[0][b] ) * res_pred_gain[b]; + res_pred_gain[b + STEREO_DFT_BAND_MAX] = hStereoDft->smooth_fac[1][b] * res_pred_gain[b] + ( 1.f - hStereoDft->smooth_fac[1][b] ) * res_pred_gain[b + STEREO_DFT_BAND_MAX]; + } } - else + } + + if ( hMdDec != 0 ) + { + float xfade_start_ns; + int16_t xfade_delay_subframes; + int16_t i_hist; + + xfade_start_ns = cross_fade_start_offset / (float) output_Fs * 1000000000.f - IVAS_FB_ENC_DELAY_NS; + xfade_delay_subframes = (int16_t) ( xfade_start_ns / ( FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ) ); + + i_hist = 4 - xfade_delay_subframes; + + for ( k = 0; k < 2; k++ ) { - side_gain[b] = hStereoDft->smooth_fac[0][b] * prev_side_gain[b] + ( 1.f - hStereoDft->smooth_fac[0][b] ) * side_gain[b]; - side_gain[b + STEREO_DFT_BAND_MAX] = hStereoDft->smooth_fac[1][b] * side_gain[b] + ( 1.f - hStereoDft->smooth_fac[1][b] ) * side_gain[b + STEREO_DFT_BAND_MAX]; - res_pred_gain[b] = hStereoDft->smooth_fac[0][b] * prev_res_pred_gain[b] + ( 1.f - hStereoDft->smooth_fac[0][b] ) * res_pred_gain[b]; - res_pred_gain[b + STEREO_DFT_BAND_MAX] = hStereoDft->smooth_fac[1][b] * res_pred_gain[b] + ( 1.f - hStereoDft->smooth_fac[1][b] ) * res_pred_gain[b + STEREO_DFT_BAND_MAX]; + for ( i_sf = k * 2; i_sf < ( k + 1 ) * 2; i_sf++ ) + { + if ( hStereoDft->first_frame ) + { + for ( i = 0; i < 2; i++ ) + { + for ( j = 0; j < 4; j++ ) + { + for ( b = 0; b < hStereoDft->nbands; b++ ) + { + hStereoDft->mixer_mat_smooth[i][j][b + k * IVAS_MAX_NUM_BANDS] = hMdDec->mixer_mat[i][j][b]; + } + for ( ; b < IVAS_MAX_NUM_BANDS; b++ ) + { + hStereoDft->mixer_mat_smooth[i][j][b + k * IVAS_MAX_NUM_BANDS] = 0.f; + } + } + } + } + else + { + for ( i = 0; i < 2; i++ ) + { + for ( j = 0; j < 4; j++ ) + { + for ( b = 0; b < hStereoDft->nbands; b++ ) + { + float beta = hStereoDft->smooth_fac[k][b]; + hStereoDft->mixer_mat_smooth[i][j][b + k * IVAS_MAX_NUM_BANDS] = + beta * hStereoDft->mixer_mat_smooth[i][j][b + k * IVAS_MAX_NUM_BANDS] + ( 1 - beta ) * hMdDec->mixer_mat_prev[i_hist][i][j][b]; + } + } + } + } + + mvr2r( hMdDec->mixer_mat_prev[1][0][0], hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hMdDec->mixer_mat_prev[2][0][0], hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hMdDec->mixer_mat_prev[3][0][0], hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hMdDec->mixer_mat_prev[4][0][0], hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + + for ( i = 0; i < 2; i++ ) + { + for ( j = 0; j < 4; j++ ) + { + for ( b = 0; b < hStereoDft->nbands; b++ ) + { + hMdDec->mixer_mat_prev[4][i][j][b] = hMdDec->mixer_mat[i][j][b + i_sf * IVAS_MAX_NUM_BANDS]; + } + } + } + } } + + hStereoDft->first_frame = 0; } return; @@ -539,10 +848,14 @@ void ivas_sba_dirac_stereo_smooth_parameters( void ivas_sba_dirac_stereo_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ float output[CPE_CHANNELS][L_FRAME48k], /* i/o: output synthesis signal */ - const int16_t output_frame /* i : output frame length per channel */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t mcmasa /* i : McMASA flag */ ) { int16_t dtx_flag, fd_cng_flag; +#ifdef SBA2MONO + int16_t sba_mono_flag; +#endif int16_t memOffset; float tmp_buf[NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )]; float tmp_synth[L_FRAME16k]; @@ -556,59 +869,127 @@ void ivas_sba_dirac_stereo_dec( hSCE = st_ivas->hSCE[0]; hCPE = st_ivas->hCPE[0]; hStereoDft = hCPE->hStereoDft; - dtx_flag = ( hSCE->hCoreCoder[0]->core_brate <= SID_2k40 ); - fd_cng_flag = ( dtx_flag && hSCE->hCoreCoder[0]->cng_type == FD_CNG ); + + if ( st_ivas->nchan_transport > 1 && !mcmasa ) + { + dtx_flag = 0; + fd_cng_flag = 0; + } + else + { + dtx_flag = ( hSCE->hCoreCoder[0]->core_brate <= SID_2k40 ); + fd_cng_flag = ( dtx_flag && hSCE->hCoreCoder[0]->cng_type == FD_CNG ); + } +#ifdef SBA2MONO + sba_mono_flag = ( st_ivas->hDecoderConfig->nchan_out == 1 ) ? 1 : 0; +#endif + memOffset = NS2SA( output_frame * FRAMES_PER_SEC, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ); ivas_sba_dirac_stereo_config( hStereoDft->hConfig ); - hStereoDft->nbands = ivas_sba_dirac_stereo_band_config( hStereoDft->band_limits, st_ivas->hDecoderConfig->output_Fs, hStereoDft->NFFT ); + hStereoDft->nbands = ivas_sba_dirac_stereo_band_config( hStereoDft->band_limits, st_ivas->hDecoderConfig->output_Fs, hStereoDft->NFFT, ( st_ivas->sba_mode == SBA_MODE_SPAR && !mcmasa ) ); stereo_dft_dec_update( hStereoDft, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ ); + if ( st_ivas->nchan_transport > 1 ) + { + stereo_dft_dec_analyze( hCPE, output[0], DFT, 0, output_frame, output_frame, DFT_STEREO_DEC_ANA_FB, 0, 0 ); + stereo_dft_dec_analyze( hCPE, output[1], DFT, 1, output_frame, output_frame, DFT_STEREO_DEC_ANA_FB, 0, 0 ); + hStereoDft->core_hist[0] = hCPE->hCoreCoder[0]->core; + } + else + { + /* nrg calculation for TD Stereo Filling, as done in ICBWE which is not used in this case */ + ivas_sba_dirac_stereo_compute_td_stefi_nrgs( hStereoDft, hSCE->save_hb_synth, hSCE->hCoreCoder[0]->core, output_frame, fd_cng_flag ); - /* nrg calculation for TD Stereo Filling, as done in ICBWE which is not used in this case */ - ivas_sba_dirac_stereo_compute_td_stefi_nrgs( hStereoDft, hSCE->save_hb_synth, hSCE->hCoreCoder[0]->core, output_frame, fd_cng_flag ); - - /* do DFT Stereo core switching (including DFT analysis) here as CPE element was not available in SCE decoder */ - mvr2r( hSCE->save_synth, tmp_synth, hSCE->hCoreCoder[0]->L_frame ); - stereo_dft_dec_core_switching( hCPE, output[0] /*hSCE->save_output*/, hSCE->save_synth, hSCE->save_hb_synth, DFT, output_frame, 0, dtx_flag ); + /* do DFT Stereo core switching (including DFT analysis) here as CPE element was not available in SCE decoder */ + mvr2r( hSCE->save_synth, tmp_synth, hSCE->hCoreCoder[0]->L_frame ); + stereo_dft_dec_core_switching( hCPE, output[0] /*hSCE->save_output*/, hSCE->save_synth, hSCE->save_hb_synth, DFT, output_frame, 0, dtx_flag ); - /* do updates here after skipping this in SCE decoder (needs to be done after core switching) */ - updt_dec_common( hSCE->hCoreCoder[0], NORMAL_HQ_CORE, -1, hSCE->save_synth ); + /* do updates here after skipping this in SCE decoder (needs to be done after core switching) */ + updt_dec_common( hSCE->hCoreCoder[0], NORMAL_HQ_CORE, -1, hSCE->save_synth ); + } /* mapping of DirAC parameters (azimuth, elevation, diffuseness) to DFT Stereo parameters (side gain, prediction gain) */ - map_params_dirac_to_stereo( hStereoDft, st_ivas->hQMetaData, tmp_synth, DFT[0], st_ivas->ivas_format == MC_FORMAT, hSCE->hCoreCoder[0]->L_frame ); + map_params_dirac_to_stereo( hStereoDft, st_ivas->hQMetaData, tmp_synth, DFT[0], + st_ivas->ivas_format == MC_FORMAT, + ( st_ivas->sba_mode != SBA_MODE_SPAR || mcmasa ) ? hSCE->hCoreCoder[0]->L_frame : output_frame, + ( st_ivas->sba_mode != SBA_MODE_SPAR || mcmasa ) ); + + if ( st_ivas->sba_mode == SBA_MODE_SPAR && !mcmasa ) + { + set_f( hStereoDft->res_pred_gain, 1.f, 3 * STEREO_DFT_BAND_MAX ); + } /* DFT Stereo upmix */ - stereo_dft_dec( hStereoDft, hCPE->hCoreCoder[0], DFT, NULL, NULL, 1 /*st_ivas->sba_dirac_stereo_flag*/ ); +#ifdef SBA2MONO + stereo_dft_dec( hStereoDft, hCPE->hCoreCoder[0], DFT, NULL, NULL, 1 /*st_ivas->sba_dirac_stereo_flag*/, sba_mono_flag, +#else + stereo_dft_dec( hStereoDft, hCPE->hCoreCoder[0], DFT, NULL, NULL, 1, /*st_ivas->sba_dirac_stereo_flag*/ +#endif + ( st_ivas->hSpar != NULL && !mcmasa ) ? st_ivas->hSpar->hMdDec : 0, + ( st_ivas->hSpar != NULL && !mcmasa ) ? st_ivas->hSpar->hFbMixer->cross_fade_start_offset : 0, + st_ivas->hDecoderConfig->output_Fs, st_ivas->nchan_transport ); /* DFT synthesis */ stereo_dft_dec_synthesize( hCPE, DFT, 0, output[0], output_frame ); +#ifdef SBA2MONO + if ( !sba_mono_flag ) + { + stereo_dft_dec_synthesize( hCPE, DFT, 1, output[1], output_frame ); + } +#else stereo_dft_dec_synthesize( hCPE, DFT, 1, output[1], output_frame ); +#endif synchro_synthesis( st_ivas->hDecoderConfig->ivas_total_brate, hCPE, output, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ ); /* output scaling */ +#ifdef SBA2MONO + if ( !sba_mono_flag ) + { + v_multc( output[0], 0.5f, output[0], output_frame ); + v_multc( output[1], 0.5f, output[1], output_frame ); + } +#else v_multc( output[0], 0.5f, output[0], output_frame ); v_multc( output[1], 0.5f, output[1], output_frame ); +#endif /* delay HB synth */ - mvr2r( hSCE->save_hb_synth + output_frame - memOffset, tmp_buf, memOffset ); - mvr2r( hSCE->save_hb_synth, hSCE->save_hb_synth + memOffset, output_frame - memOffset ); - mvr2r( hSCE->prev_hb_synth, hSCE->save_hb_synth, memOffset ); - mvr2r( tmp_buf, hSCE->prev_hb_synth, memOffset ); + if ( st_ivas->nchan_transport == 1 ) + { + mvr2r( hSCE->save_hb_synth + output_frame - memOffset, tmp_buf, memOffset ); + mvr2r( hSCE->save_hb_synth, hSCE->save_hb_synth + memOffset, output_frame - memOffset ); + mvr2r( hSCE->prev_hb_synth, hSCE->save_hb_synth, memOffset ); + mvr2r( tmp_buf, hSCE->prev_hb_synth, memOffset ); + } - if ( ( hCPE->hCoreCoder[0]->core == ACELP_CORE || hCPE->hCoreCoder[0]->last_core == ACELP_CORE ) && !fd_cng_flag ) + if ( ( hCPE->hCoreCoder[0]->core == ACELP_CORE || hCPE->hCoreCoder[0]->last_core == ACELP_CORE ) && !fd_cng_flag && st_ivas->nchan_transport == 1 ) { /* upmix ACELP BWE */ ivas_sba_dirac_stereo_compute_hb_gain( hStereoDft, hb_gain ); - ivas_sba_dirac_stereo_upmix_hb( hb_synth_stereo, hSCE->save_hb_synth, hb_gain, output_frame ); + + ivas_sba_dirac_stereo_upmix_hb( hb_synth_stereo, hSCE->save_hb_synth, hb_gain, output_frame, +#ifdef SBA2MONO + ( st_ivas->sba_mode != SBA_MODE_SPAR || mcmasa ), sba_mono_flag, hSCE->hCoreCoder[0]->bwidth, hStereoDft ); +#else + ( st_ivas->sba_mode != SBA_MODE_SPAR || mcmasa ), hStereoDft ); +#endif + /* add HB to ACELP core */ v_add( output[0], hb_synth_stereo[0], output[0], output_frame ); - v_add( output[1], hb_synth_stereo[1], output[1], output_frame ); +#ifdef SBA2MONO + if ( !sba_mono_flag ) + { +#endif + v_add( output[1], hb_synth_stereo[1], output[1], output_frame ); - /* apply TD Stereo Filling as is done in ICBWE */ - ivas_sba_dirac_stereo_apply_td_stefi( hStereoDft, output, output_frame ); + /* apply TD Stereo Filling as is done in ICBWE */ + ivas_sba_dirac_stereo_apply_td_stefi( hStereoDft, output, output_frame, ( st_ivas->sba_mode == SBA_MODE_SPAR && !mcmasa ) ); +#ifdef SBA2MONO + } +#endif } return; diff --git a/lib_dec/ivas_sba_rendering.c b/lib_dec/ivas_sba_rendering.c deleted file mode 100644 index 3d7b0a84fed04e421eea4377f86f590204d43b61..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_sba_rendering.c +++ /dev/null @@ -1,514 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#include "prot.h" -#include "ivas_prot.h" -#include "ivas_stat_dec.h" -#include "ivas_cnst.h" -#include -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "wmops.h" - - -/*-----------------------------------------------------------------------* - * Local function prototypes - *-----------------------------------------------------------------------*/ - -static void ivas_sba_mtx_mult( float output_f[][L_FRAME48k], const int16_t output_frame, const int16_t nchan_in, IVAS_OUTPUT_SETUP output_setup, const float *mtx_hoa_decoder ); - - -/*-------------------------------------------------------------------* - * ivas_sba_linear_renderer() - * - * Linear rendering for SBA format - *-------------------------------------------------------------------*/ - -ivas_error ivas_sba_linear_renderer( - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ - const int16_t output_frame, /* i : output frame length per channel */ - const int16_t nchan_in, /* i : number of input ambisonics channels */ - const AUDIO_CONFIG output_config, /* i : output audio configuration */ - const IVAS_OUTPUT_SETUP output_setup, /* i : output format setup */ - const float hoa_dec_mtx[] /* i : hoa decoding mtx */ -) -{ - int16_t i; - float dmx_l; - int16_t nchan_hoa; - ivas_error error; - - error = IVAS_ERR_OK; - - /* Number of channels of HOA depends of transport format which is mixed order xH1V*/ - nchan_hoa = nchan_in; - - if ( nchan_in == 6 ) /*2H1V*/ - { - nchan_hoa = 9; - } - else if ( nchan_in == 8 ) /*3H1V*/ - { - nchan_hoa = 16; - } - - switch ( output_config ) - { - case AUDIO_CONFIG_MONO: - /* If stereo DMX, MONO = W = Cardioids L + R*/ - if ( nchan_in == 2 ) - { - for ( i = 0; i < output_frame; i++ ) - { - output_f[0][i] += output_f[1][i]; - } - } - /* else: do nothing, MONO = W*/ - break; - case AUDIO_CONFIG_STEREO: - assert( ( nchan_in >= 2 ) && "Number of input channels must be at least 2 (for W and Y)!\n" ); - - /* Compute L and R cardioids from SB format except if stereo DMX is transmitted already in this format*/ - if ( nchan_in > 2 ) - { - /*Build L/R cardioids*/ - for ( i = 0; i < output_frame; i++ ) - { - dmx_l = 0.5f * ( output_f[0][i] + output_f[1][i] ); /* cardioid_left = 0.5(W + Y) */ - output_f[1][i] = 0.5f * ( output_f[0][i] - output_f[1][i] ); /* cardioid_right = 0.5(W - Y) */ - output_f[0][i] = dmx_l; - } - } - break; - case AUDIO_CONFIG_5_1: - case AUDIO_CONFIG_7_1: - case AUDIO_CONFIG_5_1_2: - case AUDIO_CONFIG_5_1_4: - case AUDIO_CONFIG_7_1_4: - case AUDIO_CONFIG_LS_CUSTOM: - ivas_sba_mtx_mult( output_f, output_frame, nchan_hoa, output_setup, hoa_dec_mtx ); - break; - case AUDIO_CONFIG_FOA: /* Ambisonics output, order: 1 */ - case AUDIO_CONFIG_HOA2: /* Ambisonics output, order: 2 */ - case AUDIO_CONFIG_HOA3: /* Ambisonics output, order: 3 */ - for ( i = nchan_hoa; i < output_setup.nchan_out_woLFE; i++ ) - { - set_zero( output_f[i], output_frame ); - } - break; - default: - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: illegal output configuration, Exiting.\n" ); - } - - return error; -} - - -/*-------------------------------------------------------------------* - * ivas_sba_mtx_mult() - * - * HOA decoding with LFE insertion - *-------------------------------------------------------------------*/ - -static void ivas_sba_mtx_mult( - float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ - const int16_t output_frame, /* i : output frame length per channel */ - const int16_t nchan_in, /* i : Number of ambisonic channels */ - IVAS_OUTPUT_SETUP output_setup, /* i : Output configuration */ - const float *mtx_hoa_decoder /* i : Hoa decoding mtx */ -) -{ - int16_t i, k, ch_idx; - int16_t idx_lfe; - float input_f[16]; - const float *hoa_decoder; - - assert( ( nchan_in >= FOA_CHANNELS ) && "Number of input channels must be at least 4 (FOA)!\n" ); - - for ( i = 0; i < output_frame; i++ ) - { - /* init*/ - idx_lfe = 0; - hoa_decoder = &mtx_hoa_decoder[0]; - for ( k = 0; k < nchan_in; k++ ) - { - input_f[k] = output_f[k][i]; - } - - /* mtx mult with LFE insertion*/ - for ( ch_idx = 0; ch_idx < ( output_setup.nchan_out_woLFE + output_setup.num_lfe ); ch_idx++ ) - { - if ( ( output_setup.num_lfe > 0 ) && ( output_setup.index_lfe[idx_lfe] == ch_idx ) ) - { - /*LFE insertion*/ - output_f[ch_idx][i] = 0.f; - if ( idx_lfe < ( output_setup.num_lfe - 1 ) ) - { - idx_lfe++; - } - } - else - { - /*HOA decoding*/ - output_f[ch_idx][i] = input_f[0] * hoa_decoder[0]; - for ( k = 1; k < nchan_in; k++ ) - { - output_f[ch_idx][i] += input_f[k] * hoa_decoder[k]; - } - hoa_decoder += 16; - } - } - } - - return; -} - - -/*-------------------------------------------------------------------* - * ivas_sba_upmixer_renderer() - * - * SBA upmix rendering - *-------------------------------------------------------------------*/ - -void ivas_sba_upmixer_renderer( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ - float output[][L_FRAME48k], /* i/o: transport/output audio channels */ - const int16_t nchan_remapped, /* i : num channels after remapping of TCs */ - const int16_t output_frame /* i : output frame length */ -) -{ - int16_t i, ch, nchan_out; - float clip, temp; - int16_t nchan_internal; - - wmops_sub_start( "ivas_sba_upmixer_renderer" ); - - nchan_internal = ivas_sba_get_nchan_metadata( st_ivas->sba_order ); - nchan_out = st_ivas->hDecoderConfig->nchan_out; - - for ( ch = 0; ch < nchan_remapped; ch++ ) - { - for ( i = 0; i < output_frame; i++ ) - { - temp = output[ch][i]; - temp = floorf( temp + 0.5f ); - - if ( temp > MAX16B_FLT ) - { - temp = MAX16B_FLT; - } - else if ( temp < ( -1.0f * PCM16_TO_FLT_FAC ) ) - { - temp = ( -1.0f * PCM16_TO_FLT_FAC ); - } - temp *= ( 1.0f / PCM16_TO_FLT_FAC ); - output[ch][i] = temp; - } - } - - if ( st_ivas->nchan_transport >= 3 ) - { - /*convert WYZX downmix to WYXZ*/ - for ( i = 0; i < output_frame; i++ ) - { - temp = output[2][i]; - output[2][i] = output[3][i]; - output[3][i] = temp; - } - } - - /* Upmixer */ - ivas_spar_foa_dec_upmixer( st_ivas, output, nchan_internal, output_frame ); - - /* Renderer */ - if ( st_ivas->hDirAC != NULL && st_ivas->renderer_type == RENDERER_DIRAC ) - { - nchan_out = st_ivas->hDirAC->hOutSetup.nchan_out_woLFE + st_ivas->hDirAC->hOutSetup.num_lfe; - } - - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) - { - ivas_sba_linear_renderer( output, output_frame, st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hDecoderConfig->output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ); - } - - clip = 1.0f; - for ( ch = 0; ch < nchan_out; ch++ ) - { - for ( i = 0; i < output_frame; i++ ) - { - clip = max( clip, fabsf( output[ch][i] ) ); - output[ch][i] = output[ch][i] * PCM16_TO_FLT_FAC; - } - } - -#ifdef DEBUGGING - if ( clip > 1.0f ) - { -#ifdef DEBUG_LBR_SBA - fprintf( stdout, "IVAS Crend Clipped: max gain = %f\n", clip ); -#else - fprintf( stderr, "IVAS Crend Clipped: max gain = %f\n", clip ); -#endif - } -#endif - - wmops_sub_end(); - - return; -} - - -/*-------------------------------------------------------------------* - * ivas_sba_mix_matrix_determiner() - * - * Determine SBA mixing matrices - *-------------------------------------------------------------------*/ - -void ivas_sba_mix_matrix_determiner( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ - float output[][L_FRAME48k], /* i/o: transport/output audio channels */ - const int16_t nchan_remapped, /* i : num channels after remapping of TCs */ - const int16_t output_frame /* i : output frame length */ -) -{ - int16_t i, ch; - float temp; - ivas_spar_foa_dec_state_t *pState; - int16_t num_bands_out, nchan_transport, nchan_out; - - /* Convert numeric range */ - for ( ch = 0; ch < nchan_remapped; ch++ ) - { - for ( i = 0; i < output_frame; i++ ) - { - temp = output[ch][i]; - temp = floorf( temp + 0.5f ); - - if ( temp > MAX16B_FLT ) - { - temp = MAX16B_FLT; - } - else if ( temp < ( -1.0f * PCM16_TO_FLT_FAC ) ) - { - temp = ( -1.0f * PCM16_TO_FLT_FAC ); - } - temp *= ( 1.0f / PCM16_TO_FLT_FAC ); - output[ch][i] = temp; - } - } - - /* AGC */ - pState = st_ivas->hSpar->hSparFoa; - nchan_transport = pState->hMdDec->spar_md_cfg.nchan_transport; - nchan_out = nchan_transport; - ivas_agc_dec_process( pState->hAgcDec, output, output, nchan_transport, output_frame ); - - /* Convert numeric range back */ - for ( ch = 0; ch < nchan_out; ch++ ) - { - for ( i = 0; i < output_frame; i++ ) - { - output[ch][i] = output[ch][i] * PCM16_TO_FLT_FAC; - } - } - - /* Mixing matrix determiner */ - num_bands_out = pState->hFbMixer->pFb->filterbank_num_bands; - ivas_spar_foa_dec_gen_umx_mat( pState->hMdDec, nchan_transport, num_bands_out, st_ivas->bfi ); - - wmops_sub_end(); - - return; -} - - -/*-------------------------------------------------------------------* - * ivas_sba_prototype_renderer() - * - * Render prototype audio signals using SBA mixing matrices - *-------------------------------------------------------------------*/ - -void ivas_sba_prototype_renderer( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ - float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ - float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, imag */ - const int16_t firstSubframe, /* i : First subframe to map */ - const int16_t nSubframes /* i : Number of subframes to map */ -) -{ - float mixer_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; - ivas_spar_foa_dec_state_t *hSparFoa; - DECODER_CONFIG_HANDLE hDecoderConfig; - int16_t num_spar_bands, spar_band; - int16_t b, ts; - int16_t num_cldfb_bands, numch_in, numch_out; - int16_t cldfb_band; - int16_t out_ch, in_ch; - int16_t firstSlot, slotEnd, firstInCh, inChEnd, firstOutCh, outChEnd; - int16_t sf_idx; - - wmops_sub_start( "ivas_sba_prototype_renderer" ); - - hSparFoa = st_ivas->hSpar->hSparFoa; - hDecoderConfig = st_ivas->hDecoderConfig; - num_spar_bands = hSparFoa->hFbMixer->pFb->filterbank_num_bands; - - firstSlot = firstSubframe * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); - slotEnd = ( firstSubframe + nSubframes ) * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); - - num_cldfb_bands = hSparFoa->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands; - numch_in = hSparFoa->hFbMixer->fb_cfg->num_in_chans; - numch_out = hSparFoa->hFbMixer->fb_cfg->num_out_chans; - - if ( st_ivas->nchan_transport == 1 ) - { - firstInCh = 0; - inChEnd = 1; - firstOutCh = 0; - outChEnd = 1; - } - else /* 2 TC */ - { - firstInCh = 0; - inChEnd = 2; - firstOutCh = 1; - outChEnd = 2; - } - - /* Apply mixing matrix */ - for ( ts = firstSlot; ts < slotEnd; ts++ ) - { - /* determine SPAR parameters for this time slot */ - ivas_spar_get_parameters( hSparFoa, hDecoderConfig, ts, numch_out, numch_in, num_spar_bands, mixer_mat ); - - for ( cldfb_band = 0; cldfb_band < num_cldfb_bands; cldfb_band++ ) - { - float out_re[IVAS_SPAR_MAX_CH]; - float out_im[IVAS_SPAR_MAX_CH]; - float cldfb_par; - ivas_fb_bin_to_band_data_t *bin2band = &hSparFoa->hFbMixer->pFb->fb_bin_to_band; - - for ( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ ) - { - out_re[out_ch] = 0.0f; - out_im[out_ch] = 0.0f; - - for ( in_ch = firstInCh; in_ch < inChEnd; in_ch++ ) - { - if ( cldfb_band < CLDFB_PAR_WEIGHT_START_BAND ) /* tuning parameter, depends on how much SPAR Filters overlap for the CLDFB bands */ - { - spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band]; - cldfb_par = mixer_mat[out_ch][in_ch][spar_band]; - } - else - { - cldfb_par = 0.0f; - for ( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ ) - { - /* accumulate contributions from all SPAR bands */ - cldfb_par += mixer_mat[out_ch][in_ch][spar_band] * bin2band->pp_cldfb_weights_per_spar_band[cldfb_band][spar_band]; - } - } - - out_re[out_ch] += inRe[in_ch][ts][cldfb_band] * cldfb_par; - out_im[out_ch] += inIm[in_ch][ts][cldfb_band] * cldfb_par; - } - } - - /*update CLDFB data with the parameter-modified data*/ - for ( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ ) - { - inRe[out_ch][ts][cldfb_band] = out_re[out_ch]; - inIm[out_ch][ts][cldfb_band] = out_im[out_ch]; - } - } - - /* Update mixing matrices */ - if ( ( ( ts + 1 ) % MAX_PARAM_SPATIAL_SUBFRAMES ) == 0 ) - { - sf_idx = ts / MAX_PARAM_SPATIAL_SUBFRAMES; - hSparFoa->i_subframe++; - hSparFoa->i_subframe = min( hSparFoa->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); - mvr2r( hSparFoa->hMdDec->mixer_mat_prev[1][0][0], hSparFoa->hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - mvr2r( hSparFoa->hMdDec->mixer_mat_prev[2][0][0], hSparFoa->hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - mvr2r( hSparFoa->hMdDec->mixer_mat_prev[3][0][0], hSparFoa->hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - mvr2r( hSparFoa->hMdDec->mixer_mat_prev[4][0][0], hSparFoa->hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - - for ( out_ch = 0; out_ch < numch_out; out_ch++ ) - { - for ( in_ch = 0; in_ch < numch_in; in_ch++ ) - { - for ( b = 0; b < num_spar_bands; b++ ) - { - hSparFoa->hMdDec->mixer_mat_prev[4][out_ch][in_ch][b] = hSparFoa->hMdDec->mixer_mat[out_ch][in_ch][b + sf_idx * IVAS_MAX_NUM_BANDS]; - } - } - } - } - } - - /* Create prototypes */ - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) - { - for ( ts = firstSlot; ts < slotEnd; ts++ ) - { - if ( st_ivas->nchan_transport == 1 ) /* Dual mono */ - { - mvr2r( inRe[0][ts], inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); - mvr2r( inIm[0][ts], inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); - } - else if ( st_ivas->nchan_transport == 2 ) /* Opposing cardioids */ - { - float temp_signal[CLDFB_NO_CHANNELS_MAX]; - - v_add( inRe[0][ts], inRe[1][ts], temp_signal, CLDFB_NO_CHANNELS_MAX ); - v_sub( inRe[0][ts], inRe[1][ts], inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); - mvr2r( temp_signal, inRe[0][ts], CLDFB_NO_CHANNELS_MAX ); - v_multc( inRe[0][ts], 0.5f, inRe[0][ts], CLDFB_NO_CHANNELS_MAX ); - v_multc( inRe[1][ts], 0.5f, inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); - - v_add( inIm[0][ts], inIm[1][ts], temp_signal, CLDFB_NO_CHANNELS_MAX ); - v_sub( inIm[0][ts], inIm[1][ts], inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); - mvr2r( temp_signal, inIm[0][ts], CLDFB_NO_CHANNELS_MAX ); - v_multc( inIm[0][ts], 0.5f, inIm[0][ts], CLDFB_NO_CHANNELS_MAX ); - v_multc( inIm[1][ts], 0.5f, inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); - } - } - } - - wmops_sub_end(); - - return; -} diff --git a/lib_dec/ivas_sba_rendering_internal.c b/lib_dec/ivas_sba_rendering_internal.c new file mode 100644 index 0000000000000000000000000000000000000000..a80986b39e7a41caf4b8a0844ac63951e90517a0 --- /dev/null +++ b/lib_dec/ivas_sba_rendering_internal.c @@ -0,0 +1,629 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_stat_dec.h" +#include "ivas_cnst.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +#ifdef DEBUG_MODE_DIRAC +/*-----------------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------------*/ + +static void debug_mode_dirac( float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], const int16_t nchan_transport, const int16_t output_frame ); +#endif + + +/*-------------------------------------------------------------------------* + * ivas_sba2MC_cldfb() + * + * SBA signals transformed into MC in CLDFB domain + *-------------------------------------------------------------------------*/ + +void ivas_sba2mc_cldfb( + IVAS_OUTPUT_SETUP hInSetup, /* i : Format of input layout */ + float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb real part */ + float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: cldfb imag part */ + const int16_t nb_channels_out, /* i : nb of output channels */ + const int16_t nb_bands, /* i : nb of CLDFB bands to process */ + const float *hoa_dec_mtx /* i : HOA decoding mtx */ +) +{ + int16_t iBlock, iBand, n, m; + float realOut[16][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX], imagOut[16][MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX]; + float g; + float *p_real, *p_imag, *p_realOut, *p_imagOut; + int16_t nb_channels_in; + + push_wmops( "ivas_sba2mc_cldfb" ); + + nb_channels_in = hInSetup.nchan_out_woLFE; + assert( ( nb_channels_in == 16 ) && ( nb_channels_out == 11 ) && "ivas_sba2mc_cldfb; only HOA3 to CICP19 is for now supported!" ); + + for ( n = 0; n < nb_channels_out; n++ ) + { + set_zero( realOut[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_bands ); + set_zero( imagOut[n], MAX_PARAM_SPATIAL_SUBFRAMES * nb_bands ); + + for ( m = 0; m < nb_channels_in; m++ ) + { + g = hoa_dec_mtx[SBA_NHARM_HOA3 * n + m]; + p_realOut = realOut[n]; + p_imagOut = imagOut[n]; + for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) + { + p_real = RealBuffer[m][iBlock]; + p_imag = ImagBuffer[m][iBlock]; + for ( iBand = 0; iBand < nb_bands; iBand++ ) + { + *p_realOut = *p_realOut + g * *( p_real++ ); + *p_imagOut = *p_imagOut + g * *( p_imag++ ); + p_realOut++; + p_imagOut++; + } + } + } + } + + for ( n = 0; n < nb_channels_out; n++ ) + { + p_realOut = realOut[n]; + p_imagOut = imagOut[n]; + for ( iBlock = 0; iBlock < MAX_PARAM_SPATIAL_SUBFRAMES; iBlock++ ) + { + p_real = RealBuffer[n][iBlock]; + p_imag = ImagBuffer[n][iBlock]; + for ( iBand = 0; iBand < nb_bands; iBand++ ) + { + *( p_real++ ) = *p_realOut++; + *( p_imag++ ) = *p_imagOut++; + } + } + } + + pop_wmops(); + + return; +} + + +/*-------------------------------------------------------------------------* + * ivas_mc2sba() + * + * MC signals transformed into SBA in TD domain + *-------------------------------------------------------------------------*/ + +void ivas_mc2sba( + IVAS_OUTPUT_SETUP hIntSetup, /* i : Format of decoder output */ + float buffer_td[][L_FRAME48k], /* i/o: MC signals (on input) and the HOA3 (on output) */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t sba_order, /* i : Ambisonic (SBA) order */ + const float gain_lfe /* i : gain for LFE, 0 = ignore LFE */ +) +{ + int16_t i, j, k; + int16_t idx_lfe, idx_in; + float buffer_tmp[16][L_FRAME48k]; + float gains[16]; + int16_t azimuth, elevation; + int16_t sba_num_chans; + + assert( ( sba_order <= 3 ) && "Only order up to 3 is supported!" ); + + /* Init*/ + sba_num_chans = ( sba_order + 1 ) * ( sba_order + 1 ); + for ( j = 0; j < sba_num_chans; j++ ) + { + set_zero( buffer_tmp[j], output_frame ); + } + + /* HOA encoding*/ + idx_lfe = 0; + idx_in = 0; + for ( i = 0; i < hIntSetup.nchan_out_woLFE + hIntSetup.num_lfe; i++ ) + { + if ( ( hIntSetup.num_lfe > 0 ) && ( i == hIntSetup.index_lfe[idx_lfe] ) ) + { + if ( gain_lfe > 0.f ) + { + /* Add LFE to omni W with gain*/ + for ( k = 0; k < output_frame; k++ ) + { + buffer_tmp[0][k] += gain_lfe * buffer_td[i][k]; + } + } + + if ( idx_lfe < ( hIntSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else + { + azimuth = (int16_t) ( hIntSetup.ls_azimuth[idx_in] ); + elevation = (int16_t) ( hIntSetup.ls_elevation[idx_in] ); + idx_in++; + + /* get HOA response for direction (ACN/SN3D)*/ + ivas_dirac_dec_get_response( + azimuth, + elevation, + gains, + sba_order ); + + for ( j = 0; j < sba_num_chans; j++ ) + { + for ( k = 0; k < output_frame; k++ ) + { + buffer_tmp[j][k] += gains[j] * buffer_td[i][k]; + } + } + } + } + + for ( j = 0; j < sba_num_chans; j++ ) + { + mvr2r( buffer_tmp[j], buffer_td[j], output_frame ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_sba_remapTCs() + * + * Get TCs from Ambisonics signal in ACN + *-------------------------------------------------------------------*/ + +int16_t ivas_sba_remapTCs( + float sba_data[][L_FRAME48k], /* i/o: SBA signals */ + Decoder_Struct *st_ivas, /* i/o: decoder struct */ + const int16_t output_frame /* i : frame length */ +) +{ + int16_t nchan_remapped; + +#ifdef DEBUG_MODE_DIRAC + debug_mode_dirac( sba_data, st_ivas->nchan_transport, output_frame ); +#endif + + nchan_remapped = st_ivas->nchan_transport; + if ( ( st_ivas->sba_mode != SBA_MODE_SPAR && st_ivas->sba_planar && nchan_remapped >= 3 ) || + ( ( st_ivas->sba_mode == SBA_MODE_SPAR ) && nchan_remapped == 3 ) ) + { + + nchan_remapped++; + if ( st_ivas->sba_mode != SBA_MODE_SPAR ) + { + assert( ( ( st_ivas->nchan_transport == 3 ) || ( st_ivas->nchan_transport == 5 ) || ( st_ivas->nchan_transport == 7 ) ) && "Number of channels must be odd for SBA planar!" ); + } + + if ( nchan_remapped == 4 ) + { + /*For planar A-format channel 2 and 3 are identical -> Z=0*/ + mvr2r( sba_data[2], sba_data[3], output_frame ); + } + } + + if ( st_ivas->nchan_transport >= 3 ) + { + int16_t i = 0; + float temp; + + /*convert WYXZ downmix to WYZX*/ + for ( i = 0; i < output_frame; i++ ) + { + temp = sba_data[2][i]; + sba_data[2][i] = sba_data[3][i]; + sba_data[3][i] = temp; + if ( st_ivas->nchan_transport == 3 ) + { + sba_data[2][i] = 0; + } + } + } + + if ( st_ivas->sba_mode != SBA_MODE_SPAR ) + { + ivas_sba_zero_vert_comp( sba_data, st_ivas->sba_analysis_order, st_ivas->sba_planar, output_frame ); + } + + return ( nchan_remapped ); +} + + +/*-------------------------------------------------------------------------* + * ivas_ism2sba() + * + * ISM transformed into SBA in TD domain. + *-------------------------------------------------------------------------*/ + +void ivas_ism2sba( + float buffer_td[][L_FRAME48k], /* i/o: TD signal buffers */ + ISM_RENDERER_HANDLE hIsmRendererData, /* i/o: renderer data */ + const ISM_METADATA_HANDLE hIsmMetaData[], /* i : object metadata */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ +) +{ + int16_t i, j, k; + float buffer_tmp[16][L_FRAME48k]; + float gains[16]; + float g1, g2; + int16_t azimuth, elevation; + int16_t sba_num_chans; + + assert( ( sba_order <= 3 ) && "Only order up to 3 is supported!" ); + assert( hIsmRendererData != NULL && "hIsmRendererData not allocated!" ); + + /* Init*/ + sba_num_chans = ( sba_order + 1 ) * ( sba_order + 1 ); + for ( j = 0; j < sba_num_chans; j++ ) + { + set_zero( buffer_tmp[j], output_frame ); + } + + for ( i = 0; i < nchan_ism; i++ ) + { + // TODO tmu review when #215 is resolved + azimuth = (int16_t) floorf( hIsmMetaData[i]->azimuth + 0.5f ); + elevation = (int16_t) floorf( hIsmMetaData[i]->elevation + 0.5f ); + + /*get HOA gets for direction (ACN/SN3D)*/ + ivas_dirac_dec_get_response( azimuth, elevation, gains, sba_order ); + + for ( j = 0; j < sba_num_chans; j++ ) + { + g1 = 1.f; + g2 = 0.f; + for ( k = 0; k < output_frame; k++ ) + { + buffer_tmp[j][k] += ( g2 * gains[j] + g1 * hIsmRendererData->prev_gains[i][j] ) * buffer_td[i][k]; + g2 += 1.f / ( output_frame - 1 ); + g1 = 1.0f - g2; + } + hIsmRendererData->prev_gains[i][j] = gains[j]; + } + } + + for ( j = 0; j < sba_num_chans; j++ ) + { + mvr2r( buffer_tmp[j], buffer_td[j], output_frame ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_sba_upmixer_renderer() + * + * SBA upmix & rendering + *-------------------------------------------------------------------*/ + +void ivas_sba_upmixer_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ + float output[][L_FRAME48k], /* i/o: transport/output audio channels */ + const int16_t output_frame /* i : output frame length */ +) +{ + int16_t i, nchan_internal; + float temp; + + push_wmops( "ivas_sba_upmixer_renderer" ); + + nchan_internal = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order ); + + if ( st_ivas->nchan_transport >= 3 ) + { + /*convert WYZX downmix to WYXZ*/ + for ( i = 0; i < output_frame; i++ ) + { + temp = output[2][i]; + output[2][i] = output[3][i]; + output[3][i] = temp; + } + } + + /* Upmixer + Renderer */ + ivas_spar_dec_upmixer( st_ivas, output, nchan_internal, output_frame ); + + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC ) + { + ivas_sba_linear_renderer( output, output_frame, st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hDecoderConfig->output_config, st_ivas->hOutSetup, st_ivas->hoa_dec_mtx ); + } + + pop_wmops(); + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_sba_mtx_mult() + * + * HOA decoding with LFE insertion + *-------------------------------------------------------------------*/ + +static void ivas_sba_mtx_mult( + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t nchan_in, /* i : Number of ambisonic channels */ + const IVAS_OUTPUT_SETUP output_setup, /* i : Output configuration */ + const float *mtx_hoa_decoder /* i : HOA decoding mtx */ +) +{ + int16_t i, k, ch_idx; + int16_t idx_lfe; + float input_f[16]; + const float *hoa_decoder; + + assert( ( nchan_in >= FOA_CHANNELS ) && "Number of input channels must be at least 4 (FOA)!\n" ); + + for ( i = 0; i < output_frame; i++ ) + { + /* init*/ + idx_lfe = 0; + hoa_decoder = &mtx_hoa_decoder[0]; + for ( k = 0; k < nchan_in; k++ ) + { + input_f[k] = output_f[k][i]; + } + + /* mtx mult with LFE insertion*/ + for ( ch_idx = 0; ch_idx < ( output_setup.nchan_out_woLFE + output_setup.num_lfe ); ch_idx++ ) + { + if ( ( output_setup.num_lfe > 0 ) && ( output_setup.index_lfe[idx_lfe] == ch_idx ) ) + { + /*LFE insertion*/ + output_f[ch_idx][i] = 0.f; + if ( idx_lfe < ( output_setup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else + { + /*HOA decoding*/ + output_f[ch_idx][i] = input_f[0] * hoa_decoder[0]; + for ( k = 1; k < nchan_in; k++ ) + { + output_f[ch_idx][i] += input_f[k] * hoa_decoder[k]; + } + hoa_decoder += 16; + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_sba_linear_renderer() + * + * Linear rendering for SBA format + *-------------------------------------------------------------------*/ + +ivas_error ivas_sba_linear_renderer( + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t output_frame, /* i : output frame length per channel */ + const int16_t nchan_in, /* i : number of input ambisonics channels */ + const AUDIO_CONFIG output_config, /* i : output audio configuration */ + const IVAS_OUTPUT_SETUP output_setup, /* i : output format setup */ + const float hoa_dec_mtx[] /* i : HOA decoding mtx */ +) +{ + int16_t i; + float dmx_l; + int16_t nchan_hoa; + ivas_error error; + + error = IVAS_ERR_OK; + + /* Number of channels of HOA depends of transport format which is mixed order xH1V*/ + nchan_hoa = nchan_in; + + if ( nchan_in == 6 ) /*2H1V*/ + { + nchan_hoa = 9; + } + else if ( nchan_in == 8 ) /*3H1V*/ + { + nchan_hoa = 16; + } + + switch ( output_config ) + { + case AUDIO_CONFIG_MONO: + /* If stereo DMX, MONO = W = Cardioids L + R*/ + if ( nchan_in == 2 ) + { + for ( i = 0; i < output_frame; i++ ) + { + output_f[0][i] += output_f[1][i]; + } + } + /* else: do nothing, MONO = W*/ + break; + case AUDIO_CONFIG_STEREO: + assert( ( nchan_in >= 2 ) && "Number of input channels must be at least 2 (for W and Y)!\n" ); + + /* Compute L and R cardioids from SB format except if stereo DMX is transmitted already in this format*/ + if ( nchan_in > 2 ) + { + /*Build L/R cardioids*/ + for ( i = 0; i < output_frame; i++ ) + { + dmx_l = 0.5f * ( output_f[0][i] + output_f[1][i] ); /* cardioid_left = 0.5(W + Y) */ + output_f[1][i] = 0.5f * ( output_f[0][i] - output_f[1][i] ); /* cardioid_right = 0.5(W - Y) */ + output_f[0][i] = dmx_l; + } + } + break; + case AUDIO_CONFIG_5_1: + case AUDIO_CONFIG_7_1: + case AUDIO_CONFIG_5_1_2: + case AUDIO_CONFIG_5_1_4: + case AUDIO_CONFIG_7_1_4: + case AUDIO_CONFIG_LS_CUSTOM: + ivas_sba_mtx_mult( output_f, output_frame, nchan_hoa, output_setup, hoa_dec_mtx ); + break; + case AUDIO_CONFIG_FOA: /* Ambisonics output, order: 1 */ + case AUDIO_CONFIG_HOA2: /* Ambisonics output, order: 2 */ + case AUDIO_CONFIG_HOA3: /* Ambisonics output, order: 3 */ + for ( i = nchan_hoa; i < output_setup.nchan_out_woLFE; i++ ) + { + set_zero( output_f[i], output_frame ); + } + break; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: illegal output configuration, Exiting.\n" ); + } + + return error; +} + + +/*-------------------------------------------------------------------* + * ivas_sba_mix_matrix_determiner() + * + * Determine SBA mixing matrices + *-------------------------------------------------------------------*/ + +void ivas_sba_mix_matrix_determiner( + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + float output[][L_FRAME48k], /* i/o: transport/output audio channels */ + const int16_t bfi, /* i : BFI flag */ + const int16_t nchan_remapped, /* i : num channels after remapping of TCs */ + const int16_t output_frame /* i : output frame length */ +) +{ + int16_t i, ch; + float temp; + int16_t num_bands_out, nchan_transport, nchan_out; + + /* Convert numeric range */ + for ( ch = 0; ch < nchan_remapped; ch++ ) + { + for ( i = 0; i < output_frame; i++ ) + { + temp = output[ch][i]; + temp = floorf( temp + 0.5f ); + + if ( temp > MAX16B_FLT ) + { + temp = MAX16B_FLT; + } + else if ( temp < ( -1.0f * PCM16_TO_FLT_FAC ) ) + { + temp = ( -1.0f * PCM16_TO_FLT_FAC ); + } + temp *= ( 1.0f / PCM16_TO_FLT_FAC ); + output[ch][i] = temp; + } + } + + /* AGC */ + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + nchan_out = nchan_transport; + ivas_agc_dec_process( hSpar->hAgcDec, output, output, nchan_transport, output_frame ); + + /* Convert numeric range back */ + for ( ch = 0; ch < nchan_out; ch++ ) + { + for ( i = 0; i < output_frame; i++ ) + { + output[ch][i] = output[ch][i] * PCM16_TO_FLT_FAC; + } + } + + /* Mixing matrix determiner */ + num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; + ivas_spar_dec_gen_umx_mat( hSpar->hMdDec, nchan_transport, num_bands_out, bfi ); + + return; +} + + +#ifdef DEBUG_MODE_DIRAC +/*-----------------------------------------------------------------------* + * Debugging function + *-----------------------------------------------------------------------*/ + +static void debug_mode_dirac( + float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], + const int16_t nchan_transport, + const int16_t output_frame ) +{ + int16_t i, n; + int16_t tmp[L_FRAME48k]; + char file_name[50] = { 0 }; + +#ifdef DEBUG_MODE_DIRAC_NOCORE + for ( n = 0; n < nchan_transport; n++ ) + { + sprintf( file_name, "./res/ivas_dirac_enc_%d.%d.pcm", n, (int16_t) ( output_frame * 0.05 ) ); + dbgread( tmp, sizeof( int16_t ), output_frame, file_name ); + for ( i = 0; i < output_frame; i++ ) + { + output[n][i] = (float) ( tmp[i] ); + } + } +#else + for ( n = 0; n < nchan_transport; n++ ) + { + for ( i = 0; i < output_frame; i++ ) + { + tmp[i] = (int16_t) ( output[n][i] + 0.5f ); + } + + sprintf( file_name, "./res/ivas_dirac_dec_%d.%d.pcm", n, (int16_t) ( output_frame * 0.05 ) ); + dbgwrite( tmp, sizeof( int16_t ), output_frame, 1, file_name ); + } +#endif + + return; +} +#endif diff --git a/lib_dec/ivas_sce_dec.c b/lib_dec/ivas_sce_dec.c index e14754567eb4b4f88496d3d8503c133071e7a00f..064cdbb4e093afee49f03aec8b479615008039f5 100644 --- a/lib_dec/ivas_sce_dec.c +++ b/lib_dec/ivas_sce_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* @@ -67,7 +67,7 @@ ivas_error ivas_sce_dec( error = IVAS_ERR_OK; - wmops_sub_start( "ivas_sce_dec" ); + push_wmops( "ivas_sce_dec" ); hSCE = st_ivas->hSCE[sce_id]; st = hSCE->hCoreCoder[0]; @@ -77,12 +77,21 @@ ivas_error ivas_sce_dec( ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; +#ifdef DISCRETE_ISM_DTX_CNG + if ( st_ivas->ivas_format == ISM_FORMAT ) +#else + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) +#endif + { + st->cng_type = FD_CNG; + } + /*------------------------------------------------------------------* * Read audio bandwidth info *-----------------------------------------------------------------*/ /* set total_brate - needed in DTX */ - if ( !st_ivas->bfi && ( ivas_total_brate == IVAS_SID_4k4 || ivas_total_brate == IVAS_SID_5k ) ) + if ( !st_ivas->bfi && ( ivas_total_brate == IVAS_SID_5k2 ) ) { st->total_brate = ivas_total_brate - nb_bits_metadata * FRAMES_PER_SEC; assert( st->total_brate == SID_2k40 && "SCE SID must be 2.4kbps!" ); @@ -91,10 +100,21 @@ ivas_error ivas_sce_dec( { st->total_brate = ivas_total_brate; } - else if ( !st_ivas->bfi && ( last_ivas_total_brate <= SID_2k40 || last_ivas_total_brate == IVAS_SID_4k4 ) ) +#ifdef DISCRETE_ISM_DTX_CNG + else if ( !st_ivas->bfi && st_ivas->ivas_format != ISM_FORMAT && last_ivas_total_brate <= IVAS_SID_5k2 ) { st->total_brate = hSCE->element_brate - nb_bits_metadata * FRAMES_PER_SEC; } +#else + else if ( !st_ivas->bfi && ( last_ivas_total_brate <= SID_2k40 || last_ivas_total_brate == IVAS_SID_5k2 ) ) + { + /* check if this is indeed needed? */ + if ( st_ivas->ivas_format != ISM_FORMAT ) + { + st->total_brate = hSCE->element_brate - nb_bits_metadata * FRAMES_PER_SEC; + } + } +#endif /* read the bandwidth */ if ( st_ivas->bfi || st->total_brate <= SID_2k40 ) @@ -105,7 +125,7 @@ ivas_error ivas_sce_dec( { if ( st->low_rate_mode ) { - /* ISm Low-rate mode -> always WB */ + /* ISM Low-rate mode -> always WB */ st->bwidth = WB; } else if ( hSCE->element_brate < MIN_BRATE_SWB_SCE ) @@ -153,7 +173,7 @@ ivas_error ivas_sce_dec( } else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - st->bits_frame_nominal = (int16_t) ( st_ivas->hSpar->hSparFoa->core_nominal_brate / FRAMES_PER_SEC ); + st->bits_frame_nominal = (int16_t) ( st_ivas->hSpar->core_nominal_brate / FRAMES_PER_SEC ); } else { @@ -161,7 +181,7 @@ ivas_error ivas_sce_dec( } /* set "total_brate" */ - if ( !st_ivas->bfi && ( ivas_total_brate == IVAS_SID_4k4 || ivas_total_brate == IVAS_SID_5k ) ) + if ( !st_ivas->bfi && ( ivas_total_brate == IVAS_SID_5k2 ) ) { st->total_brate = ivas_total_brate - nb_bits_metadata * FRAMES_PER_SEC; } @@ -188,7 +208,6 @@ ivas_error ivas_sce_dec( st->flag_ACELP16k = set_ACELP_flag( IVAS_SCE, hSCE->element_brate, st->total_brate, 0, 0, -1, -1 ); } - /*TODO : check if is_SIDrate() can be used here*/ if ( is_DTXrate( ivas_total_brate ) ) { st->VAD = 0; @@ -215,12 +234,11 @@ ivas_error ivas_sce_dec( * Decoder *----------------------------------------------------------------*/ - if ( ( error = ivas_core_dec( NULL, hSCE, NULL, NULL, 1, output, outputHB, NULL, st_ivas->sba_dirac_stereo_flag ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_core_dec( st_ivas, hSCE, NULL, NULL, 1, output, outputHB, NULL, st_ivas->sba_dirac_stereo_flag ) ) != IVAS_ERR_OK ) { return error; } - if ( st_ivas->sba_dirac_stereo_flag && ( st->core_brate > SID_2k40 || st->cng_type == LP_CNG ) ) { /* skip addition of ACELP BWE for now, will be done after upmix */ @@ -274,14 +292,18 @@ ivas_error ivas_sce_dec( for ( i = 0; i < n; i++ ) { dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "element_brate", 0, sce_id, DEC ) ); - dbgwrite( &st->element_mode, 2, 1, output_frame, fname( debug_dir, "element_mode", 0, sce_id, DEC ) ); + dbgwrite( &st->element_mode, sizeof( int16_t ), 1, output_frame, fname( debug_dir, "element_mode", 0, sce_id, DEC ) ); dbgwrite( output, sizeof( float ), output_frame, 1, fname( debug_dir, "output.sce", 0, sce_id, DEC ) ); + tmpF = 0; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.cpe", 0, sce_id, DEC ) ); + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, fname( debug_dir, "output.mct", 0, sce_id, DEC ) ); } } #endif - wmops_sub_end(); + + pop_wmops(); return error; } @@ -310,7 +332,7 @@ ivas_error create_sce_dec( * Allocate SCE handle *-----------------------------------------------------------------*/ - if ( ( hSCE = (SCE_DEC_HANDLE) count_malloc( sizeof( SCE_DEC_DATA ) ) ) == NULL ) + if ( ( hSCE = (SCE_DEC_HANDLE) malloc( sizeof( SCE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SCE\n" ) ); } @@ -328,7 +350,7 @@ ivas_error create_sce_dec( * Core Coder, 1 instance: allocate and initialize *-----------------------------------------------------------------*/ - if ( ( st = (DEC_CORE_HANDLE) count_malloc( sizeof( Decoder_State ) ) ) == NULL ) + if ( ( st = (DEC_CORE_HANDLE) malloc( sizeof( Decoder_State ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); } @@ -338,16 +360,16 @@ ivas_error create_sce_dec( st->total_brate = hSCE->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( ( error = init_decoder( st, 0, st_ivas->mc_mode ) ) != IVAS_ERR_OK ) -#else - if ( ( error = init_decoder( st, 0 ) ) != IVAS_ERR_OK ) -#endif { return error; } +#ifdef SBA2MONO + if ( st_ivas->ivas_format == SBA_FORMAT && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO || ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO && st_ivas->nchan_transport == 1 ) ) ) +#else if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) +#endif { if ( ( error = openCldfb( &st->cldfbSynHB, CLDFB_SYNTHESIS, st->output_Fs, CLDFB_PROTOTYPE_1_25MS ) ) != IVAS_ERR_OK ) { @@ -362,7 +384,7 @@ ivas_error create_sce_dec( /* allocate and initialize "hTdCngDec" - needed in DTX */ if ( sce_id == 0 && st->hTdCngDec == NULL ) { - if ( ( st->hTdCngDec = (TD_CNG_DEC_HANDLE) count_malloc( sizeof( TD_CNG_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTdCngDec = (TD_CNG_DEC_HANDLE) malloc( sizeof( TD_CNG_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n" ) ); } @@ -376,13 +398,13 @@ ivas_error create_sce_dec( if ( st_ivas->sba_dirac_stereo_flag ) { - if ( ( hSCE->save_synth = (float *) count_malloc( sizeof( float ) * output_frame ) ) == NULL ) + if ( ( hSCE->save_synth = (float *) malloc( sizeof( float ) * output_frame ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) ); } set_zero( hSCE->save_synth, output_frame ); - if ( ( hSCE->save_hb_synth = (float *) count_malloc( sizeof( float ) * output_frame ) ) == NULL ) + if ( ( hSCE->save_hb_synth = (float *) malloc( sizeof( float ) * output_frame ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) ); } @@ -419,22 +441,22 @@ void destroy_sce_dec( { destroy_core_dec( st ); - count_free( st ); + free( st ); st = NULL; } if ( hSCE->save_synth != NULL ) { - count_free( hSCE->save_synth ); + free( hSCE->save_synth ); hSCE->save_synth = NULL; } if ( hSCE->save_hb_synth != NULL ) { - count_free( hSCE->save_hb_synth ); + free( hSCE->save_hb_synth ); hSCE->save_hb_synth = NULL; } - count_free( hSCE ); + free( hSCE ); return; } diff --git a/lib_dec/ivas_sns_dec.c b/lib_dec/ivas_sns_dec.c index 444a76cf803645eb9429c11e88db19cb13205ff8..7aecb898d139a033876c4916c8ec4aebadeaab30 100644 --- a/lib_dec/ivas_sns_dec.c +++ b/lib_dec/ivas_sns_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,7 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * sns_1st_dec() diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index d4e79296fbf979d95dc5b83aded7c031480bf763..01e4db2ed40c3764b0b9d07e375cb255767d39c2 100644 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,52 +39,124 @@ #include "prot.h" #include "string.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_rom_com.h" #include "ivas_stat_com.h" #include #include -#include "wmops.h" +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * Local function prototypes + *--------------------------------------------------------------------*/ + +static void ivas_spar_dec_MD( Decoder_Struct *st_ivas, Decoder_State *st0 ); /*------------------------------------------------------------------------- * ivas_spar_dec_open() * - * Allocate and initialize SPAR handle + * Allocate and initialize SPAR decoder handle and sub-handles *------------------------------------------------------------------------*/ ivas_error ivas_spar_dec_open( - Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ) { SPAR_DEC_HANDLE hSpar; ivas_error error; int16_t sba_order_internal, num_channels_internal; + IVAS_FB_CFG *fb_cfg; + int16_t i, j, b, active_w_mixing; + int32_t output_Fs; error = IVAS_ERR_OK; + sba_order_internal = min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ); + num_channels_internal = ivas_sba_get_nchan_metadata( sba_order_internal ); + hSpar = st_ivas->hSpar; - sba_order_internal = min( st_ivas->sba_order, IVAS_MAX_SBA_ORDER ); + if ( !spar_reconfig_flag ) + { + /* SPAR decoder handle */ + if ( ( hSpar = (SPAR_DEC_HANDLE) malloc( sizeof( SPAR_DEC_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR decoder" ); + } + } - num_channels_internal = ivas_sba_get_nchan_metadata( sba_order_internal ); + output_Fs = st_ivas->hDecoderConfig->output_Fs; - /*-----------------------------------------------------------------* - * Allocate and initialize SPAR handle - *-----------------------------------------------------------------*/ + /* TD decorr. */ + if ( ( error = ivas_td_decorr_dec_open( &hSpar->hTdDecorr, output_Fs, num_channels_internal, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* MD handle */ + if ( ( error = ivas_spar_md_dec_open( &hSpar->hMdDec, st_ivas->hDecoderConfig, num_channels_internal, sba_order_internal, st_ivas->sid_format ) ) != IVAS_ERR_OK ) + { + return error; + } + hSpar->hMdDec->td_decorr_flag = 1; + hSpar->hMdDec->table_idx = -1; - if ( ( hSpar = (SPAR_DEC_HANDLE) count_malloc( sizeof( SPAR_DEC_DATA ) ) ) == NULL ) + /* set FB config. */ + active_w_mixing = -1; + if ( ( error = ivas_fb_set_cfg( &fb_cfg, SBA_FORMAT, SBA_MODE_SPAR, num_channels_internal, num_channels_internal, active_w_mixing, output_Fs ) ) != IVAS_ERR_OK ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR decoder" ); + return error; } + fb_cfg->pcm_offset = NS2SA( output_Fs, DELAY_FB_1_NS + IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ); + fb_cfg->remix_order = remix_order_set[hSpar->hMdDec->spar_md_cfg.remix_unmix_order]; - if ( ( error = ivas_spar_foa_dec_open( &hSpar->hSparFoa, st_ivas->hDecoderConfig, num_channels_internal ) ) != IVAS_ERR_OK ) + /* FB mixer handle */ + if ( ( error = ivas_FB_mixer_open( &hSpar->hFbMixer, output_Fs, fb_cfg, spar_reconfig_flag ) ) != IVAS_ERR_OK ) { return error; } + /* AGC handle */ + if ( ( error = ivas_spar_agc_dec_open( &hSpar->hAgcDec, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* PCA handle */ + hSpar->hPCA = NULL; + if ( st_ivas->hDecoderConfig->ivas_total_brate == PCA_BRATE && sba_order_internal == 1 ) + { + if ( ( hSpar->hPCA = (PCA_DEC_STATE *) malloc( sizeof( PCA_DEC_STATE ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for PCA decoder" ); + } + + ivas_pca_dec_init( hSpar->hPCA ); + } + + /* mixer_mat intitialization */ + for ( i = 0; i < num_channels_internal; i++ ) + { + for ( j = 0; j < num_channels_internal; j++ ) + { + for ( b = 0; b < IVAS_MAX_NUM_BANDS; b++ ) + { + hSpar->hMdDec->mixer_mat[i][j][b] = 0.0f; + for ( int16_t i_ts = 0; i_ts < ( MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); i_ts++ ) + { + hSpar->hMdDec->mixer_mat_prev[i_ts][i][j][b] = 0.0f; + } + } + } + } + hSpar->i_subframe = 0; + /*-----------------------------------------------------------------* * Configuration - set SPAR high-level parameters *-----------------------------------------------------------------*/ - ivas_spar_config( st_ivas->hDecoderConfig->ivas_total_brate, sba_order_internal, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &hSpar->hSparFoa->core_nominal_brate, st_ivas->sid_format ); + ivas_spar_config( st_ivas->hDecoderConfig->ivas_total_brate, sba_order_internal, &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &hSpar->core_nominal_brate, st_ivas->sid_format ); switch ( sba_order_internal ) { @@ -114,15 +186,40 @@ ivas_error ivas_spar_dec_open( *------------------------------------------------------------------------*/ void ivas_spar_dec_close( - SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ - const int32_t output_Fs /* i : output sampling rate */ + SPAR_DEC_HANDLE *hSpar, /* i/o: SPAR decoder handle */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ) { - /* SPAR FOA handle */ - ivas_spar_foa_dec_close( &hSpar->hSparFoa, output_Fs ); + if ( *hSpar == NULL || hSpar == NULL ) + { + return; + } - count_free( hSpar ); - hSpar = NULL; + /* MD handle */ + ivas_spar_md_dec_close( &( *hSpar )->hMdDec ); + + /* TD decorrelator handle */ + ivas_td_decorr_dec_close( &( *hSpar )->hTdDecorr ); + + /* FB mixer handle */ + ivas_FB_mixer_close( &( *hSpar )->hFbMixer, output_Fs, spar_reconfig_flag ); + + /* AGC */ + ivas_spar_agc_dec_close( &( *hSpar )->hAgcDec ); + + /* PCA */ + if ( ( *hSpar )->hPCA != NULL ) + { + free( ( *hSpar )->hPCA ); + ( *hSpar )->hPCA = NULL; + } + + if ( !spar_reconfig_flag ) + { + free( ( *hSpar ) ); + ( *hSpar ) = NULL; + } return; } @@ -146,7 +243,7 @@ ivas_error ivas_spar_dec( uint16_t bstr_meta[MAX_BITS_METADATA], *bit_stream_orig; ivas_error error; - wmops_sub_start( "ivas_spar_decode" ); + push_wmops( "ivas_spar_decode" ); error = IVAS_ERR_OK; hDecoderConfig = st_ivas->hDecoderConfig; @@ -156,6 +253,10 @@ ivas_error ivas_spar_dec( next_bit_pos_orig = st0->next_bit_pos; last_bit_pos = (int16_t) ( ( hDecoderConfig->ivas_total_brate / FRAMES_PER_SEC ) - 1 ); + if ( !st0->bfi && hDecoderConfig->ivas_total_brate == IVAS_SID_5k2 ) + { + last_bit_pos -= SID_FORMAT_NBITS; + } nb_bits_read_orig = *nb_bits_read; last_bit_pos -= nb_bits_read_orig; @@ -169,13 +270,974 @@ ivas_error ivas_spar_dec( st0->bits_frame = min( MAX_BITS_METADATA, last_bit_pos + 1 ); st0->total_brate = hDecoderConfig->ivas_total_brate; /* to avoid BER detect */ - ivas_spar_foa_dec_MD( st_ivas, st0 ); + ivas_spar_dec_MD( st_ivas, st0 ); *nb_bits_read = st0->next_bit_pos + nb_bits_read_orig; st0->bit_stream = bit_stream_orig; st0->next_bit_pos = next_bit_pos_orig; - wmops_sub_end(); + if ( !st0->bfi && hDecoderConfig->ivas_total_brate == IVAS_SID_5k2 ) + { + int16_t zero_pad_bits; + *nb_bits_read += SID_FORMAT_NBITS; + zero_pad_bits = (int16_t) ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - *nb_bits_read; + assert( zero_pad_bits <= 1 ); + *nb_bits_read += zero_pad_bits; + } + + pop_wmops(); return error; } + + +/*---------------------------------------------------------------------* + * Function ivas_get_spar_table_idx_from_coded_idx() + * + * Get SPAR table index + *---------------------------------------------------------------------*/ + +static int16_t ivas_get_spar_table_idx_from_coded_idx( + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t sba_order, /* i : Ambisonic (SBA) order */ + Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ + int16_t *bitlen /* o : number of bits */ +) +{ + int16_t table_idx, ind1[IVAS_SPAR_BR_TABLE_LEN]; + int16_t i, j, ind2; + + j = 0; + for ( i = 0; i < IVAS_SPAR_BR_TABLE_LEN; i++ ) + { + ind1[j] = 0; + if ( ( ivas_spar_br_table_consts[i].ivas_total_brate == ivas_total_brate ) && + ( ivas_spar_br_table_consts[i].sba_order == sba_order ) ) + { + ind1[j++] = i; + } + } + + assert( j > 0 ); + + *bitlen = ivas_get_bits_to_encode( j - 1 ); + + ind2 = get_next_indice( st0, *bitlen ); + + table_idx = ind1[ind2]; + + return table_idx; +} + + +/*---------------------------------------------------------------------* + * Function ivas_parse_spar_header() + * + * Get SPAR table index + *---------------------------------------------------------------------*/ + +static int16_t ivas_parse_spar_header( + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t sba_order, /* i : Ambisonic (SBA) order */ + Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ + int16_t *table_idx ) +{ + int16_t bitlen, bwidth; + + *table_idx = ivas_get_spar_table_idx_from_coded_idx( ivas_total_brate, sba_order, st0, &bitlen ); + + bwidth = ivas_spar_br_table_consts[( *table_idx )].bwidth; + + return bwidth; +} + + +static float get_random_number( + int16_t *seed ) +{ + float x = (float) own_random( seed ) / 32768.0f; + + return x; +} + + +static float matrix_det( + const float a00, + const float a01, + const float a10, + const float a11 ) +{ + return a00 * a11 - a01 * a10; +} + + +static void matrix_inverse( + float in[3][3], + float out[3][3], + const int16_t size ) +{ + float det, fac; + float eps = 1e-16f; + + if ( size == 1 ) + { + out[0][0] = 1.0f / max( in[0][0], eps ); + + return; + } + else if ( size == 2 ) + { + det = matrix_det( in[0][1], in[0][1], in[1][0], in[1][1] ); + fac = 1.0f / max( det, eps ); + + out[0][0] = in[1][1] * fac; + out[1][0] = in[1][0] * ( -fac ); + + out[0][1] = in[0][1] * ( -fac ); + out[1][1] = in[0][0] * fac; + + return; + } + + det = in[0][0] * matrix_det( in[1][1], in[1][2], in[2][1], in[2][2] ) - in[1][0] * matrix_det( in[0][1], in[0][2], in[2][1], in[2][2] ) + in[2][0] * matrix_det( in[0][1], in[0][2], in[1][1], in[1][2] ); + fac = 1.0f / max( det, eps ); + + out[0][0] = matrix_det( in[1][1], in[1][2], in[2][1], in[2][2] ) * fac; + out[1][0] = matrix_det( in[1][0], in[1][2], in[2][0], in[2][2] ) * ( -fac ); + out[2][0] = matrix_det( in[1][0], in[1][1], in[2][0], in[2][1] ) * fac; + + out[0][1] = matrix_det( in[0][1], in[0][2], in[2][1], in[2][2] ) * ( -fac ); + out[1][1] = matrix_det( in[0][0], in[0][2], in[2][0], in[2][2] ) * fac; + out[2][1] = matrix_det( in[0][0], in[0][1], in[2][0], in[2][1] ) * ( -fac ); + + out[0][2] = matrix_det( in[0][1], in[0][2], in[1][1], in[1][2] ) * fac; + out[1][2] = matrix_det( in[0][0], in[0][2], in[1][0], in[1][2] ) * ( -fac ); + out[2][2] = matrix_det( in[0][0], in[0][1], in[1][0], in[1][1] ) * fac; + + return; +} + + +/*---------------------------------------------------------------------* + * Function ivas_spar_get_cldfb_gains() + * + * + *---------------------------------------------------------------------*/ + +void ivas_spar_get_cldfb_gains( + SPAR_DEC_HANDLE hSpar, + HANDLE_CLDFB_FILTER_BANK cldfbAnaDec0, + HANDLE_CLDFB_FILTER_BANK cldfbSynDec0, + const DECODER_CONFIG_HANDLE hDecoderConfig ) +{ + float output_Fs = (float) hDecoderConfig->output_Fs; + int16_t pt_len, stride, num_cldfb_bands, decfb_delay; + int16_t encfb_delay, cf_start, cf_end, cf_len; + float *weights; + int16_t ts, cf_cldfb_start, cf_cldfb_end; + float cf_start_s, cf_len_s; + int16_t sample, num_cf_slots, num_samples; + float T[3 * CLDFB_NO_CHANNELS_MAX + 10 * CLDFB_NO_CHANNELS_MAX - CLDFB_NO_CHANNELS_MAX][3]; + float Tt_T[3][3]; + float Tt_T_inv[3][3]; + float Tt_tgt[3]; + float ts_inout[CLDFB_NO_CHANNELS_MAX]; + float ts_re[CLDFB_NO_CHANNELS_MAX]; + float ts_im[CLDFB_NO_CHANNELS_MAX]; + float *pp_ts_im[1], *pp_ts_re[1]; + float tgt[( 3 - 1 ) * CLDFB_NO_CHANNELS_MAX + 10 * CLDFB_NO_CHANNELS_MAX]; + int16_t seed, split_band, slot_row, slot_col, slot, tmp_idx; + + pt_len = cldfbAnaDec0->p_filter_length; + num_cldfb_bands = cldfbAnaDec0->no_channels; + + stride = NS2SA( output_Fs, DELAY_CLDFB_NS ); + encfb_delay = NS2SA( output_Fs, IVAS_FB_ENC_DELAY_NS ); + decfb_delay = NS2SA( output_Fs, IVAS_FB_DEC_DELAY_NS ); + + cf_start = (int16_t) hSpar->hFbMixer->cross_fade_start_offset - encfb_delay + decfb_delay; /* time domain after CLDFB synthesis*/ + cf_end = (int16_t) hSpar->hFbMixer->cross_fade_end_offset - encfb_delay + decfb_delay; + cf_len = cf_end - cf_start; + weights = hSpar->hFbMixer->cldfb_cross_fade; + + cf_cldfb_start = (int16_t) ceil( ( cf_start - decfb_delay / 2 ) / (float) stride - 0.5f ); + cf_cldfb_end = (int16_t) ( ( cf_start - decfb_delay / 2 + cf_len ) / (float) stride - 0.5f ); + + num_cf_slots = cf_cldfb_end - cf_cldfb_start + 1; + num_samples = num_cf_slots * stride + pt_len - stride; + seed = RANDOM_INITSEED; + split_band = SPAR_DIRAC_SPLIT_START_BAND; + pp_ts_im[0] = ts_im; + pp_ts_re[0] = ts_re; + set_f( tgt, 0, ( 3 - 1 ) * CLDFB_NO_CHANNELS_MAX + 10 * CLDFB_NO_CHANNELS_MAX ); + + cf_start_s = ( cf_start - decfb_delay / 2 ) / output_Fs; + cf_len_s = hSpar->hFbMixer->cross_fade_end_offset / output_Fs - hSpar->hFbMixer->cross_fade_start_offset / output_Fs; + + for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + { + weights[ts] = ( ( ( ts + 0.5f ) * stride / output_Fs ) - cf_start_s ) / cf_len_s; + weights[ts] = max( min( weights[ts], 1.0f ), 0.0f ); + } + hSpar->hFbMixer->cldfb_cross_fade_start = cf_cldfb_start; + hSpar->hFbMixer->cldfb_cross_fade_end = cf_cldfb_end; + + if ( num_cf_slots > 3 || pt_len > 10 * CLDFB_NO_CHANNELS_MAX || stride > CLDFB_NO_CHANNELS_MAX || split_band == IVAS_MAX_NUM_BANDS ) + { + return; + } + + /* optimization*/ + /* compute time-domain cross-fade for considered time slots*/ + tmp_idx = cf_start - cf_cldfb_start * stride; + for ( sample = 0; sample < cf_len; sample++ ) + { + /* increasing window function */ + tgt[tmp_idx++] = hSpar->hFbMixer->pFilterbank_cross_fade[sample]; + } + + for ( ; tmp_idx < num_samples; tmp_idx++ ) + { + /* fill up with ones*/ + tgt[tmp_idx] = 1.0f; + } + + for ( sample = 0; sample < num_samples; sample++ ) + { + /* initialize trasnform matrix with zeros*/ + T[sample][0] = T[sample][1] = T[sample][2] = 0.0f; + } + + for ( sample = 0; sample < pt_len - stride; sample++ ) + { + /* fill internal CLDFB analysis time buffer with data*/ + float x = get_random_number( &seed ); + + cldfbAnaDec0->cldfb_state[sample] = x; + } + + for ( slot = 0; slot < num_cf_slots; slot++ ) + { + for ( sample = 0; sample < stride; sample++ ) + { + float x = get_random_number( &seed ); + ts_inout[sample] = x; + } + + cldfbAnalysis_ts( ts_inout, ts_re, ts_im, num_cldfb_bands, cldfbAnaDec0 ); + cldfb_reset_memory( cldfbSynDec0 ); + cldfbSynthesis( pp_ts_re, pp_ts_im, ts_inout, num_cldfb_bands, cldfbSynDec0 ); + + for ( sample = 0; sample < stride; sample++ ) + { + T[slot * stride + sample][slot] = ts_inout[sample]; + } + + tmp_idx = pt_len - 1; + for ( sample = stride; sample < pt_len; sample++ ) + { + T[slot * stride + sample][slot] = cldfbSynDec0->cldfb_state[tmp_idx--]; + } + } + + /* target is synthesis output times the cross-fade window*/ + for ( sample = 0; sample < num_samples; sample++ ) + { + tgt[sample] *= ( T[sample][0] + T[sample][1] + T[sample][2] ); + } + + /* compute matrices */ + for ( slot_row = 0; slot_row < num_cf_slots; slot_row++ ) + { + for ( slot_col = slot_row; slot_col < num_cf_slots; slot_col++ ) + { + Tt_T[slot_row][slot_col] = 0.0f; + for ( sample = 0; sample < num_samples; sample++ ) + { + Tt_T[slot_row][slot_col] += T[sample][slot_row] * T[sample][slot_col]; + } + } + } + + Tt_T[1][0] = Tt_T[0][1]; + Tt_T[2][0] = Tt_T[0][2]; + Tt_T[2][1] = Tt_T[1][2]; + + for ( slot_row = 0; slot_row < num_cf_slots; slot_row++ ) + { + Tt_tgt[slot_row] = 0.0f; + for ( sample = 0; sample < num_samples; sample++ ) + { + Tt_tgt[slot_row] += T[sample][slot_row] * tgt[sample]; + } + } + + matrix_inverse( Tt_T, Tt_T_inv, num_cf_slots ); + + /* compute the optimal coefficients */ + for ( slot_row = 0; slot_row < num_cf_slots; slot_row++ ) + { + float tmp = 0.0f; + for ( slot_col = 0; slot_col < num_cf_slots; slot_col++ ) + { + tmp += Tt_T_inv[slot_row][slot_col] * Tt_tgt[slot_col]; + } + weights[cf_cldfb_start + slot_row] = max( min( tmp, 1.0f ), 0.0f ); + } + + cldfb_reset_memory( cldfbSynDec0 ); + cldfb_reset_memory( cldfbAnaDec0 ); + + return; +} + + +/*---------------------------------------------------------------------* + * Function ivas_is_res_channel() + * + * determines if an FOA input channel is transmitted as residual channel. + *---------------------------------------------------------------------*/ + +/* !r: 1 if prediction residual channel */ +int16_t ivas_is_res_channel( + const int16_t ch, /* i : ch index in WYZX ordering */ + const int16_t nchan_transport /* i : number of transport channels (1-4) */ +) +{ + const int16_t rc_map[FOA_CHANNELS][FOA_CHANNELS] = { + { 0, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 1, 0, 1 }, + { 0, 1, 1, 1 } + }; + + if ( ch >= FOA_CHANNELS ) + { + /* never transmitted */ + return 0; + } + assert( nchan_transport <= FOA_CHANNELS ); + + return ( rc_map[nchan_transport - 1][ch] ); +} + + +/*-------------------------------------------------------------------* + * ivas_spar_dec_MD() + * + * IVAS SPAR MD decoder + *-------------------------------------------------------------------*/ + +static void ivas_spar_dec_MD( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + Decoder_State *st0 /* i/o: decoder state structure - for bitstream handling*/ +) +{ + int16_t num_channels, table_idx, num_bands_out, bfi, sba_order; + int32_t ivas_total_brate; + DECODER_CONFIG_HANDLE hDecoderConfig = st_ivas->hDecoderConfig; + SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; + + push_wmops( "ivas_spar_dec_MD" ); + + /*---------------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------------*/ + + sba_order = min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ); + bfi = st_ivas->bfi; + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + num_channels = ivas_sba_get_nchan_metadata( sba_order ); + num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; + + if ( ivas_total_brate > FRAME_NO_DATA && !bfi ) + { + if ( ivas_total_brate > IVAS_SID_5k2 ) + { + ivas_parse_spar_header( hDecoderConfig->ivas_total_brate, sba_order, st0, &table_idx ); + + if ( hSpar->hMdDec->spar_hoa_md_flag ) + { + hSpar->hMdDec->spar_md.num_bands = IVAS_MAX_NUM_BANDS; + } + else + { + hSpar->hMdDec->spar_md.num_bands = min( SPAR_DIRAC_SPLIT_START_BAND, IVAS_MAX_NUM_BANDS ); + } + + if ( hSpar->hMdDec->table_idx != table_idx ) + { + hSpar->hMdDec->table_idx = table_idx; + hSpar->hTdDecorr->ducking_flag = ivas_spar_br_table_consts[table_idx].td_ducking; + + ivas_spar_md_dec_init( hSpar->hMdDec, hDecoderConfig, num_channels, sba_order ); + } + } + + /*---------------------------------------------------------------------* + * Decode MD + *---------------------------------------------------------------------*/ + + ivas_spar_md_dec_process( st_ivas, st0, num_bands_out, sba_order ); + + /*---------------------------------------------------------------------* + * read PCA bits + *---------------------------------------------------------------------*/ + + if ( hSpar->hPCA != NULL ) + { + ivas_pca_read_bits( st0, hSpar->hPCA ); + } + + /*---------------------------------------------------------------------* + * Read AGC bits + *---------------------------------------------------------------------*/ + + if ( ivas_total_brate > IVAS_SID_5k2 && !bfi && hSpar->hMdDec->dtx_vad ) + { + hSpar->AGC_flag = get_next_indice( st0, 1 ); + + ivas_agc_read_bits( hSpar->hAgcDec, st0, hSpar->hMdDec->spar_md_cfg.nchan_transport, hSpar->AGC_flag ); + } + + /*---------------------------------------------------------------------* + * MD smoothing + *---------------------------------------------------------------------*/ + + if ( st0->m_old_frame_type == ZERO_FRAME && ivas_total_brate == IVAS_SID_5k2 && st0->prev_bfi == 0 && hSpar->hMdDec->spar_md_cfg.nchan_transport == 1 ) + { + ivas_spar_setup_md_smoothing( hSpar->hMdDec, num_bands_out ); + } + else + { + ivas_spar_update_md_hist( hSpar->hMdDec ); + } + } + else + { + if ( !bfi ) + { + ivas_spar_smooth_md_dtx( hSpar->hMdDec, num_bands_out ); + } + + set_s( hSpar->hMdDec->valid_bands, 0, IVAS_MAX_NUM_BANDS ); + } + + pop_wmops(); + return; +} + + +/*-------------------------------------------------------------------* + * ivas_spar_get_cldfb_slot_gain() + * + * + *-------------------------------------------------------------------*/ + +static float ivas_spar_get_cldfb_slot_gain( + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ + const int16_t time_slot_idx, + int16_t *time_slot_idx0, + int16_t *time_slot_idx1, + float *weight_lowfreq ) +{ + float weight; + float output_Fs, encfb_delay, decfb_delay; + float xfade_start_ns; + int16_t xfade_delay_subframes; + int16_t i_hist; + int16_t split_band; + + *weight_lowfreq = hSpar->hFbMixer->cldfb_cross_fade[time_slot_idx]; + + output_Fs = (float) hDecoderConfig->output_Fs; + encfb_delay = IVAS_FB_ENC_DELAY_NS; + decfb_delay = IVAS_FB_DEC_DELAY_NS; + xfade_start_ns = hSpar->hFbMixer->cross_fade_start_offset / output_Fs * 1000000000.f - encfb_delay + decfb_delay * 0.5f; + xfade_delay_subframes = (int16_t) ( xfade_start_ns / ( FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ) ); + + i_hist = 4 - xfade_delay_subframes; + split_band = SPAR_DIRAC_SPLIT_START_BAND; + + if ( split_band < IVAS_MAX_NUM_BANDS ) + { + if ( hSpar->i_subframe > 3 ) + { + weight = (float) ( time_slot_idx % MAX_PARAM_SPATIAL_SUBFRAMES ) / (float) MAX_PARAM_SPATIAL_SUBFRAMES; + } + else + { + weight = 0.0f; + } + *time_slot_idx0 = i_hist; + *time_slot_idx1 = i_hist + 1; + } + else + { + /* determine cross-fade gain for current frame Parameters*/ + *time_slot_idx0 = hSpar->hFbMixer->cldfb_cross_fade_start; + *time_slot_idx1 = hSpar->hFbMixer->cldfb_cross_fade_end; + weight = *weight_lowfreq; + } + + return weight; +} + + +/*-------------------------------------------------------------------* + * ivas_spar_get_parameters() + * + * + *-------------------------------------------------------------------*/ + +void ivas_spar_get_parameters( + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ + const int16_t ts, + const int16_t num_ch_out, + const int16_t num_ch_in, + const int16_t num_spar_bands, + float par_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS] ) +{ + int16_t spar_band, out_ch, in_ch; + float weight, weight_20ms; + int16_t ts0, ts1, split_band; + + weight = ivas_spar_get_cldfb_slot_gain( hSpar, hDecoderConfig, ts, &ts0, &ts1, &weight_20ms ); + + split_band = SPAR_DIRAC_SPLIT_START_BAND; + for ( spar_band = 0; spar_band < num_spar_bands; spar_band++ ) + { + for ( out_ch = 0; out_ch < num_ch_out; out_ch++ ) + { + if ( split_band < IVAS_MAX_NUM_BANDS + /* 20ms cross-fade for Transport channels in all frequency bands */ + && ( 0 == ivas_is_res_channel( out_ch, hSpar->hMdDec->spar_md_cfg.nchan_transport ) ) /* sub-frame processing for missing channels in all frequency bands*/ + ) + { + for ( in_ch = 0; in_ch < num_ch_in; in_ch++ ) + { + if ( hSpar->i_subframe > 3 ) + { + par_mat[out_ch][in_ch][spar_band] = ( 1.0f - weight ) * hSpar->hMdDec->mixer_mat_prev[ts0][out_ch][in_ch][spar_band] + + weight * hSpar->hMdDec->mixer_mat_prev[ts1][out_ch][in_ch][spar_band]; + } + else + { + par_mat[out_ch][in_ch][spar_band] = hSpar->hMdDec->mixer_mat[out_ch][in_ch][spar_band]; + } + } + } + else + { + for ( in_ch = 0; in_ch < num_ch_in; in_ch++ ) + { + /* 20ms Transport channel reconstruction with matching encoder/decoder processing */ + int16_t prev_idx = SPAR_DIRAC_SPLIT_START_BAND < IVAS_MAX_NUM_BANDS ? 1 : 0; /* if SPAR_DIRAC_SPLIT_START_BAND == IVAS_MAX_NUM_BANDS, then the sub-frame mixer_mat delay line is not active */ + par_mat[out_ch][in_ch][spar_band] = ( 1.0f - weight_20ms ) * hSpar->hMdDec->mixer_mat_prev[prev_idx][out_ch][in_ch][spar_band] + weight_20ms * hSpar->hMdDec->mixer_mat[out_ch][in_ch][spar_band]; + } + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_spar_get_skip_mat() + * + * + *-------------------------------------------------------------------*/ + +static void ivas_spar_get_skip_mat( + SPAR_DEC_HANDLE hSpar, /* i/o: SPAR decoder handle */ + const int16_t num_ch_out, + const int16_t num_ch_in, + const int16_t num_spar_bands, + int16_t skip_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH] ) +{ + int16_t spar_band, out_ch, in_ch; + int16_t i_ts, skip_flag; + + for ( out_ch = 0; out_ch < num_ch_out; out_ch++ ) + { + for ( in_ch = 0; in_ch < num_ch_in; in_ch++ ) + { + skip_mat[out_ch][in_ch] = 1; + skip_flag = 1; + + for ( i_ts = 0; i_ts < MAX_PARAM_SPATIAL_SUBFRAMES; i_ts++ ) + { + for ( spar_band = 0; spar_band < num_spar_bands; spar_band++ ) + { + if ( hSpar->hMdDec->mixer_mat_prev[1 + i_ts][out_ch][in_ch][spar_band] != 0.0f || hSpar->hMdDec->mixer_mat[out_ch][in_ch][spar_band + i_ts * MAX_PARAM_SPATIAL_SUBFRAMES] != 0.0f ) + { + skip_flag = 0; + break; + } + } + + if ( skip_flag == 0 ) + { + skip_mat[out_ch][in_ch] = 0; + break; + } + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_spar_dec_upmixer() + * + * IVAS SPAR upmixer + *-------------------------------------------------------------------*/ + +void ivas_spar_dec_upmixer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + float output[][L_FRAME48k], /* i/o: input/output audio channels */ + const int16_t nchan_internal, /* i : number of internal channels */ + const int16_t output_frame /* i : output frame length */ +) +{ + int16_t cldfb_band, num_cldfb_bands, numch_in, numch_out; + float *cldfb_in_ts_re[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX]; + float *cldfb_in_ts_im[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX]; + int16_t i, b, ts, out_ch, in_ch; + int16_t num_spar_bands, spar_band, nchan_transport; + int16_t num_in_ingest, num_bands_out, split_band; + float Pcm_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + int16_t numch_out_dirac; + float *pPcm_tmp[MAX_OUTPUT_CHANNELS]; + float mixer_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; + int16_t b_skip_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; + DECODER_CONFIG_HANDLE hDecoderConfig; + SPAR_DEC_HANDLE hSpar; + + push_wmops( "ivas_spar_dec_upmixer" ); + + hSpar = st_ivas->hSpar; + hDecoderConfig = st_ivas->hDecoderConfig; + num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + + num_cldfb_bands = hSpar->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands; + numch_in = hSpar->hFbMixer->fb_cfg->num_in_chans; + numch_out = hSpar->hFbMixer->fb_cfg->num_out_chans; + +#ifdef DEBUG_SPAR_BYPASS_EVS_CODEC + /* by-pass core-coder */ + /*write the core coder output to a file for debugging*/ + { + float tmp; + int16_t pcm, j; + for ( j = 0; j < output_frame; j++ ) + { + for ( i = 0; i < nchan_transport; i++ ) + { + tmp = roundf( output[i][j] * PCM16_TO_FLT_FAC ); + pcm = ( tmp > MAX16B_FLT ) ? MAX16B : ( tmp < MIN16B_FLT ) ? MIN16B + : (short) tmp; + dbgwrite( &pcm, sizeof( int16_t ), 1, 1, "dmx_dec.raw" ); + } + } + } + + /*overwrite the core coder output with core input for debugging*/ + { + static FILE *fid_enc = 0; + int16_t smp; + + if ( !fid_enc ) + { + fid_enc = fopen( "evs_input_float.raw", "rb" ); + } + for ( smp = 0; smp < L_FRAME48k; smp++ ) + { + for ( in_ch = 0; in_ch < nchan_transport; in_ch++ ) + { + fread( &output[in_ch][smp], sizeof( float ), 1, fid_enc ); + } + } + } +#endif + + /*---------------------------------------------------------------------* + * AGC + *---------------------------------------------------------------------*/ + + ivas_agc_dec_process( hSpar->hAgcDec, output, output, nchan_transport, output_frame ); + +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after ivas_agc_dec_process */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[1], "ivas_agc_dec_process()" ); +#endif + + /*---------------------------------------------------------------------* + * TD Decorr and pcm ingest + *---------------------------------------------------------------------*/ + + if ( hSpar->hMdDec->td_decorr_flag ) + { + num_in_ingest = nchan_internal; + } + else + { + num_in_ingest = nchan_transport; + } + + for ( i = 0; i < nchan_internal; i++ ) + { + pPcm_tmp[i] = Pcm_tmp[i]; + } + + /*---------------------------------------------------------------------* + * PCA decoder + *---------------------------------------------------------------------*/ +#ifdef DEBUG_SBA_AUDIO_DUMP + hSpar->pca_ingest_channels = num_in_ingest; +#endif + + if ( hSpar->hPCA != NULL ) + { + ivas_pca_dec( hSpar->hPCA, output_frame, num_in_ingest, hDecoderConfig->ivas_total_brate, hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, output ); +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after ivas_pca_dec */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, num_in_ingest, spar_foa_dec_wav[2], "ivas_pca_dec()" ); +#endif + } + + + /*---------------------------------------------------------------------* + * TD decorrelation + *---------------------------------------------------------------------*/ + + if ( hSpar->hMdDec->td_decorr_flag ) + { + ivas_td_decorr_process( hSpar->hTdDecorr, output, pPcm_tmp, output_frame ); + + for ( i = 0; i < nchan_internal - nchan_transport; i++ ) + { + mvr2r( pPcm_tmp[hSpar->hTdDecorr->num_apd_outputs - 1 - i], output[nchan_internal - 1 - i], output_frame ); + } + } + + hSpar->hFbMixer->fb_cfg->num_in_chans = num_in_ingest; + + + /*---------------------------------------------------------------------* + * Prepare CLDFB buffers + *---------------------------------------------------------------------*/ + + /* set-up pointers */ + if ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA ) + { + /* at this point, output channels are used as intermediate procesing buffers */ + for ( in_ch = 0; in_ch < MAX_OUTPUT_CHANNELS; in_ch++ ) + { + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + cldfb_in_ts_re[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands]; + cldfb_in_ts_im[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands + 4 * num_cldfb_bands]; + } + } + } + else + { + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + cldfb_in_ts_re[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands]; + cldfb_in_ts_im[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands + 4 * num_cldfb_bands]; + } + } + } + + /*---------------------------------------------------------------------* + * Gen umx mat + *---------------------------------------------------------------------*/ + + ivas_spar_dec_gen_umx_mat( hSpar->hMdDec, nchan_transport, num_bands_out, st_ivas->bfi ); + + + /*---------------------------------------------------------------------* + * CLDFB Processing and Synthesis + *---------------------------------------------------------------------*/ + + num_spar_bands = hSpar->hFbMixer->pFb->filterbank_num_bands; + + /* apply parameters */ + /* determine if we can skip certain data */ + ivas_spar_get_skip_mat( hSpar, numch_out, numch_in, num_spar_bands, b_skip_mat ); /* this can be precomputed based on bitrate and format*/ + + numch_out_dirac = hDecoderConfig->nchan_out; + + for ( int16_t i_sf = 0; i_sf < MAX_PARAM_SPATIAL_SUBFRAMES; i_sf++ ) + { + /* CLDFB analysis of incoming frame */ + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + cldfbAnalysis_ts( + &output[in_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], + cldfb_in_ts_re[in_ch][ts], + cldfb_in_ts_im[in_ch][ts], + num_cldfb_bands, + st_ivas->cldfbAnaDec[in_ch] ); + } + } + + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + /* determine SPAR parameters for this time slots */ + ivas_spar_get_parameters( hSpar, hDecoderConfig, ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES, numch_out, numch_in, num_spar_bands, mixer_mat ); + + for ( cldfb_band = 0; cldfb_band < num_cldfb_bands; cldfb_band++ ) + { + float out_re[IVAS_SPAR_MAX_CH]; + float out_im[IVAS_SPAR_MAX_CH]; + float cldfb_par; + ivas_fb_bin_to_band_data_t *bin2band = &hSpar->hFbMixer->pFb->fb_bin_to_band; + + for ( out_ch = 0; out_ch < numch_out; out_ch++ ) + { + out_re[out_ch] = 0.0f; + out_im[out_ch] = 0.0f; + + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + if ( b_skip_mat[out_ch][in_ch] ) + { + continue; + } + else if ( cldfb_band < CLDFB_PAR_WEIGHT_START_BAND ) /* tuning parameter, depends on how much SPAR Filters overlap for the CLDFB bands */ + { + spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band]; + cldfb_par = mixer_mat[out_ch][in_ch][spar_band]; + } + else + { + cldfb_par = 0.0f; + for ( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ ) + { + /* accumulate contributions from all SPAR bands */ + cldfb_par += mixer_mat[out_ch][in_ch][spar_band] * bin2band->pp_cldfb_weights_per_spar_band[cldfb_band][spar_band]; + } + } + + out_re[out_ch] += cldfb_in_ts_re[in_ch][ts][cldfb_band] * cldfb_par; + out_im[out_ch] += cldfb_in_ts_im[in_ch][ts][cldfb_band] * cldfb_par; + } + } + + /*update CLDFB data with the parameter-modified data*/ + for ( out_ch = 0; out_ch < numch_out; out_ch++ ) + { + cldfb_in_ts_re[out_ch][ts][cldfb_band] = out_re[out_ch]; + cldfb_in_ts_im[out_ch][ts][cldfb_band] = out_im[out_ch]; + } + } + } + + if ( hDecoderConfig->output_config != AUDIO_CONFIG_FOA && hDecoderConfig->output_config != AUDIO_CONFIG_STEREO && hDecoderConfig->output_config != AUDIO_CONFIG_MONO ) + { + ivas_dirac_dec( st_ivas, output, nchan_internal, cldfb_in_ts_re, cldfb_in_ts_im, i_sf ); + } + + if ( st_ivas->hDirAC != NULL ) + { + int16_t outchannels, idx_in, idx_lfe, ch; + idx_in = 0; + idx_lfe = 0; + + outchannels = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + for ( ch = 0; ch < outchannels; ch++ ) + { + if ( ( st_ivas->hOutSetup.num_lfe > 0 ) && ( st_ivas->hOutSetup.index_lfe[idx_lfe] == ch ) ) + { + set_zero( &( output[ch][i_sf * MAX_PARAM_SPATIAL_SUBFRAMES * num_cldfb_bands] ), MAX_PARAM_SPATIAL_SUBFRAMES * num_cldfb_bands ); + + if ( idx_lfe < ( st_ivas->hDirAC->hOutSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else + { + if ( hDecoderConfig->output_config == AUDIO_CONFIG_FOA || !( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL || st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) + { + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + cldfbSynthesis( + &cldfb_in_ts_re[idx_in][ts], + &cldfb_in_ts_im[idx_in][ts], + &output[ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], + num_cldfb_bands, + st_ivas->cldfbSynDec[idx_in] ); + } + } + idx_in++; + } + } +#ifdef DEBUG_SBA_AUDIO_DUMP + hSpar->numOutChannels = outchannels; +#endif + } + else + { + /* CLDFB to time synthesis (overwrite mixer output) */ + for ( out_ch = 0; out_ch < numch_out_dirac; out_ch++ ) + { + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + cldfbSynthesis( + &cldfb_in_ts_re[out_ch][ts], + &cldfb_in_ts_im[out_ch][ts], + &output[out_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], + num_cldfb_bands, + st_ivas->cldfbSynDec[out_ch] ); + } + } +#ifdef DEBUG_SBA_AUDIO_DUMP + hSpar->numOutChannels = numch_out_dirac; +#endif + } +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after cldfbSynthesis */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, hSpar->numOutChannels, spar_foa_dec_wav[3], "cldfbSynthesis()" ); +#endif + + split_band = SPAR_DIRAC_SPLIT_START_BAND; + if ( split_band < IVAS_MAX_NUM_BANDS ) + { + hSpar->i_subframe++; + hSpar->i_subframe = min( hSpar->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[1][0][0], hSpar->hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[2][0][0], hSpar->hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[3][0][0], hSpar->hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[4][0][0], hSpar->hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + + for ( out_ch = 0; out_ch < numch_out; out_ch++ ) + { + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + for ( b = 0; b < num_spar_bands; b++ ) + { + hSpar->hMdDec->mixer_mat_prev[4][out_ch][in_ch][b] = hSpar->hMdDec->mixer_mat[out_ch][in_ch][b + i_sf * IVAS_MAX_NUM_BANDS]; + } + } + } + } + } + + pop_wmops(); + + return; +} diff --git a/lib_dec/ivas_spar_foa_dec.c b/lib_dec/ivas_spar_foa_dec.c deleted file mode 100644 index a96595abc08b6a9c1cc827a9c161574ab5695200..0000000000000000000000000000000000000000 --- a/lib_dec/ivas_spar_foa_dec.c +++ /dev/null @@ -1,1158 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "math.h" -#include "ivas_prot.h" -#include "prot.h" -#include "ivas_rom_com.h" -#include -#include "wmops.h" - - -#ifdef DEBUG_SPAR_FOA -extern FILE *fFb_pcm; -#endif - -/*----------------------------------------------------------------------* - * Local constants - *----------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------* - * Function ivas_get_spar_table_idx_from_coded_idx() - * - * Get SPAR table index - *---------------------------------------------------------------------*/ - -static int16_t ivas_get_spar_table_idx_from_coded_idx( - const int32_t ivas_total_brate, /* i : IVAS total bitrate */ - const int16_t sba_order, /* i : Ambisonic (SBA) order */ - Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ - int16_t *bitlen /* o : number of bits */ -) -{ - int16_t table_idx, ind1[IVAS_SPAR_BR_TABLE_LEN]; - int16_t i, j, ind2; - - j = 0; - for ( i = 0; i < IVAS_SPAR_BR_TABLE_LEN; i++ ) - { - ind1[j] = 0; - if ( ( ivas_spar_br_table_consts[i].ivas_total_brate == ivas_total_brate ) && - ( ivas_spar_br_table_consts[i].sba_order == sba_order ) ) - { - ind1[j++] = i; - } - } - - assert( j > 0 ); - - *bitlen = ivas_get_bits_to_encode( j - 1 ); - - ind2 = get_next_indice( st0, *bitlen ); - - table_idx = ind1[ind2]; - - return table_idx; -} - - -/*---------------------------------------------------------------------* - * Function ivas_parse_spar_header() - * - * Get SPAR table index - *---------------------------------------------------------------------*/ - -static int16_t ivas_parse_spar_header( - const int32_t ivas_total_brate, /* i : IVAS total bitrate */ - const int16_t sba_order, /* i : Ambisonic (SBA) order */ - Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ - int16_t *table_idx ) -{ - int16_t bitlen, bwidth; - - *table_idx = ivas_get_spar_table_idx_from_coded_idx( ivas_total_brate, sba_order, st0, &bitlen ); - - bwidth = ivas_spar_br_table_consts[( *table_idx )].bwidth; - - return bwidth; -} - - -static float get_random_number( - int16_t *seed ) -{ - float x = (float) own_random( seed ) / 32768.0f; - - return x; -} - - -static float matrix_det( - const float a00, - const float a01, - const float a10, - const float a11 ) -{ - return a00 * a11 - a01 * a10; -} - - -static void matrix_inverse( - float in[3][3], - float out[3][3], - const int16_t size ) -{ - float det, fac; - float eps = 1e-16f; - - if ( size == 1 ) - { - out[0][0] = 1.0f / max( in[0][0], eps ); - - return; - } - else if ( size == 2 ) - { - det = matrix_det( in[0][1], in[0][1], in[1][0], in[1][1] ); - fac = 1.0f / max( det, eps ); - - out[0][0] = in[1][1] * fac; - out[1][0] = in[1][0] * ( -fac ); - - out[0][1] = in[0][1] * ( -fac ); - out[1][1] = in[0][0] * fac; - - return; - } - - det = in[0][0] * matrix_det( in[1][1], in[1][2], in[2][1], in[2][2] ) - in[1][0] * matrix_det( in[0][1], in[0][2], in[2][1], in[2][2] ) + in[2][0] * matrix_det( in[0][1], in[0][2], in[1][1], in[1][2] ); - fac = 1.0f / max( det, eps ); - - out[0][0] = matrix_det( in[1][1], in[1][2], in[2][1], in[2][2] ) * fac; - out[1][0] = matrix_det( in[1][0], in[1][2], in[2][0], in[2][2] ) * ( -fac ); - out[2][0] = matrix_det( in[1][0], in[1][1], in[2][0], in[2][1] ) * fac; - - out[0][1] = matrix_det( in[0][1], in[0][2], in[2][1], in[2][2] ) * ( -fac ); - out[1][1] = matrix_det( in[0][0], in[0][2], in[2][0], in[2][2] ) * fac; - out[2][1] = matrix_det( in[0][0], in[0][1], in[2][0], in[2][1] ) * ( -fac ); - - out[0][2] = matrix_det( in[0][1], in[0][2], in[1][1], in[1][2] ) * fac; - out[1][2] = matrix_det( in[0][0], in[0][2], in[1][0], in[1][2] ) * ( -fac ); - out[2][2] = matrix_det( in[0][0], in[0][1], in[1][0], in[1][1] ) * fac; - - return; -} - - -/*---------------------------------------------------------------------* - * Function ivas_spar_get_cldfb_gains() - * - * - *---------------------------------------------------------------------*/ - -void ivas_spar_get_cldfb_gains( - ivas_spar_foa_dec_state_t *hSparFoa, - HANDLE_CLDFB_FILTER_BANK cldfbAnaDec0, - HANDLE_CLDFB_FILTER_BANK cldfbSynDec0, - const DECODER_CONFIG_HANDLE hDecoderConfig ) -{ - float output_Fs = (float) hDecoderConfig->output_Fs; - int16_t pt_len, stride, num_cldfb_bands, decfb_delay; - int16_t encfb_delay, cf_start, cf_end, cf_len; - float *weights; - int16_t ts, cf_cldfb_start, cf_cldfb_end; - float cf_start_s, cf_len_s; - int16_t sample, num_cf_slots, num_samples; - float T[3 * CLDFB_NO_CHANNELS_MAX + 10 * CLDFB_NO_CHANNELS_MAX - CLDFB_NO_CHANNELS_MAX][3]; - float Tt_T[3][3]; - float Tt_T_inv[3][3]; - float Tt_tgt[3]; - float ts_inout[CLDFB_NO_CHANNELS_MAX]; - float ts_re[CLDFB_NO_CHANNELS_MAX]; - float ts_im[CLDFB_NO_CHANNELS_MAX]; - float *pp_ts_im[1], *pp_ts_re[1]; - float tgt[( 3 - 1 ) * CLDFB_NO_CHANNELS_MAX + 10 * CLDFB_NO_CHANNELS_MAX]; - int16_t seed, split_band, slot_row, slot_col, slot, tmp_idx; - - pt_len = cldfbAnaDec0->p_filter_length; - num_cldfb_bands = cldfbAnaDec0->no_channels; - - stride = NS2SA( output_Fs, DELAY_CLDFB_NS ); - encfb_delay = NS2SA( output_Fs, IVAS_FB_ENC_DELAY_NS ); - decfb_delay = NS2SA( output_Fs, IVAS_FB_DEC_DELAY_NS ); - - cf_start = (int16_t) hSparFoa->hFbMixer->cross_fade_start_offset - encfb_delay + decfb_delay; /* time domain after CLDFB synthesis*/ - cf_end = (int16_t) hSparFoa->hFbMixer->cross_fade_end_offset - encfb_delay + decfb_delay; - cf_len = cf_end - cf_start; - weights = hSparFoa->hFbMixer->cldfb_cross_fade; - - cf_cldfb_start = (int16_t) ceil( ( cf_start - decfb_delay / 2 ) / (float) stride - 0.5f ); - cf_cldfb_end = (int16_t) ( ( cf_start - decfb_delay / 2 + cf_len ) / (float) stride - 0.5f ); - - num_cf_slots = cf_cldfb_end - cf_cldfb_start + 1; - num_samples = num_cf_slots * stride + pt_len - stride; - seed = RANDOM_INITSEED; - split_band = SPAR_DIRAC_SPLIT_START_BAND; - pp_ts_im[0] = ts_im; - pp_ts_re[0] = ts_re; - set_f( tgt, 0, ( 3 - 1 ) * CLDFB_NO_CHANNELS_MAX + 10 * CLDFB_NO_CHANNELS_MAX ); - - cf_start_s = ( cf_start - decfb_delay / 2 ) / output_Fs; - cf_len_s = hSparFoa->hFbMixer->cross_fade_end_offset / output_Fs - hSparFoa->hFbMixer->cross_fade_start_offset / output_Fs; - - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) - { - weights[ts] = ( ( ( ts + 0.5f ) * stride / output_Fs ) - cf_start_s ) / cf_len_s; - weights[ts] = max( min( weights[ts], 1.0f ), 0.0f ); - } - hSparFoa->hFbMixer->cldfb_cross_fade_start = cf_cldfb_start; - hSparFoa->hFbMixer->cldfb_cross_fade_end = cf_cldfb_end; - hSparFoa->hFbMixer->cldfb_latency = decfb_delay; - - if ( num_cf_slots > 3 || pt_len > 10 * CLDFB_NO_CHANNELS_MAX || stride > CLDFB_NO_CHANNELS_MAX || split_band == IVAS_MAX_NUM_BANDS ) - { - return; - } - - /* optimization*/ - /* compute time-domain cross-fade for considered time slots*/ - tmp_idx = cf_start - cf_cldfb_start * stride; - for ( sample = 0; sample < cf_len; sample++ ) - { - /* increasing window function */ - tgt[tmp_idx++] = hSparFoa->hFbMixer->pFilterbank_cross_fade[sample]; - } - - for ( ; tmp_idx < num_samples; tmp_idx++ ) - { - /* fill up with ones*/ - tgt[tmp_idx] = 1.0f; - } - - for ( sample = 0; sample < num_samples; sample++ ) - { - /* initialize trasnform matrix with zeros*/ - T[sample][0] = T[sample][1] = T[sample][2] = 0.0f; - } - - for ( sample = 0; sample < pt_len - stride; sample++ ) - { - /* fill internal CLDFB analysis time buffer with data*/ - float x = get_random_number( &seed ); - - cldfbAnaDec0->cldfb_state[sample] = x; - } - - for ( slot = 0; slot < num_cf_slots; slot++ ) - { - for ( sample = 0; sample < stride; sample++ ) - { - float x = get_random_number( &seed ); - ts_inout[sample] = x; - } - - cldfbAnalysis_ts( ts_inout, ts_re, ts_im, num_cldfb_bands, cldfbAnaDec0 ); - cldfb_reset_memory( cldfbSynDec0 ); - cldfbSynthesis( pp_ts_re, pp_ts_im, ts_inout, num_cldfb_bands, cldfbSynDec0 ); - - for ( sample = 0; sample < stride; sample++ ) - { - T[slot * stride + sample][slot] = ts_inout[sample]; - } - - tmp_idx = pt_len - 1; - for ( sample = stride; sample < pt_len; sample++ ) - { - T[slot * stride + sample][slot] = cldfbSynDec0->cldfb_state[tmp_idx--]; - } - } - - /* target is synthesis output times the cross-fade window*/ - for ( sample = 0; sample < num_samples; sample++ ) - { - tgt[sample] *= ( T[sample][0] + T[sample][1] + T[sample][2] ); - } - - /* compute matrices */ - for ( slot_row = 0; slot_row < num_cf_slots; slot_row++ ) - { - for ( slot_col = slot_row; slot_col < num_cf_slots; slot_col++ ) - { - Tt_T[slot_row][slot_col] = 0.0f; - for ( sample = 0; sample < num_samples; sample++ ) - { - Tt_T[slot_row][slot_col] += T[sample][slot_row] * T[sample][slot_col]; - } - } - } - - Tt_T[1][0] = Tt_T[0][1]; - Tt_T[2][0] = Tt_T[0][2]; - Tt_T[2][1] = Tt_T[1][2]; - - for ( slot_row = 0; slot_row < num_cf_slots; slot_row++ ) - { - Tt_tgt[slot_row] = 0.0f; - for ( sample = 0; sample < num_samples; sample++ ) - { - Tt_tgt[slot_row] += T[sample][slot_row] * tgt[sample]; - } - } - - matrix_inverse( Tt_T, Tt_T_inv, num_cf_slots ); - - /* compute the optimal coefficients */ - for ( slot_row = 0; slot_row < num_cf_slots; slot_row++ ) - { - float tmp = 0.0f; - for ( slot_col = 0; slot_col < num_cf_slots; slot_col++ ) - { - tmp += Tt_T_inv[slot_row][slot_col] * Tt_tgt[slot_col]; - } - weights[cf_cldfb_start + slot_row] = max( min( tmp, 1.0f ), 0.0f ); - } - - cldfb_reset_memory( cldfbSynDec0 ); - cldfb_reset_memory( cldfbAnaDec0 ); - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_spar_foa_dec_open() - * - * Allocate and initialize SPAR decoder handle for static memory - *------------------------------------------------------------------------*/ - -ivas_error ivas_spar_foa_dec_open( - ivas_spar_foa_dec_state_t **hSparFoa, /* i/o: SPAR FOA decoder handle */ - const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t nchan_internal /* i : number of internal channels */ -) -{ - ivas_spar_foa_dec_state_t *pState; - IVAS_FB_CFG *fb_cfg; - int16_t i, j, b, active_w_mixing; - int32_t output_Fs; - ivas_error error; - - error = IVAS_ERR_OK; - - if ( ( pState = (ivas_spar_foa_dec_state_t *) count_malloc( sizeof( ivas_spar_foa_dec_state_t ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR decoder" ); - } - - output_Fs = hDecoderConfig->output_Fs; - - /* TD decorr. */ - if ( ( error = ivas_spar_td_decorr_dec_open( &pState->hTdDecorr, output_Fs, nchan_internal, 1 ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* MD handle */ - if ( ( error = ivas_spar_foa_md_dec_open( &pState->hMdDec, hDecoderConfig, nchan_internal ) ) != IVAS_ERR_OK ) - { - return error; - } - pState->hMdDec->td_decorr_flag = 1; - pState->hMdDec->table_idx = -1; - - /* set FB config. */ - active_w_mixing = -1; - if ( ( error = ivas_fb_set_cfg( &fb_cfg, SBA_FORMAT, SBA_MODE_SPAR, nchan_internal, nchan_internal, active_w_mixing, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - fb_cfg->pcm_offset = NS2SA( output_Fs, DELAY_FB_1_NS + IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ); - fb_cfg->remix_order = remix_order_set[pState->hMdDec->spar_md_cfg.remix_unmix_order]; - - /* FB mixer handle */ - if ( ( error = ivas_FB_mixer_open( &pState->hFbMixer, output_Fs, fb_cfg ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* AGC */ - if ( ( error = ivas_spar_agc_dec_open( &pState->hAgcDec, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* PCA */ - if ( ( pState->hPCA = (PCA_DEC_STATE *) count_malloc( sizeof( PCA_DEC_STATE ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for PCA decoder" ); - } - - init_pca_dec( pState->hPCA ); - - /* mixer_mat intitialization */ - for ( i = 0; i < nchan_internal; i++ ) - { - for ( j = 0; j < nchan_internal; j++ ) - { - for ( b = 0; b < IVAS_MAX_NUM_BANDS; b++ ) - { - pState->hMdDec->mixer_mat[i][j][b] = 0.0f; - for ( int16_t i_ts = 0; i_ts < ( MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); i_ts++ ) - { - pState->hMdDec->mixer_mat_prev[i_ts][i][j][b] = 0.0f; - } - } - } - } - pState->i_subframe = 0; - - *hSparFoa = pState; - - return error; -} - - -/*------------------------------------------------------------------------- - * ivas_spar_foa_dec_close() - * - * Deallocate SPAR decoder handle for static memory - *------------------------------------------------------------------------*/ - -void ivas_spar_foa_dec_close( - ivas_spar_foa_dec_state_t **hSparFoa, /* i/o: SPAR FOA decoder handle */ - const int32_t output_Fs /* i : output sampling rate */ -) -{ - ivas_spar_foa_dec_state_t *pState; - - pState = *hSparFoa; - - if ( pState != NULL ) - { - /* MD handle */ - ivas_spar_foa_md_dec_close( &pState->hMdDec ); - - /* Covar. State handle */ - ivas_spar_td_decorr_dec_close( &pState->hTdDecorr ); - - /* FB mixer handle */ - ivas_FB_mixer_close( &pState->hFbMixer, output_Fs ); - - /* AGC */ - ivas_spar_agc_dec_close( &pState->hAgcDec ); - - /* PCA */ - if ( pState->hPCA != NULL ) - { - count_free( pState->hPCA ); - pState->hPCA = NULL; - } - - count_free( pState ); - pState = NULL; - } - - return; -} - - -/*---------------------------------------------------------------------* - * Function ivas_is_res_channel() - * - * determines if an FOA input channel is transmitted as residual channel. - *---------------------------------------------------------------------*/ - -/* !r: 1 if prediction residual channel */ -int16_t ivas_is_res_channel( - const int16_t ch, /* i : ch index in WYZX ordering */ - const int16_t nchan_transport /* i : number of transport channels (1-4) */ -) -{ - const int16_t rc_map[FOA_CHANNELS][FOA_CHANNELS] = { - { 0, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 1, 0, 1 }, - { 0, 1, 1, 1 } - }; - - if ( ch >= FOA_CHANNELS ) - { - /* never transmitted */ - return 0; - } - assert( nchan_transport <= FOA_CHANNELS ); - - return ( rc_map[nchan_transport - 1][ch] ); -} - - -/*-------------------------------------------------------------------* - * ivas_spar_foa_dec_MD() - * - * IVAS SPAR MD decoder - *-------------------------------------------------------------------*/ - -void ivas_spar_foa_dec_MD( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - Decoder_State *st0 /* i/o: decoder state structure - for bitstream handling*/ -) -{ - int16_t num_channels, table_idx, num_bands_out, bfi, sba_order; - int32_t ivas_total_brate; - DECODER_CONFIG_HANDLE hDecoderConfig = st_ivas->hDecoderConfig; - ivas_spar_foa_dec_state_t *pState = st_ivas->hSpar->hSparFoa; - - wmops_sub_start( "ivas_spar_foa_dec_MD" ); - - /*---------------------------------------------------------------------* - * Initialization - *---------------------------------------------------------------------*/ - - sba_order = min( st_ivas->sba_order, IVAS_MAX_SBA_ORDER ); - bfi = st_ivas->bfi; - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; - - num_channels = ivas_sba_get_nchan_metadata( sba_order ); - - num_bands_out = pState->hFbMixer->pFb->filterbank_num_bands; - - if ( ivas_total_brate > FRAME_NO_DATA && bfi != 1 ) - { - if ( ivas_total_brate > IVAS_SID_5k ) - { - ivas_parse_spar_header( hDecoderConfig->ivas_total_brate, sba_order, st0, &table_idx ); - - pState->hMdDec->spar_md.num_bands = min( SPAR_DIRAC_SPLIT_START_BAND, IVAS_MAX_NUM_BANDS ); - - if ( pState->hMdDec->table_idx != table_idx ) - { - pState->hMdDec->table_idx = table_idx; - pState->hTdDecorr->ducking_flag = ivas_spar_br_table_consts[table_idx].td_ducking; - - ivas_spar_foa_md_dec_init( pState->hMdDec, hDecoderConfig, num_channels ); - } - } - - - /*---------------------------------------------------------------------* - * Decode MD - *---------------------------------------------------------------------*/ - - ivas_spar_foa_md_dec_process( st_ivas, st0, num_bands_out, sba_order ); - - /*---------------------------------------------------------------------* - * read PCA bits - *---------------------------------------------------------------------*/ - - if ( hDecoderConfig->ivas_total_brate == PCA_BRATE && sba_order == 1 ) - { - ivas_pca_read_bits( st0, pState->hPCA ); - } - else - { - pState->hPCA->pca_bypass = PCA_MODE_INACTIVE; - } - - /*---------------------------------------------------------------------* - * Read AGC bits - *---------------------------------------------------------------------*/ - - if ( ivas_total_brate > IVAS_SID_5k && !bfi && ( pState->hMdDec->dtx_vad == 1 ) ) - { - pState->AGC_flag = get_next_indice( st0, 1 ); - - ivas_agc_read_bits( pState->hAgcDec, st0, pState->hMdDec->spar_md_cfg.nchan_transport, pState->AGC_flag ); - } - - /*---------------------------------------------------------------------* - * MD smoothing - *---------------------------------------------------------------------*/ - - if ( st0->m_old_frame_type == ZERO_FRAME && ivas_total_brate == IVAS_SID_5k && st0->prev_bfi == 0 && pState->hMdDec->spar_md_cfg.nchan_transport == 1 ) - { - ivas_spar_foa_setup_md_smoothing( pState->hMdDec, num_bands_out ); - } - else - { - ivas_spar_foa_update_md_hist( pState->hMdDec ); - } - } - else - { - if ( !bfi ) - { - ivas_spar_foa_smooth_md_dtx( pState->hMdDec, num_bands_out ); - } - - set_s( pState->hMdDec->valid_bands, 0, IVAS_MAX_NUM_BANDS ); - } - - wmops_sub_end(); - return; -} - - -/*-------------------------------------------------------------------* - * ivas_spar_get_cldfb_slot_gain() - * - * - *-------------------------------------------------------------------*/ - -static float ivas_spar_get_cldfb_slot_gain( - ivas_spar_foa_dec_state_t *hSparFoa, /* i/o: SPAR FOA decoder handle */ - const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t time_slot_idx, - int16_t *time_slot_idx0, - int16_t *time_slot_idx1, - float *weight_lowfreq ) -{ - ivas_spar_foa_dec_state_t *pState = hSparFoa; - float weight; - float output_Fs, encfb_delay, decfb_delay; - float xfade_start_ns; - int16_t xfade_delay_subframes; - int16_t i_hist; - int16_t split_band; - - *weight_lowfreq = pState->hFbMixer->cldfb_cross_fade[time_slot_idx]; - - output_Fs = (float) hDecoderConfig->output_Fs; - encfb_delay = IVAS_FB_ENC_DELAY_NS; - decfb_delay = IVAS_FB_DEC_DELAY_NS; - // VE: overcomplicated logic -> rewrite - xfade_start_ns = pState->hFbMixer->cross_fade_start_offset / output_Fs * 1000000000.f - encfb_delay + decfb_delay * 0.5f; - xfade_delay_subframes = (int16_t) ( xfade_start_ns / ( FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ) ); - - i_hist = 4 - xfade_delay_subframes; - split_band = SPAR_DIRAC_SPLIT_START_BAND; - - if ( split_band < IVAS_MAX_NUM_BANDS ) - { - if ( hSparFoa->i_subframe > 3 ) - { - weight = (float) ( time_slot_idx % MAX_PARAM_SPATIAL_SUBFRAMES ) / (float) MAX_PARAM_SPATIAL_SUBFRAMES; - } - else - { - weight = 0.0f; - } - *time_slot_idx0 = i_hist; - *time_slot_idx1 = i_hist + 1; - } - else - { - /* determine cross-fade gain for current frame Parameters*/ - *time_slot_idx0 = pState->hFbMixer->cldfb_cross_fade_start; - *time_slot_idx1 = pState->hFbMixer->cldfb_cross_fade_end; - weight = *weight_lowfreq; - } - - return weight; -} - - -/*-------------------------------------------------------------------* - * ivas_spar_get_parameters() - * - * - *-------------------------------------------------------------------*/ - -void ivas_spar_get_parameters( - ivas_spar_foa_dec_state_t *hSparFoa, /* i/o: SPAR FOA decoder handle */ - const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t ts, - const int16_t num_ch_out, - const int16_t num_ch_in, - const int16_t num_spar_bands, - float par_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS] ) -{ - int16_t spar_band, out_ch, in_ch; - float weight, weight_20ms; - int16_t ts0, ts1, split_band; - - weight = ivas_spar_get_cldfb_slot_gain( hSparFoa, hDecoderConfig, ts, &ts0, &ts1, &weight_20ms ); - - split_band = SPAR_DIRAC_SPLIT_START_BAND; - for ( spar_band = 0; spar_band < num_spar_bands; spar_band++ ) - { - for ( out_ch = 0; out_ch < num_ch_out; out_ch++ ) - { - for ( in_ch = 0; in_ch < num_ch_in; in_ch++ ) - { - if ( split_band < IVAS_MAX_NUM_BANDS - /* 20ms cross-fade for Transport channels in all frequency bands */ - && ( 0 == ivas_is_res_channel( out_ch, hSparFoa->hMdDec->spar_md_cfg.nchan_transport ) ) /* sub-frame processing for missing channels in all frequency bands*/ - ) - { - if ( hSparFoa->i_subframe > 3 ) - { - par_mat[out_ch][in_ch][spar_band] = ( 1.0f - weight ) * hSparFoa->hMdDec->mixer_mat_prev[ts0][out_ch][in_ch][spar_band] + - weight * hSparFoa->hMdDec->mixer_mat_prev[ts1][out_ch][in_ch][spar_band]; - } - else - { - par_mat[out_ch][in_ch][spar_band] = hSparFoa->hMdDec->mixer_mat[out_ch][in_ch][spar_band]; - } - } - else - { - /* 20ms Transport channel reconstruction with matching encoder/decoder processing */ - int16_t prev_idx = SPAR_DIRAC_SPLIT_START_BAND < IVAS_MAX_NUM_BANDS ? 1 : 0; /* if SPAR_DIRAC_SPLIT_START_BAND == IVAS_MAX_NUM_BANDS, then the sub-frame mixer_mat delay line is not active */ - par_mat[out_ch][in_ch][spar_band] = ( 1.0f - weight_20ms ) * hSparFoa->hMdDec->mixer_mat_prev[prev_idx][out_ch][in_ch][spar_band] + weight_20ms * hSparFoa->hMdDec->mixer_mat[out_ch][in_ch][spar_band]; - } - } - } - } - - return; -} - - -/*-------------------------------------------------------------------* - * ivas_spar_get_skip_mat() - * - * - *-------------------------------------------------------------------*/ - -static void ivas_spar_get_skip_mat( - ivas_spar_foa_dec_state_t *hSparFoa, /* i/o: SPAR FOA decoder handle */ - const int16_t num_ch_out, - const int16_t num_ch_in, - const int16_t num_spar_bands, - int16_t skip_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH] ) -{ - int16_t spar_band, out_ch, in_ch; - int16_t i_ts, skip_flag; - - for ( out_ch = 0; out_ch < num_ch_out; out_ch++ ) - { - for ( in_ch = 0; in_ch < num_ch_in; in_ch++ ) - { - skip_mat[out_ch][in_ch] = 1; - skip_flag = 1; - - for ( i_ts = 0; i_ts < MAX_PARAM_SPATIAL_SUBFRAMES; i_ts++ ) - { - for ( spar_band = 0; spar_band < num_spar_bands; spar_band++ ) - { - if ( hSparFoa->hMdDec->mixer_mat_prev[1 + i_ts][out_ch][in_ch][spar_band] != 0.0f || hSparFoa->hMdDec->mixer_mat[out_ch][in_ch][spar_band + i_ts * MAX_PARAM_SPATIAL_SUBFRAMES] != 0.0f ) - { - skip_flag = 0; - break; - } - } - - if ( skip_flag == 0 ) - { - skip_mat[out_ch][in_ch] = 0; - break; - } - } - } - } - - return; -} - - -/*-------------------------------------------------------------------* - * ivas_spar_foa_dec_upmixer() - * - * IVAS SPAR FOA upmixer - *-------------------------------------------------------------------*/ - -void ivas_spar_foa_dec_upmixer( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - float output[][L_FRAME48k], /* i/o: input/output audio channels */ - const int16_t nchan_internal, /* i : number of internal channels */ - const int16_t output_frame /* i : output frame length */ -) -{ - int16_t cldfb_band, num_cldfb_bands, numch_in, numch_out; - float *cldfb_in_ts_re[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX]; - float *cldfb_in_ts_im[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX]; - int16_t i, b, ts, out_ch, in_ch; - int16_t num_spar_bands, spar_band, nchan_transport; - int16_t num_in_ingest, num_bands_out, split_band; - float Pcm_tmp[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - int16_t numch_out_dirac; - float *pPcm_tmp[MAX_OUTPUT_CHANNELS]; - float mixer_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; - int16_t b_skip_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - DECODER_CONFIG_HANDLE hDecoderConfig; - ivas_spar_foa_dec_state_t *pState, *hSparFoa; - - wmops_sub_start( "ivas_spar_foa_dec_upmixer" ); - - hSparFoa = st_ivas->hSpar->hSparFoa; - pState = hSparFoa; - hDecoderConfig = st_ivas->hDecoderConfig; - num_bands_out = pState->hFbMixer->pFb->filterbank_num_bands; - nchan_transport = pState->hMdDec->spar_md_cfg.nchan_transport; - - num_cldfb_bands = hSparFoa->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands; - numch_in = hSparFoa->hFbMixer->fb_cfg->num_in_chans; - numch_out = hSparFoa->hFbMixer->fb_cfg->num_out_chans; - -#ifdef DEBUG_SPAR_FOA - if ( fFb_pcm != NULL ) - { - for ( i = 0; i < output_frame; i++ ) - { - for ( int16_t j = 0; j < nchan_transport; j++ ) - { - fscanf( fFb_pcm, "%f\n", &output[j][i] ); - } - } - } -#endif - - /* by-pass EVS */ -#ifdef DEBUG_SPAR_BYPASS_EVS_CODEC - /*write the core coder output to a file for debugging*/ - { - float tmp; - int16_t pcm, j; - for ( j = 0; j < output_frame; j++ ) - { - for ( i = 0; i < nchan_transport; i++ ) - { - tmp = roundf( output[i][j] * PCM16_TO_FLT_FAC ); - pcm = ( tmp > MAX16B_FLT ) ? MAX16B : ( tmp < MIN16B_FLT ) ? MIN16B - : (short) tmp; - dbgwrite( &pcm, sizeof( int16_t ), 1, 1, "dmx_dec.raw" ); - } - } - } - - /*overwrite the core coder output with core input for debugging*/ - { - static FILE *fid_enc = 0; - int16_t smp; - - if ( !fid_enc ) - { - fid_enc = fopen( "evs_input_float.raw", "rb" ); - } - for ( smp = 0; smp < L_FRAME48k; smp++ ) - { - for ( in_ch = 0; in_ch < nchan_transport; in_ch++ ) - { - fread( &output[in_ch][smp], sizeof( float ), 1, fid_enc ); - } - } - } -#endif - - /*---------------------------------------------------------------------* - * AGC - *---------------------------------------------------------------------*/ - - ivas_agc_dec_process( pState->hAgcDec, output, output, nchan_transport, output_frame ); - - /*---------------------------------------------------------------------* - * TD Decorr and pcm ingest - *---------------------------------------------------------------------*/ - - if ( pState->hMdDec->td_decorr_flag ) - { - num_in_ingest = nchan_internal; - } - else - { - num_in_ingest = nchan_transport; - } - - for ( i = 0; i < nchan_internal; i++ ) - { - pPcm_tmp[i] = Pcm_tmp[i]; - } - - /*---------------------------------------------------------------------* - * PCA decoder - *---------------------------------------------------------------------*/ - - ivas_pca_dec( pState->hPCA, output_frame, num_in_ingest, hDecoderConfig->ivas_total_brate, hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, output ); - - /*---------------------------------------------------------------------* - * TD decorrelation - *---------------------------------------------------------------------*/ - - if ( pState->hMdDec->td_decorr_flag ) - { - ivas_td_decorr_process( pState->hTdDecorr, output, pPcm_tmp, output_frame ); - - for ( i = 0; i < nchan_internal - nchan_transport; i++ ) - { - mvr2r( pPcm_tmp[pState->hTdDecorr->num_apd_outputs - 1 - i], output[nchan_internal - 1 - i], output_frame ); - } - - pState->hFbMixer->fb_cfg->num_in_chans = num_in_ingest; - } - else - { - pState->hFbMixer->fb_cfg->num_in_chans = num_in_ingest; - } - - /*---------------------------------------------------------------------* - * Prepare CLDFB buffers - *---------------------------------------------------------------------*/ - - /* set-up pointers */ - if ( st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_FOA ) - { - /* at this point, output channels are used as intermediate procesing buffers */ - for ( in_ch = 0; in_ch < MAX_OUTPUT_CHANNELS; in_ch++ ) - { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) - { - cldfb_in_ts_re[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands]; - cldfb_in_ts_im[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands + 4 * num_cldfb_bands]; - } - } - } - else - { - for ( in_ch = 0; in_ch < numch_in; in_ch++ ) - { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) - { - cldfb_in_ts_re[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands]; - cldfb_in_ts_im[in_ch][ts] = &Pcm_tmp[in_ch][ts * num_cldfb_bands + 4 * num_cldfb_bands]; - } - } - } - - - /*---------------------------------------------------------------------* - * Gen umx mat - *---------------------------------------------------------------------*/ - - ivas_spar_foa_dec_gen_umx_mat( pState->hMdDec, nchan_transport, num_bands_out, st_ivas->bfi ); - -#ifdef DEBUG_LBR_SBA - fprintf( stdout, "\n\mMixer matrix:\n\n" ); - for (int b = 0; b < IVAS_MAX_NUM_BANDS; b++) - { - fprintf( stdout, "band %d:\n", b ); - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - fprintf( stdout, "%f,\t", pState->hMdDec->mixer_mat[i][j][b] ); - } - if (i > 0 && b % 2 == 0) - { - fprintf( stdout, "%f,\t%f\t", pState->hMdDec->spar_md.band_coeffs[b/2].pred_re[i-1], pState->hMdDec->spar_md.band_coeffs[b/2].P_re[i-1] ); - } - fprintf( stdout, "\n" ); - } - fprintf( stdout, "\n" ); - } -#endif - /*---------------------------------------------------------------------* - * CLDFB Processing and Synthesis - *---------------------------------------------------------------------*/ - - num_spar_bands = hSparFoa->hFbMixer->pFb->filterbank_num_bands; - - /* apply parameters */ - /* determine if we can skip certain data */ - ivas_spar_get_skip_mat( hSparFoa, numch_out, numch_in, num_spar_bands, b_skip_mat ); /* this can be precomputed based on bitrate and format*/ - - numch_out_dirac = audioCfg2channels( st_ivas->hDecoderConfig->output_config ); - - for ( int16_t i_sf = 0; i_sf < MAX_PARAM_SPATIAL_SUBFRAMES; i_sf++ ) - { - /* CLDFB analysis of incoming frame */ - for ( in_ch = 0; in_ch < numch_in; in_ch++ ) - { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) - { - cldfbAnalysis_ts( - &output[in_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], - cldfb_in_ts_re[in_ch][ts], - cldfb_in_ts_im[in_ch][ts], - num_cldfb_bands, - st_ivas->cldfbAnaDec[in_ch] ); - } - } - - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) - { - /* determine SPAR parameters for this time slots */ - ivas_spar_get_parameters( hSparFoa, hDecoderConfig, ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES, numch_out, numch_in, num_spar_bands, mixer_mat ); - - for ( cldfb_band = 0; cldfb_band < num_cldfb_bands; cldfb_band++ ) - { - float out_re[IVAS_SPAR_MAX_CH]; - float out_im[IVAS_SPAR_MAX_CH]; - float cldfb_par; - ivas_fb_bin_to_band_data_t *bin2band = &pState->hFbMixer->pFb->fb_bin_to_band; - - for ( out_ch = 0; out_ch < numch_out; out_ch++ ) - { - out_re[out_ch] = 0.0f; - out_im[out_ch] = 0.0f; - - for ( in_ch = 0; in_ch < numch_in; in_ch++ ) - { - if ( b_skip_mat[out_ch][in_ch] ) - { - continue; - } - else if ( cldfb_band < CLDFB_PAR_WEIGHT_START_BAND ) /* tuning parameter, depends on how much SPAR Filters overlap for the CLDFB bands */ - { - spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band]; - cldfb_par = mixer_mat[out_ch][in_ch][spar_band]; - } - else - { - cldfb_par = 0.0f; - for ( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ ) - { - /* accumulate contributions from all SPAR bands */ - cldfb_par += mixer_mat[out_ch][in_ch][spar_band] * bin2band->pp_cldfb_weights_per_spar_band[cldfb_band][spar_band]; - } - } - - out_re[out_ch] += cldfb_in_ts_re[in_ch][ts][cldfb_band] * cldfb_par; - out_im[out_ch] += cldfb_in_ts_im[in_ch][ts][cldfb_band] * cldfb_par; - } - } - - /*update CLDFB data with the parameter-modified data*/ - for ( out_ch = 0; out_ch < numch_out; out_ch++ ) - { - cldfb_in_ts_re[out_ch][ts][cldfb_band] = out_re[out_ch]; - cldfb_in_ts_im[out_ch][ts][cldfb_band] = out_im[out_ch]; - } - } - } - - if ( st_ivas->hDecoderConfig->output_config != AUDIO_CONFIG_FOA ) - { - nchan_transport = ivas_sba_get_nchan_metadata( st_ivas->sba_order ); // VE: == nchan_internal that is already set correctly - - ivas_dirac_dec( st_ivas, output, nchan_transport, cldfb_in_ts_re, cldfb_in_ts_im, i_sf ); - } - - if ( st_ivas->hDirAC != NULL ) - { - int16_t outchannels, idx_in, idx_lfe, ch; - idx_in = 0; - idx_lfe = 0; - - outchannels = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - for ( ch = 0; ch < outchannels; ch++ ) - { - if ( ( st_ivas->hOutSetup.num_lfe > 0 ) && ( st_ivas->hOutSetup.index_lfe[idx_lfe] == ch ) ) - { - set_zero( &( output[ch][0] ), CLDFB_NO_COL_MAX * num_cldfb_bands ); - - if ( idx_lfe < ( st_ivas->hDirAC->hOutSetup.num_lfe - 1 ) ) - { - idx_lfe++; - } - } - else - { - if ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_FOA || - !( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL || st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM ) ) - { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) - { - cldfbSynthesis( - &cldfb_in_ts_re[idx_in][ts], - &cldfb_in_ts_im[idx_in][ts], - &output[ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], - num_cldfb_bands, - st_ivas->cldfbSynDec[idx_in] ); - } - } - idx_in++; - } - } - } - else - { - /* CLDFB to time synthesis (overwrite mixer output) */ - for ( out_ch = 0; out_ch < numch_out_dirac; out_ch++ ) - { - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) - { - cldfbSynthesis( - &cldfb_in_ts_re[out_ch][ts], - &cldfb_in_ts_im[out_ch][ts], - &output[out_ch][( ts + i_sf * MAX_PARAM_SPATIAL_SUBFRAMES ) * num_cldfb_bands], - num_cldfb_bands, - st_ivas->cldfbSynDec[out_ch] - - ); - } - } - } - - split_band = SPAR_DIRAC_SPLIT_START_BAND; - if ( split_band < IVAS_MAX_NUM_BANDS ) - { - pState->i_subframe++; - pState->i_subframe = min( pState->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); - mvr2r( pState->hMdDec->mixer_mat_prev[1][0][0], pState->hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - mvr2r( pState->hMdDec->mixer_mat_prev[2][0][0], pState->hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - mvr2r( pState->hMdDec->mixer_mat_prev[3][0][0], pState->hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - mvr2r( pState->hMdDec->mixer_mat_prev[4][0][0], pState->hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); - - for ( out_ch = 0; out_ch < numch_out; out_ch++ ) - { - for ( in_ch = 0; in_ch < numch_in; in_ch++ ) - { - for ( b = 0; b < num_spar_bands; b++ ) - { - pState->hMdDec->mixer_mat_prev[4][out_ch][in_ch][b] = pState->hMdDec->mixer_mat[out_ch][in_ch][b + i_sf * IVAS_MAX_NUM_BANDS]; - } - } - } - } - } - - - wmops_sub_end(); - - return; -} diff --git a/lib_dec/ivas_spar_foa_md_dec.c b/lib_dec/ivas_spar_md_dec.c similarity index 63% rename from lib_dec/ivas_spar_foa_md_dec.c rename to lib_dec/ivas_spar_md_dec.c index 5fc28916bf8916a62f2fe0bd323c8f5224371c71..6a29c98f0ad524d1ae911d7343229fb9452c6a51 100644 --- a/lib_dec/ivas_spar_foa_md_dec.c +++ b/lib_dec/ivas_spar_md_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,10 +40,9 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_stat_dec.h" - /*#define ENABLE_DITHER */ /* IVAS_fmToDo: development switch */ /*------------------------------------------------------------------------------------------* @@ -64,14 +63,14 @@ static const int16_t ivas_spar_dec_plc_spatial_target[IVAS_SPAR_MAX_CH] = { 1, 0 * Static functions declaration *------------------------------------------------------------------------------------------*/ -static void ivas_get_spar_matrices( ivas_spar_foa_md_dec_state_t *pState, const int16_t num_bands_out, const int16_t n_ts, const int16_t bw, const int16_t dtx_vad, const int16_t nB, const int16_t sba_order +static void ivas_get_spar_matrices( ivas_spar_md_dec_state_t *hMdDec, const int16_t num_bands_out, const int16_t n_ts, const int16_t bw, const int16_t dtx_vad, const int16_t nB, const int16_t sba_order #ifdef LBR_SBA , const int16_t active_w_vlbr #endif ); -static void ivas_decode_arith_bs( ivas_spar_foa_md_dec_state_t *pState, Decoder_State *st, const uint16_t qsi, const int16_t nB, const int16_t bands_bw, int16_t *pDo_diff, const int16_t freq_diff, const int16_t planarCP +static void ivas_decode_arith_bs( ivas_spar_md_dec_state_t *hMdDec, Decoder_State *st, const uint16_t qsi, const int16_t nB, const int16_t bands_bw, int16_t *pDo_diff, const int16_t freq_diff, const int16_t planarCP #ifdef LBR_SBA , const int16_t strat, @@ -79,7 +78,7 @@ static void ivas_decode_arith_bs( ivas_spar_foa_md_dec_state_t *pState, Decoder_ #endif ); -static void ivas_decode_huffman_bs( ivas_spar_foa_md_dec_state_t *pState, Decoder_State *st, const uint16_t qsi, const int16_t nB, const int16_t bands_bw, const int16_t planarCP +static void ivas_decode_huffman_bs( ivas_spar_md_dec_state_t *hMdDec, Decoder_State *st, const uint16_t qsi, const int16_t nB, const int16_t bands_bw, const int16_t planarCP #ifdef LBR_SBA_PLANAR , const int32_t ivas_total_brate @@ -92,159 +91,163 @@ static void ivas_get_band_idx_from_differential( ivas_spar_md_t *pSpar_md, const static void ivas_mat_col_rearrange( float in_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], const int16_t order[IVAS_SPAR_MAX_CH], const int16_t i_ts, float ***mixer_mat, const int16_t bands, const int16_t num_ch ); -static void ivas_spar_foa_dec_compute_ramp_down_post_matrix( ivas_spar_foa_md_dec_state_t *pState, const int16_t num_bands, const int16_t bfi ); +static void ivas_spar_dec_compute_ramp_down_post_matrix( ivas_spar_md_dec_state_t *hMdDec, const int16_t num_bands, const int16_t bfi ); -static void ivas_spar_md_fill_invalid_bands( ivas_spar_dec_matrices_t *pSpar_coeffs, ivas_spar_dec_matrices_t *pSpar_coeffs_prev, int16_t *valid_bands, int16_t *base_band_age, const int16_t num_bands, const int16_t sba_order ); +static void ivas_spar_md_fill_invalid_bands( ivas_spar_dec_matrices_t *pSpar_coeffs, ivas_spar_dec_matrices_t *pSpar_coeffs_prev, const int16_t *valid_bands, int16_t *base_band_age, const int16_t num_bands, const int16_t sba_order ); -static ivas_error ivas_spar_foa_set_dec_config( ivas_spar_foa_md_dec_state_t *pState, const int16_t nchan_transport, float *pFC ); +static ivas_error ivas_spar_set_dec_config( ivas_spar_md_dec_state_t *hMdDec, const int16_t nchan_transport, float *pFC ); static void ivas_parse_parameter_bitstream_dtx( ivas_spar_md_t *pSpar_md, Decoder_State *st, const int16_t bw, const int16_t num_bands, int16_t *num_dmx_per_band, int16_t *num_dec_per_band ); -static ivas_error ivas_deindex_real_index( int16_t **index, const int16_t q_levels, const float min_value, const float max_value, float **quant, const int16_t num_ch, const int16_t dim2 ); +static ivas_error ivas_deindex_real_index( const int16_t *index, const int16_t q_levels, const float min_value, const float max_value, float *quant, const int16_t num_ch_dim2 ); -static void ivas_spar_foa_dec_parse_md_bs( ivas_spar_foa_md_dec_state_t *hMdDec, Decoder_State *st, int16_t *nB, int16_t *bands_bw, int16_t *dtx_vad, const int32_t ivas_total_brate, const int16_t use_planar_coeff, const int16_t sba_inactive_mode ); +static void ivas_spar_dec_parse_md_bs( ivas_spar_md_dec_state_t *hMdDec, Decoder_State *st, int16_t *nB, int16_t *bands_bw, int16_t *dtx_vad, const int32_t ivas_total_brate, const int16_t use_planar_coeff, const int16_t sba_inactive_mode ); /*------------------------------------------------------------------------- - * ivas_spar_foa_md_dec_matrix_open() + * ivas_spar_md_dec_matrix_open() * * Allocate and initialize SPAR MD decoder matrices *------------------------------------------------------------------------*/ -static ivas_error ivas_spar_foa_md_dec_matrix_open( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ - const int16_t num_channels /* i : number of internal channels */ +static ivas_error ivas_spar_md_dec_matrix_open( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + const int16_t num_channels /* i : number of internal channels */ ) { int16_t i, j; - if ( ( hMdDec->mixer_mat = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdDec->spar_md.band_coeffs = (ivas_band_coeffs_t *) malloc( IVAS_MAX_NUM_BANDS * MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( ivas_band_coeffs_t ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for band_coeffs in SPAR MD" ); + } + if ( ( hMdDec->mixer_mat = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdDec->mixer_mat[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdDec->mixer_mat[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdDec->mixer_mat[i][j] = (float *) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdDec->mixer_mat[i][j] = (float *) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( hMdDec->spar_coeffs.C_re = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs.C_re = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdDec->spar_coeffs.C_re[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs.C_re[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdDec->spar_coeffs.C_re[i][j] = (float *) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs.C_re[i][j] = (float *) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( hMdDec->spar_coeffs.P_re = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs.P_re = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdDec->spar_coeffs.P_re[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs.P_re[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdDec->spar_coeffs.P_re[i][j] = (float *) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs.P_re[i][j] = (float *) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( hMdDec->spar_coeffs_prev.C_re = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_prev.C_re = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdDec->spar_coeffs_prev.C_re[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_prev.C_re[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdDec->spar_coeffs_prev.C_re[i][j] = (float *) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_prev.C_re[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( hMdDec->spar_coeffs_prev.P_re = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_prev.P_re = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdDec->spar_coeffs_prev.P_re[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_prev.P_re[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdDec->spar_coeffs_prev.P_re[i][j] = (float *) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_prev.P_re[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( hMdDec->spar_coeffs_tar.C_re = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_tar.C_re = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdDec->spar_coeffs_tar.C_re[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_tar.C_re[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdDec->spar_coeffs_tar.C_re[i][j] = (float *) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_tar.C_re[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( hMdDec->spar_coeffs_tar.P_re = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_tar.P_re = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdDec->spar_coeffs_tar.P_re[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_tar.P_re[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdDec->spar_coeffs_tar.P_re[i][j] = (float *) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdDec->spar_coeffs_tar.P_re[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } @@ -256,35 +259,40 @@ static ivas_error ivas_spar_foa_md_dec_matrix_open( /*------------------------------------------------------------------------- - * ivas_spar_foa_md_dec_open() + * ivas_spar_md_dec_open() * * Allocate and initialize SPAR MD decoder handle *------------------------------------------------------------------------*/ -ivas_error ivas_spar_foa_md_dec_open( - ivas_spar_foa_md_dec_state_t **hMdDec_out, /* i/o: SPAR MD decoder handle */ - const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t num_channels /* i : number of internal channels */ +ivas_error ivas_spar_md_dec_open( + ivas_spar_md_dec_state_t **hMdDec_out, /* i/o: SPAR MD decoder handle */ + const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ + const int16_t num_channels, /* i : number of internal channels */ + const int16_t sba_order, /* i : SBA order */ + const int16_t sid_format /* i : SID format */ ) { - ivas_spar_foa_md_dec_state_t *hMdDec; + ivas_spar_md_dec_state_t *hMdDec; ivas_error error; error = IVAS_ERR_OK; - if ( ( hMdDec = (ivas_spar_foa_md_dec_state_t *) count_malloc( sizeof( ivas_spar_foa_md_dec_state_t ) ) ) == NULL ) + if ( ( hMdDec = (ivas_spar_md_dec_state_t *) malloc( sizeof( ivas_spar_md_dec_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD decoder" ); } - if ( ( error = ivas_spar_foa_md_dec_matrix_open( hMdDec, num_channels ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_spar_md_dec_matrix_open( hMdDec, num_channels ) ) != IVAS_ERR_OK ) { return error; } hMdDec->table_idx = 0; /* just to initialize state variables*/ - - if ( ( error = ivas_spar_foa_md_dec_init( hMdDec, hDecoderConfig, num_channels ) ) != IVAS_ERR_OK ) + if ( ( hDecoderConfig->ivas_total_brate == IVAS_SID_5k2 ) && ( sid_format == SID_SBA_2TC ) ) + { + hMdDec->table_idx = ivas_get_spar_table_idx( IVAS_48k, sba_order, SPAR_CONFIG_BW, NULL, NULL ); + } + if ( ( error = ivas_spar_md_dec_init( hMdDec, hDecoderConfig, num_channels, sba_order ) ) != IVAS_ERR_OK ) { return error; } @@ -296,29 +304,35 @@ ivas_error ivas_spar_foa_md_dec_open( /*------------------------------------------------------------------------- - * ivas_spar_foa_md_dec_matrix_close() + * ivas_spar_md_dec_matrix_close() * * Deallocate SPAR MD decoder matrices *------------------------------------------------------------------------*/ -static void ivas_spar_foa_md_dec_matrix_close( - ivas_spar_foa_md_dec_state_t *hMdDecoder, /* i/o: SPAR MD decoder handle */ - const int16_t num_channels /* i : number of internal channels */ +static void ivas_spar_md_dec_matrix_close( + ivas_spar_md_dec_state_t *hMdDecoder, /* i/o: SPAR MD decoder handle */ + const int16_t num_channels /* i : number of internal channels */ ) { int16_t i, j; + if ( hMdDecoder->spar_md.band_coeffs != NULL ) + { + free( hMdDecoder->spar_md.band_coeffs ); + hMdDecoder->spar_md.band_coeffs = NULL; + } + if ( hMdDecoder->mixer_mat != NULL ) { for ( i = 0; i < num_channels; i++ ) { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdDecoder->mixer_mat[i][j] ); + free( hMdDecoder->mixer_mat[i][j] ); } - count_free( hMdDecoder->mixer_mat[i] ); + free( hMdDecoder->mixer_mat[i] ); } - count_free( hMdDecoder->mixer_mat ); + free( hMdDecoder->mixer_mat ); } if ( hMdDecoder->spar_coeffs.C_re != NULL ) @@ -327,11 +341,11 @@ static void ivas_spar_foa_md_dec_matrix_close( { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdDecoder->spar_coeffs.C_re[i][j] ); + free( hMdDecoder->spar_coeffs.C_re[i][j] ); } - count_free( hMdDecoder->spar_coeffs.C_re[i] ); + free( hMdDecoder->spar_coeffs.C_re[i] ); } - count_free( hMdDecoder->spar_coeffs.C_re ); + free( hMdDecoder->spar_coeffs.C_re ); } if ( hMdDecoder->spar_coeffs.P_re != NULL ) @@ -340,11 +354,11 @@ static void ivas_spar_foa_md_dec_matrix_close( { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdDecoder->spar_coeffs.P_re[i][j] ); + free( hMdDecoder->spar_coeffs.P_re[i][j] ); } - count_free( hMdDecoder->spar_coeffs.P_re[i] ); + free( hMdDecoder->spar_coeffs.P_re[i] ); } - count_free( hMdDecoder->spar_coeffs.P_re ); + free( hMdDecoder->spar_coeffs.P_re ); } if ( hMdDecoder->spar_coeffs_prev.C_re != NULL ) @@ -353,11 +367,11 @@ static void ivas_spar_foa_md_dec_matrix_close( { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdDecoder->spar_coeffs_prev.C_re[i][j] ); + free( hMdDecoder->spar_coeffs_prev.C_re[i][j] ); } - count_free( hMdDecoder->spar_coeffs_prev.C_re[i] ); + free( hMdDecoder->spar_coeffs_prev.C_re[i] ); } - count_free( hMdDecoder->spar_coeffs_prev.C_re ); + free( hMdDecoder->spar_coeffs_prev.C_re ); } if ( hMdDecoder->spar_coeffs_prev.P_re != NULL ) @@ -366,11 +380,11 @@ static void ivas_spar_foa_md_dec_matrix_close( { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdDecoder->spar_coeffs_prev.P_re[i][j] ); + free( hMdDecoder->spar_coeffs_prev.P_re[i][j] ); } - count_free( hMdDecoder->spar_coeffs_prev.P_re[i] ); + free( hMdDecoder->spar_coeffs_prev.P_re[i] ); } - count_free( hMdDecoder->spar_coeffs_prev.P_re ); + free( hMdDecoder->spar_coeffs_prev.P_re ); } if ( hMdDecoder->spar_coeffs_tar.C_re != NULL ) @@ -379,11 +393,11 @@ static void ivas_spar_foa_md_dec_matrix_close( { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdDecoder->spar_coeffs_tar.C_re[i][j] ); + free( hMdDecoder->spar_coeffs_tar.C_re[i][j] ); } - count_free( hMdDecoder->spar_coeffs_tar.C_re[i] ); + free( hMdDecoder->spar_coeffs_tar.C_re[i] ); } - count_free( hMdDecoder->spar_coeffs_tar.C_re ); + free( hMdDecoder->spar_coeffs_tar.C_re ); } if ( hMdDecoder->spar_coeffs_tar.P_re != NULL ) @@ -392,11 +406,11 @@ static void ivas_spar_foa_md_dec_matrix_close( { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdDecoder->spar_coeffs_tar.P_re[i][j] ); + free( hMdDecoder->spar_coeffs_tar.P_re[i][j] ); } - count_free( hMdDecoder->spar_coeffs_tar.P_re[i] ); + free( hMdDecoder->spar_coeffs_tar.P_re[i] ); } - count_free( hMdDecoder->spar_coeffs_tar.P_re ); + free( hMdDecoder->spar_coeffs_tar.P_re ); } return; @@ -404,54 +418,53 @@ static void ivas_spar_foa_md_dec_matrix_close( /*------------------------------------------------------------------------- - * ivas_spar_foa_md_dec_close() + * ivas_spar_md_dec_close() * * Deallocate SPAR MD decoder handle *------------------------------------------------------------------------*/ -void ivas_spar_foa_md_dec_close( - ivas_spar_foa_md_dec_state_t **hMdDec /* i/o: SPAR MD decoder handle */ +void ivas_spar_md_dec_close( + ivas_spar_md_dec_state_t **hMdDec /* i/o: SPAR MD decoder handle */ ) { - ivas_spar_foa_md_dec_state_t *hMdDecoder; + ivas_spar_md_dec_state_t *hMdDecoder; int16_t num_channels; hMdDecoder = *hMdDec; num_channels = hMdDecoder->spar_md_cfg.num_umx_chs; - ivas_spar_foa_md_dec_matrix_close( hMdDecoder, num_channels ); + ivas_spar_md_dec_matrix_close( hMdDecoder, num_channels ); - if ( *hMdDec != NULL ) - { - count_free( *hMdDec ); - *hMdDec = NULL; - } + free( *hMdDec ); + *hMdDec = NULL; return; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_md_dec_init() + * Function ivas_spar_md_dec_init() * - * Init call for md dec process + * SPAR MD decoder initialization *-----------------------------------------------------------------------------------------*/ -ivas_error ivas_spar_foa_md_dec_init( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ +ivas_error ivas_spar_md_dec_init( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : configuration structure */ - const int16_t num_channels /* i : number of internal channels */ + const int16_t num_channels, /* i : number of internal channels */ + const int16_t sba_order /* i : SBA order */ ) { int16_t i, j, k; int16_t nchan_transport; float pFC[IVAS_MAX_NUM_BANDS], PR_minmax[2]; - ivas_spar_foa_md_dec_state_t *pState = hMdDec; - pState->spar_md_cfg.gen_bs = 1; - ivas_spar_set_bitrate_config( &pState->spar_md_cfg, pState->table_idx, min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ) ); + hMdDec->spar_hoa_md_flag = ivas_sba_get_spar_hoa_md_flag( sba_order, hDecoderConfig->ivas_total_brate ); + hMdDec->spar_md.num_bands = ( hMdDec->spar_hoa_md_flag ) ? IVAS_MAX_NUM_BANDS : min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); - nchan_transport = pState->spar_md_cfg.nchan_transport; + ivas_spar_set_bitrate_config( &hMdDec->spar_md_cfg, hMdDec->table_idx, hMdDec->spar_md.num_bands ); + + nchan_transport = hMdDec->spar_md_cfg.nchan_transport; /* get FB coefficients */ for ( i = 0; i < IVAS_MAX_NUM_BANDS; i++ ) @@ -459,28 +472,28 @@ ivas_error ivas_spar_foa_md_dec_init( pFC[i] = ivas_fb_fcs_12band_1ms[i] * hDecoderConfig->output_Fs * 0.5f; } - ivas_spar_foa_set_dec_config( pState, nchan_transport, pFC ); + ivas_spar_set_dec_config( hMdDec, nchan_transport, pFC ); - if ( nchan_transport != 2 && ( ( pState->spar_md_cfg.remix_unmix_order == 2 ) || ( pState->spar_md_cfg.remix_unmix_order == 1 ) ) ) + if ( nchan_transport != 2 && ( ( hMdDec->spar_md_cfg.remix_unmix_order == 2 ) || ( hMdDec->spar_md_cfg.remix_unmix_order == 1 ) ) ) { return IVAS_ERR_INTERNAL; } /* DTX quant init */ - PR_minmax[0] = pState->spar_md_cfg.quant_strat[0].PR.min; - PR_minmax[1] = pState->spar_md_cfg.quant_strat[0].PR.max; - ivas_spar_quant_dtx_init( &pState->spar_md, PR_minmax ); + PR_minmax[0] = hMdDec->spar_md_cfg.quant_strat[0].PR.min; + PR_minmax[1] = hMdDec->spar_md_cfg.quant_strat[0].PR.max; + ivas_spar_quant_dtx_init( &hMdDec->spar_md, PR_minmax ); - ivas_arith_coeffs_dec_init( &pState->arith_coeffs, &pState->spar_md_cfg, pState->table_idx ); - ivas_huff_coeffs_dec_init( &pState->huff_coeffs, &pState->spar_md_cfg, pState->table_idx ); + ivas_spar_arith_coeffs_com_init( &hMdDec->arith_coeffs, &hMdDec->spar_md_cfg, hMdDec->table_idx, DEC ); + ivas_spar_huff_coeffs_com_init( &hMdDec->huff_coeffs, &hMdDec->spar_md_cfg, hMdDec->table_idx, DEC ); - pState->spar_md_cfg.prev_quant_idx = -1; + hMdDec->spar_md_cfg.prev_quant_idx = -1; /* initialize PLC state */ - set_s( pState->valid_bands, 0, IVAS_MAX_NUM_BANDS ); - set_s( pState->base_band_age, 0, IVAS_MAX_NUM_BANDS ); - pState->spar_plc_num_lost_frames = 0; - pState->spar_plc_enable_fadeout_flag = 1; + set_s( hMdDec->valid_bands, 0, IVAS_MAX_NUM_BANDS ); + set_s( hMdDec->base_band_age, 0, IVAS_MAX_NUM_BANDS ); + hMdDec->spar_plc_num_lost_frames = 0; + hMdDec->spar_plc_enable_fadeout_flag = 1; for ( i = 0; i < num_channels; i++ ) { @@ -488,7 +501,7 @@ ivas_error ivas_spar_foa_md_dec_init( { for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ ) { - pState->spar_coeffs_prev.C_re[i][j][k] = 0; + hMdDec->spar_coeffs_prev.C_re[i][j][k] = 0; } } } @@ -499,7 +512,7 @@ ivas_error ivas_spar_foa_md_dec_init( { for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ ) { - pState->spar_coeffs_prev.P_re[i][j][k] = 0; + hMdDec->spar_coeffs_prev.P_re[i][j][k] = 0; } } } @@ -510,7 +523,7 @@ ivas_error ivas_spar_foa_md_dec_init( { for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ ) { - pState->spar_coeffs_tar.C_re[i][j][k] = 0; + hMdDec->spar_coeffs_tar.C_re[i][j][k] = 0; } } } @@ -521,37 +534,36 @@ ivas_error ivas_spar_foa_md_dec_init( { for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ ) { - pState->spar_coeffs_tar.P_re[i][j][k] = 0; + hMdDec->spar_coeffs_tar.P_re[i][j][k] = 0; } } } - pState->dtx_md_smoothing_cntr = 1; + hMdDec->dtx_md_smoothing_cntr = 1; - ivas_clear_band_coeffs( pState->spar_md.band_coeffs, IVAS_MAX_NUM_BANDS ); - ivas_clear_band_coeff_idx( pState->spar_md.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); - ivas_clear_band_coeff_idx( pState->spar_md_prev.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); - ivas_clear_band_coeff_idx( pState->spar_md_prev.band_coeffs_idx_mapped, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeffs( hMdDec->spar_md.band_coeffs, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeff_idx( hMdDec->spar_md.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeff_idx( hMdDec->spar_md_prev.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeff_idx( hMdDec->spar_md_prev.band_coeffs_idx_mapped, IVAS_MAX_NUM_BANDS ); - pState->spar_md.dtx_vad = 0; - pState->spar_md.num_bands = min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); - pState->td_decorr_flag = 1; + hMdDec->spar_md.dtx_vad = 0; + hMdDec->td_decorr_flag = 1; - set_f( pState->spar_md.en_ratio_slow, 0.0f, IVAS_MAX_NUM_BANDS ); - set_f( pState->spar_md.ref_pow_slow, 0.0f, IVAS_MAX_NUM_BANDS ); + set_f( hMdDec->spar_md.en_ratio_slow, 0.0f, IVAS_MAX_NUM_BANDS ); + set_f( hMdDec->spar_md.ref_pow_slow, 0.0f, IVAS_MAX_NUM_BANDS ); return IVAS_ERR_OK; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_set_dec_config() + * Function ivas_spar_set_dec_config() * - * Set configuration for SPAR FOA md dec + * Set configuration for SPAR MD decoder *-----------------------------------------------------------------------------------------*/ -static ivas_error ivas_spar_foa_set_dec_config( - ivas_spar_foa_md_dec_state_t *pState, +static ivas_error ivas_spar_set_dec_config( + ivas_spar_md_dec_state_t *hMdDec, const int16_t nchan_transport, float *pFC ) { @@ -559,31 +571,31 @@ static ivas_error ivas_spar_foa_set_dec_config( for ( i = 0; i < nchan_transport; i++ ) { - pState->spar_md_cfg.max_freq_per_chan[i] = ivas_spar_br_table_consts[pState->table_idx].fpcs; + hMdDec->spar_md_cfg.max_freq_per_chan[i] = ivas_spar_br_table_consts[hMdDec->table_idx].fpcs; } - nchan = ivas_sba_get_nchan_metadata( ivas_spar_br_table_consts[pState->table_idx].sba_order ); + nchan = ivas_sba_get_nchan_metadata( ivas_spar_br_table_consts[hMdDec->table_idx].sba_order ); switch ( nchan ) { case 4: /* FOA_CHANNELS */ - pState->num_decorr = IVAS_TD_DECORR_OUT_3CH; + hMdDec->num_decorr = IVAS_TD_DECORR_OUT_3CH; break; case 9: /* IVAS_HOA_2_CH */ // VE: is this relevant? - pState->num_decorr = IVAS_TD_DECORR_OUT_5CH; + hMdDec->num_decorr = IVAS_TD_DECORR_OUT_5CH; break; case 16: /* IVAS_HOA_3_CH */ // VE: is this relevant? - pState->num_decorr = IVAS_TD_DECORR_OUT_12CH; + hMdDec->num_decorr = IVAS_TD_DECORR_OUT_12CH; break; case 6: /* IVAS_HOA_2_CH */ - pState->num_decorr = IVAS_TD_DECORR_OUT_2CH; + hMdDec->num_decorr = IVAS_TD_DECORR_OUT_2CH; break; case 8: /* IVAS_HOA_3_CH */ - pState->num_decorr = IVAS_TD_DECORR_OUT_4CH; + hMdDec->num_decorr = IVAS_TD_DECORR_OUT_4CH; break; } - pState->spar_md_cfg.num_umx_chs = nchan; + hMdDec->spar_md_cfg.num_umx_chs = nchan; dmx_ch = 0; for ( i = 0; i < IVAS_MAX_NUM_BANDS; i++ ) @@ -591,99 +603,113 @@ static ivas_error ivas_spar_foa_set_dec_config( dmx_ch = 0; for ( j = 0; j < nchan_transport; j++ ) { - if ( pFC[i] < pState->spar_md_cfg.max_freq_per_chan[j] ) + if ( pFC[i] < hMdDec->spar_md_cfg.max_freq_per_chan[j] ) { dmx_ch += 1; } } - pState->spar_md_cfg.num_dmx_chans_per_band[i] = pState->spar_md_cfg.nchan_transport; - pState->spar_md_cfg.num_decorr_per_band[i] = nchan - pState->spar_md_cfg.nchan_transport; + hMdDec->spar_md_cfg.num_dmx_chans_per_band[i] = hMdDec->spar_md_cfg.nchan_transport; + hMdDec->spar_md_cfg.num_decorr_per_band[i] = nchan - hMdDec->spar_md_cfg.nchan_transport; } - pState->spar_md_cfg.nchan_transport = dmx_ch; + hMdDec->spar_md_cfg.nchan_transport = dmx_ch; return IVAS_ERR_OK; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_md_dec_process() + * Function ivas_spar_md_dec_process() * - * SPAR FOA Meta Data decoder process + * SPAR Meta Data decoder process *-----------------------------------------------------------------------------------------*/ -void ivas_spar_foa_md_dec_process( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ - const int16_t num_bands_out, /* i : number of output bands */ - const int16_t sba_order /* i : Ambisonic (SBA) order */ +void ivas_spar_md_dec_process( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling */ + const int16_t num_bands_out, /* i : number of output bands */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { - int16_t j, b, bw, dtx_vad, nB, i_ts; - ivas_spar_foa_md_dec_state_t *hMdDec = st_ivas->hSpar->hSparFoa->hMdDec; + int16_t j, k, b, bw, dtx_vad, nB, i_ts; + ivas_spar_md_dec_state_t *hMdDec; + + hMdDec = st_ivas->hSpar->hMdDec; #ifdef LBR_SBA int16_t active_w_vlbr; active_w_vlbr = ( st_ivas->hDecoderConfig->ivas_total_brate < IVAS_24k4 ) ? 1 : 0; #endif - ivas_spar_foa_dec_parse_md_bs( hMdDec, st0, &nB, &bw, &dtx_vad, st_ivas->hDecoderConfig->ivas_total_brate, - ivas_spar_br_table_consts[hMdDec->table_idx].usePlanarCoeff, - st_ivas->hQMetaData->sba_inactive_mode ); + ivas_spar_dec_parse_md_bs( hMdDec, st0, &nB, &bw, &dtx_vad, st_ivas->hDecoderConfig->ivas_total_brate, + ivas_spar_br_table_consts[hMdDec->table_idx].usePlanarCoeff, st_ivas->hQMetaData->sba_inactive_mode ); - /* SPAR to DirAC and DirAC to SPAR conversion */ - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) +#if 0 { - ivas_spar_to_dirac( st_ivas, hMdDec, dtx_vad, num_bands_out -#ifdef LBR_SBA - , - bw -#endif - ); - - /* set correct number of bands*/ - nB = IVAS_MAX_NUM_BANDS; - if ( bw == IVAS_RED_BAND_FACT ) + char f_name[100]; + int16_t num_bands = nB; + int16_t num_subframes = 1, num_block_groups = 1, num_elements = 1, byte_size = sizeof( float ); + int16_t num_ch = ivas_sba_get_nchan_metadata( sba_order ); + for ( b = 0; b < num_bands; b++ ) { - nB = nB >> 1; + sprintf( f_name, "spar_band_pred_coeffs_dec.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &num_bands, sizeof( num_bands ), 1, 1, f_name ) : false; + num_elements = num_ch - 1; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( j = 0; j < num_ch - 1; j++ ) + { + dbgwrite( &hMdDec->spar_md.band_coeffs[b].pred_re[j], sizeof( float ), 1, 1, f_name ); + } + sprintf( f_name, "spar_band_C_coeffs_dec.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &num_bands, sizeof( num_bands ), 1, 1, f_name ) : false; + num_elements = ( hMdDec->spar_md_cfg.num_decorr_per_band[bw * b] - hMdDec->spar_md_cfg.num_dmx_chans_per_band[bw * b] ) * ( hMdDec->spar_md_cfg.num_dmx_chans_per_band[bw * b] - 1 ); + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( j = 0; j < ( hMdDec->spar_md_cfg.num_decorr_per_band[bw * b] - hMdDec->spar_md_cfg.num_dmx_chans_per_band[bw * b] ); j++ ) + { + for ( k = 0; k < hMdDec->spar_md_cfg.num_dmx_chans_per_band[bw * b] - 1; k++ ) + { + dbgwrite( &hMdDec->spar_md.band_coeffs[b].C_re[j][k], sizeof( float ), 1, 1, f_name ); + } + } + sprintf( f_name, "spar_band_P_coeffs_dec.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &num_bands, sizeof( num_bands ), 1, 1, f_name ) : false; + num_elements = num_ch - 1; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( j = 0; j < num_ch - 1; j++ ) + { + dbgwrite( &hMdDec->spar_md.band_coeffs[b].P_re[j], sizeof( float ), 1, 1, f_name ); + } } } -#ifdef DEBUG_LBR_SBA - /* Dumping SPAR Coefficients */ - char f_name[100]; - int16_t nbands = 6; - int16_t num_subframes = 1; - int16_t num_elements = 6; - int16_t num_block_group = 1; - int16_t byte_size = sizeof( float ); +#endif - sprintf( f_name, "SBA_MD_values_dec.bin" ); - ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + /* SPAR to DirAC conversion */ + ivas_spar_to_dirac( st_ivas, hMdDec, dtx_vad, num_bands_out +#ifdef LBR_SBA + , + bw +#endif + ); - for ( b = 0; b < nbands; b++ ) + /* set correct number of bands*/ + nB = IVAS_MAX_NUM_BANDS; + if ( bw == IVAS_RED_BAND_FACT ) { - for ( int16_t sf = 0; sf < num_subframes; sf++ ) - { - for ( int16_t bl = 0; bl < num_block_group; bl++ ) - { - dbgwrite( &hMdDec->spar_md.band_coeffs[b].pred_re[0], byte_size, 1, 1, f_name ); - dbgwrite( &hMdDec->spar_md.band_coeffs[b].pred_re[1], byte_size, 1, 1, f_name ); - dbgwrite( &hMdDec->spar_md.band_coeffs[b].pred_re[2], byte_size, 1, 1, f_name ); - dbgwrite( &hMdDec->spar_md.band_coeffs[b].P_re[0], byte_size, 1, 1, f_name ); - dbgwrite( &hMdDec->spar_md.band_coeffs[b].P_re[1], byte_size, 1, 1, f_name ); - dbgwrite( &hMdDec->spar_md.band_coeffs[b].P_re[2], byte_size, 1, 1, f_name ); - // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); - } - } + nB = nB >> 1; } -#endif + /* expand DirAC MD to all time slots */ for ( i_ts = 1; i_ts < MAX_PARAM_SPATIAL_SUBFRAMES; i_ts++ ) { - for ( b = 0; b < min( IVAS_MAX_NUM_BANDS, SPAR_DIRAC_SPLIT_START_BAND ); b++ ) + for ( b = 0; b < hMdDec->spar_md.num_bands; b++ ) { for ( j = 0; j < IVAS_SPAR_MAX_CH - 1; j++ ) { @@ -692,7 +718,7 @@ void ivas_spar_foa_md_dec_process( for ( j = 0; j < IVAS_SPAR_MAX_CH - IVAS_SPAR_MAX_DMX_CHS; j++ ) { - for ( int16_t k = 0; k < IVAS_SPAR_MAX_DMX_CHS - 1; k++ ) + for ( k = 0; k < IVAS_SPAR_MAX_DMX_CHS - 1; k++ ) { hMdDec->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].C_re[j][k] = hMdDec->spar_md.band_coeffs[b].C_re[j][k]; } @@ -704,43 +730,13 @@ void ivas_spar_foa_md_dec_process( } } } -#ifdef DEBUG_LBR_SBA - /*for ( int b = 0; b < nB; b++ ) - { - int16_t ndec = hMdDec->spar_md_cfg.num_decorr_per_band[( bw ) * b]; - int16_t ndm = hMdDec->spar_md_cfg.num_dmx_chans_per_band[( bw ) * b]; - fprintf( stdout, "\n\n POST DIRAC Metadata PR (15x1), C(15x15), P(15x15): band %d\n", b ); - for ( int i = 0; i < ndm + ndec - 1; i++ ) - { - fprintf( stdout, "i: %d -- %.2f\t|\t", i, hMdDec->spar_md.band_coeffs[b].pred_re[i] ); - if ( i < ndec ) - { - if ( keep_planar[i] == 1 ) - { - fprintf( stdout, ">>" ); - } - else - { - fprintf( stdout, " " ); - } - for ( j = 0; j < ndm - 1; j++ ) - { - fprintf( stdout, "%.2f\t", hMdDec->spar_md.band_coeffs[b].C_re[i][j] ); - } - fprintf( stdout, "|\t" ); - fprintf( stdout, "%.2f", hMdDec->spar_md.band_coeffs[b].P_re[i] ); - } - fprintf( stdout, "\n" ); - } - fprintf( stdout, "\n" ); - }*/ -#endif + ivas_get_spar_matrices( hMdDec, num_bands_out, MAX_PARAM_SPATIAL_SUBFRAMES, bw, dtx_vad, nB, sba_order #ifdef LBR_SBA , active_w_vlbr #endif - ); +); #ifdef DEBUG_SPAR_DIRAC_WRITE_OUT_PRED_PARS { @@ -753,7 +749,6 @@ void ivas_spar_foa_md_dec_process( fprintf( fid, "%.6f\n", hMdDec->mixer_mat[1][0][band] ); } #endif - #ifdef LBR_SBA if ( bw == IVAS_RED_BAND_FACT ) { @@ -774,38 +769,36 @@ void ivas_spar_foa_md_dec_process( /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_smooth_md_dtx() + * Function ivas_spar_smooth_md_dtx() * * Smooth MD during no data frame during DTX *-----------------------------------------------------------------------------------------*/ + #ifdef SPAR_HOA_DBG /* NOTE: No changes here as DTX only operates below 160kbps */ #endif -void ivas_spar_foa_smooth_md_dtx( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ - const int16_t num_bands_out /* i : number of output bands */ +void ivas_spar_smooth_md_dtx( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + const int16_t num_bands_out /* i : number of output bands */ ) { - int16_t j, k, b; - int16_t dmx_ch; - ivas_spar_foa_md_dec_state_t *pState = hMdDec; + int16_t j, k, b, dmx_ch; float ramp, tar, prev, new_val; - ramp = (float) pState->dtx_md_smoothing_cntr / IVAS_DEFAULT_DTX_CNG_RAMP; + ramp = (float) hMdDec->dtx_md_smoothing_cntr / IVAS_DEFAULT_DTX_CNG_RAMP; for ( b = 0; b < num_bands_out; b++ ) { - dmx_ch = pState->spar_md_cfg.num_dmx_chans_per_band[b]; + dmx_ch = hMdDec->spar_md_cfg.num_dmx_chans_per_band[b]; for ( j = 1; j < FOA_CHANNELS; j++ ) { for ( k = dmx_ch; k < FOA_CHANNELS; k++ ) - { - prev = pState->spar_coeffs_prev.P_re[j][k][b]; - tar = pState->spar_coeffs_tar.P_re[j][k][b]; + prev = hMdDec->spar_coeffs_prev.P_re[j][k][b]; + tar = hMdDec->spar_coeffs_tar.P_re[j][k][b]; new_val = prev + ( ramp * ( tar - prev ) ); - pState->spar_coeffs.P_re[j][k][b] = new_val; + hMdDec->spar_coeffs.P_re[j][k][b] = new_val; } } @@ -813,10 +806,10 @@ void ivas_spar_foa_smooth_md_dtx( { for ( k = 0; k < dmx_ch; k++ ) { - prev = pState->spar_coeffs_prev.C_re[j][k][b]; - tar = pState->spar_coeffs_tar.C_re[j][k][b]; + prev = hMdDec->spar_coeffs_prev.C_re[j][k][b]; + tar = hMdDec->spar_coeffs_tar.C_re[j][k][b]; new_val = prev + ( ramp * ( tar - prev ) ); - pState->spar_coeffs.C_re[j][k][b] = new_val; + hMdDec->spar_coeffs.C_re[j][k][b] = new_val; } } } @@ -826,14 +819,14 @@ void ivas_spar_foa_smooth_md_dtx( { for ( b = 0; b < num_bands_out; b++ ) { - dmx_ch = pState->spar_md_cfg.num_dmx_chans_per_band[b]; + dmx_ch = hMdDec->spar_md_cfg.num_dmx_chans_per_band[b]; for ( j = 1; j < FOA_CHANNELS; j++ ) { for ( k = dmx_ch; k < FOA_CHANNELS; k++ ) { - pState->spar_coeffs.P_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS] = pState->spar_coeffs.P_re[j][k][b]; + hMdDec->spar_coeffs.P_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.P_re[j][k][b]; } } @@ -841,27 +834,27 @@ void ivas_spar_foa_smooth_md_dtx( { for ( k = 0; k < dmx_ch; k++ ) { - pState->spar_coeffs.C_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS] = pState->spar_coeffs.C_re[j][k][b]; + hMdDec->spar_coeffs.C_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.C_re[j][k][b]; } } } } - pState->dtx_md_smoothing_cntr = min( pState->dtx_md_smoothing_cntr + 1, IVAS_DEFAULT_DTX_CNG_RAMP ); + hMdDec->dtx_md_smoothing_cntr = min( hMdDec->dtx_md_smoothing_cntr + 1, IVAS_DEFAULT_DTX_CNG_RAMP ); return; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_setup_md_smoothing() + * Function ivas_spar_setup_md_smoothing() * * Set up smoothing of SPAR MD when SID update frame is received *-----------------------------------------------------------------------------------------*/ -void ivas_spar_foa_setup_md_smoothing( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ - const int16_t num_bands_out /* i : number of output bands */ +void ivas_spar_setup_md_smoothing( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + const int16_t num_bands_out /* i : number of output bands */ ) { /* copy the coeffs */ @@ -913,20 +906,20 @@ void ivas_spar_foa_setup_md_smoothing( } } - ivas_spar_foa_smooth_md_dtx( hMdDec, num_bands_out ); + ivas_spar_smooth_md_dtx( hMdDec, num_bands_out ); return; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_update_md_hist() + * Function ivas_spar_update_md_hist() * * Update previous and target MD *-----------------------------------------------------------------------------------------*/ -void ivas_spar_foa_update_md_hist( - ivas_spar_foa_md_dec_state_t *hMdDec ) +void ivas_spar_update_md_hist( + ivas_spar_md_dec_state_t *hMdDec ) { int16_t num_channels, i, j, k; @@ -987,7 +980,7 @@ void ivas_spar_foa_update_md_hist( *-----------------------------------------------------------------------------------------*/ static void ivas_get_spar_matrices( - ivas_spar_foa_md_dec_state_t *pState, + ivas_spar_md_dec_state_t *hMdDec, const int16_t num_bands_out, const int16_t n_ts, const int16_t bw, @@ -1000,16 +993,15 @@ static void ivas_get_spar_matrices( #endif ) { - int16_t numch_out, num_bands, dmx_ch; + int16_t numch_out, num_bands, dmx_ch, split_band; int16_t i, j, k, m, b, i_ts, active_w; const int16_t *order; float active_w_dm_fac, re; - int16_t split_band; numch_out = ivas_sba_get_nchan_metadata( sba_order ); num_bands = num_bands_out; - order = remix_order_set[pState->spar_md_cfg.remix_unmix_order]; + order = remix_order_set[hMdDec->spar_md_cfg.remix_unmix_order]; split_band = SPAR_DIRAC_SPLIT_START_BAND; if ( split_band >= IVAS_MAX_NUM_BANDS ) @@ -1021,7 +1013,7 @@ static void ivas_get_spar_matrices( { for ( b = 0; b < num_bands; b++ ) { - pState->mixer_mat_prev[0][i][j][b] = pState->mixer_mat[i][j][b]; + hMdDec->mixer_mat_prev[0][i][j][b] = hMdDec->mixer_mat[i][j][b]; } } } @@ -1030,15 +1022,15 @@ static void ivas_get_spar_matrices( #ifdef SPAR_HOA_DBG /*for (b = 0; b < BANDS_12; b++) { - for (i = 0; i < IVAS_SPAR_MAX_CH - 1; i++) - { - pState->spar_md.band_coeffs[b].pred_re[i] = (float)(i + 1)/10; - for (j = 0; j < IVAS_SPAR_MAX_CH - 1; j++) + for (i = 0; i < IVAS_SPAR_MAX_CH - 1; i++) { - pState->spar_md.band_coeffs[b].C_re[i][j] = (float)(i + j * 20 + 1)/10; - pState->spar_md.band_coeffs[b].P_re[i][j] = (float)(i + j * 20 + 1)/10; + hMdDec->spar_md.band_coeffs[b].pred_re[i] = (float)(i + 1)/10; + for (j = 0; j < IVAS_SPAR_MAX_CH - 1; j++) + { + hMdDec->spar_md.band_coeffs[b].C_re[i][j] = (float)(i + j * 20 + 1)/10; + hMdDec->spar_md.band_coeffs[b].P_re[i][j] = (float)(i + j * 20 + 1)/10; + } } - } }*/ #endif #ifdef LBR_SBA @@ -1047,7 +1039,7 @@ static void ivas_get_spar_matrices( num_bands = num_bands >> 1; } #endif - active_w = pState->spar_md_cfg.active_w; + active_w = hMdDec->spar_md_cfg.active_w; #ifdef LBR_SBA active_w_dm_fac = ( dtx_vad == 0 ) ? IVAS_ACTIVEW_DM_F_SCALE_DTX : ( ( active_w_vlbr ) ? IVAS_ACTIVEW_DM_F_SCALE_VLBR : IVAS_ACTIVEW_DM_F_SCALE ); #else @@ -1059,9 +1051,8 @@ static void ivas_get_spar_matrices( { for ( j = 0; j < numch_out; j++ ) { - - set_zero( &pState->spar_coeffs.C_re[i][j][i_ts * IVAS_MAX_NUM_BANDS], IVAS_MAX_NUM_BANDS ); - set_zero( &pState->spar_coeffs.P_re[i][j][i_ts * IVAS_MAX_NUM_BANDS], IVAS_MAX_NUM_BANDS ); + set_zero( &hMdDec->spar_coeffs.C_re[i][j][i_ts * IVAS_MAX_NUM_BANDS], IVAS_MAX_NUM_BANDS ); + set_zero( &hMdDec->spar_coeffs.P_re[i][j][i_ts * IVAS_MAX_NUM_BANDS], IVAS_MAX_NUM_BANDS ); } } #ifndef LBR_SBA @@ -1078,7 +1069,7 @@ static void ivas_get_spar_matrices( float tmp_C2_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; float tmp_dm_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - dmx_ch = pState->spar_md_cfg.num_dmx_chans_per_band[bw * b]; + dmx_ch = hMdDec->spar_md_cfg.num_dmx_chans_per_band[bw * b]; for ( j = 0; j < numch_out; j++ ) { @@ -1093,14 +1084,14 @@ static void ivas_get_spar_matrices( for ( j = 1; j < numch_out; j++ ) { - tmp_C1_re[j][0] = pState->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].pred_re[j - 1]; + tmp_C1_re[j][0] = hMdDec->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].pred_re[j - 1]; } if ( active_w == 1 ) { for ( j = 1; j < numch_out; j++ ) { - tmp_C2_re[0][j] = active_w_dm_fac * -pState->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].pred_re[j - 1]; + tmp_C2_re[0][j] = active_w_dm_fac * -hMdDec->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].pred_re[j - 1]; } IVAS_RMULT_FLOAT( tmp_C2_re[0][1], tmp_C1_re[1][0], re ); @@ -1124,9 +1115,9 @@ static void ivas_get_spar_matrices( tmp_dm_re[3][0] = tmp_C1_re[3][0]; - if ( pState->spar_md_cfg.remix_unmix_order != 3 ) + if ( hMdDec->spar_md_cfg.remix_unmix_order != 3 ) { - ivas_mat_col_rearrange( tmp_dm_re, order, i_ts, pState->mixer_mat, b, numch_out ); + ivas_mat_col_rearrange( tmp_dm_re, order, i_ts, hMdDec->mixer_mat, b, numch_out ); } else { @@ -1134,24 +1125,24 @@ static void ivas_get_spar_matrices( for ( i = 0; i < FOA_CHANNELS; i++ ) { /* row 0 */ - pState->mixer_mat[i][0][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][0]; + hMdDec->mixer_mat[i][0][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][0]; /* row 1 */ - pState->mixer_mat[i][1][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][1]; + hMdDec->mixer_mat[i][1][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][1]; /* row 3 */ - pState->mixer_mat[i][2][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][1]; + hMdDec->mixer_mat[i][2][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][1]; /* row 4 */ - pState->mixer_mat[i][3][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][2]; + hMdDec->mixer_mat[i][3][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_dm_re[i][2]; } } } else { - if ( pState->spar_md_cfg.remix_unmix_order != 3 ) + if ( hMdDec->spar_md_cfg.remix_unmix_order != 3 ) { - ivas_mat_col_rearrange( tmp_C1_re, order, i_ts, pState->mixer_mat, b, numch_out ); + ivas_mat_col_rearrange( tmp_C1_re, order, i_ts, hMdDec->mixer_mat, b, numch_out ); } else { @@ -1159,16 +1150,16 @@ static void ivas_get_spar_matrices( for ( i = 0; i < FOA_CHANNELS; i++ ) { /* row 0 */ - pState->mixer_mat[i][0][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][0]; + hMdDec->mixer_mat[i][0][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][0]; /* row 1 */ - pState->mixer_mat[i][1][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][1]; + hMdDec->mixer_mat[i][1][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][1]; /* row 3 */ - pState->mixer_mat[i][2][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][1]; + hMdDec->mixer_mat[i][2][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][1]; /* row 4 */ - pState->mixer_mat[i][3][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][2]; + hMdDec->mixer_mat[i][3][b + i_ts * IVAS_MAX_NUM_BANDS] = tmp_C1_re[i][2]; } } } @@ -1198,28 +1189,28 @@ static void ivas_get_spar_matrices( { for ( k = 1; k < dmx_ch; k++ ) { - tmpC_re[j][k] = pState->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].C_re[j - dmx_ch][k - 1]; + tmpC_re[j][k] = hMdDec->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].C_re[j - dmx_ch][k - 1]; } } #ifdef SPAR_HOA_DBG /*fprintf(stdout, "C matrix1: %d x %d\n\n", numch_out, dmx_ch); for (j = 0; j < numch_out; j++) { - for (k = 0; k < dmx_ch; k++) - { - fprintf(stdout, "%f, ", tmpC_re[j][k]); - } - fprintf(stdout, "\n"); + for (k = 0; k < dmx_ch; k++) + { + fprintf(stdout, "%f, ", tmpC_re[j][k]); + } + fprintf(stdout, "\n"); } fprintf(stdout, "Mixer Mat: %d x %d\n\n", numch_out, numch_out); for ( j = 0; j < numch_out; j++) { - for (k = 0; k < numch_out; k++) - { - fprintf(stdout, "%f, ", pState->mixer_mat[j][k][0][b]); - } - fprintf(stdout, "\n"); + for (k = 0; k < numch_out; k++) + { + fprintf(stdout, "%f, ", hMdDec->mixer_mat[j][k][0][b]); + } + fprintf(stdout, "\n"); }*/ #endif @@ -1229,7 +1220,7 @@ static void ivas_get_spar_matrices( { if ( ( j - dmx_ch ) == ( k - dmx_ch ) ) { - tmpP_re[j][k] = pState->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].P_re[k - dmx_ch]; + tmpP_re[j][k] = hMdDec->spar_md.band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].P_re[k - dmx_ch]; } else { @@ -1240,37 +1231,36 @@ static void ivas_get_spar_matrices( #ifdef SPAR_HOA_DBG /*if (b == 0) { - fprintf(stdout, "tmp_P matrix: %d x %d\n\n", numch_out, dmx_ch); - for (j = 0; j < numch_out; j++) - { - for (k = 0; k < numch_out; k++) + fprintf(stdout, "tmp_P matrix: %d x %d\n\n", numch_out, dmx_ch); + for (j = 0; j < numch_out; j++) { - fprintf(stdout, "%f, ", tmpP_re[j][k]); - } - fprintf(stdout, "\n"); + for (k = 0; k < numch_out; k++) + { + fprintf(stdout, "%f, ", tmpP_re[j][k]); + } + fprintf(stdout, "\n"); - } - fprintf(stdout, "Mixer Mat: %d x %d\n\n", numch_out, numch_out); - for (j = 0; j < numch_out; j++) - { - for (k = 0; k < numch_out; k++) - { - fprintf(stdout, "%f, ", pState->mixer_mat[j][k][0][b]); } - fprintf(stdout, "\n"); + fprintf(stdout, "Mixer Mat: %d x %d\n\n", numch_out, numch_out); + for (j = 0; j < numch_out; j++) + { + for (k = 0; k < numch_out; k++) + { + fprintf(stdout, "%f, ", hMdDec->mixer_mat[j][k][0][b]); + } + fprintf(stdout, "\n"); - } + } }*/ #endif for ( j = 1; j < numch_out; j++ ) { for ( k = dmx_ch; k < numch_out; k++ ) - { for ( m = 0; m < numch_out; m++ ) { - IVAS_RMULT_FLOAT( pState->mixer_mat[j][m][b + i_ts * IVAS_MAX_NUM_BANDS], tmpP_re[m][k], re ); - pState->spar_coeffs.P_re[j][k][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] += re; + IVAS_RMULT_FLOAT( hMdDec->mixer_mat[j][m][b + i_ts * IVAS_MAX_NUM_BANDS], tmpP_re[m][k], re ); + hMdDec->spar_coeffs.P_re[j][k][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] += re; } } } @@ -1281,8 +1271,8 @@ static void ivas_get_spar_matrices( { for ( m = 0; m < numch_out; m++ ) { - IVAS_RMULT_FLOAT( pState->mixer_mat[j][m][b + i_ts * IVAS_MAX_NUM_BANDS], tmpC_re[m][k], re ); - pState->spar_coeffs.C_re[j][k][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] += re; + IVAS_RMULT_FLOAT( hMdDec->mixer_mat[j][m][b + i_ts * IVAS_MAX_NUM_BANDS], tmpC_re[m][k], re ); + hMdDec->spar_coeffs.C_re[j][k][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] += re; } } } @@ -1290,42 +1280,42 @@ static void ivas_get_spar_matrices( /*fprintf(stdout, "C matrix1: %d x %d\n\n", numch_out, dmx_ch); for (j = 0; j < numch_out; j++) { - for (k = 0; k < dmx_ch; k++) - { - fprintf(stdout, "%f, ", pState->spar_coeffs.C_re[j][k][b]); - } - fprintf(stdout, "\n"); + for (k = 0; k < dmx_ch; k++) + { + fprintf(stdout, "%f, ", hMdDec->spar_coeffs.C_re[j][k][b]); + } + fprintf(stdout, "\n"); }*/ #endif - pState->spar_coeffs.C_re[0][0][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] = - max( 0, pState->spar_coeffs.C_re[0][0][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] ); + hMdDec->spar_coeffs.C_re[0][0][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] = + max( 0, hMdDec->spar_coeffs.C_re[0][0][( b * bw ) + i_ts * IVAS_MAX_NUM_BANDS] ); } } #ifdef SPAR_HOA_DBG /* for (b = 0; b < 1; b++) { - fprintf(stdout, "C matrix: %d x %d band %d\n\n", numch_out, dmx_ch, b); - for (j = 0; j < numch_out; j++) - { - for (k = 0; k < numch_out; k++) + fprintf(stdout, "C matrix: %d x %d band %d\n\n", numch_out, dmx_ch, b); + for (j = 0; j < numch_out; j++) { - fprintf(stdout, "%f, ", pState->spar_coeffs.C_re[j][k][b]); - } - fprintf(stdout, "\n"); + for (k = 0; k < numch_out; k++) + { + fprintf(stdout, "%f, ", hMdDec->spar_coeffs.C_re[j][k][b]); + } + fprintf(stdout, "\n"); - } - fprintf(stdout, "\nP matrix: %d x %d\n\n", numch_out, numch_out); + } + fprintf(stdout, "\nP matrix: %d x %d\n\n", numch_out, numch_out); - for (j = 0; j < numch_out; j++) - { - for (k = 0; k < numch_out; k++) + for (j = 0; j < numch_out; j++) { - fprintf(stdout, "%f, ", pState->spar_coeffs.P_re[j][k][b]); - } - fprintf(stdout, "\n"); + for (k = 0; k < numch_out; k++) + { + fprintf(stdout, "%f, ", hMdDec->spar_coeffs.P_re[j][k][b]); + } + fprintf(stdout, "\n"); - } + } }*/ #endif @@ -1334,12 +1324,12 @@ static void ivas_get_spar_matrices( { for ( b = 0; b < num_bands_out; b = b + bw ) { - dmx_ch = pState->spar_md_cfg.num_dmx_chans_per_band[b]; + dmx_ch = hMdDec->spar_md_cfg.num_dmx_chans_per_band[b]; for ( j = 0; j < numch_out; j++ ) { for ( k = dmx_ch; k < numch_out; k++ ) { - pState->spar_coeffs.P_re[j][k][( b + 1 ) + i_ts * IVAS_MAX_NUM_BANDS] = pState->spar_coeffs.P_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS]; + hMdDec->spar_coeffs.P_re[j][k][( b + 1 ) + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.P_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS]; } } @@ -1347,7 +1337,7 @@ static void ivas_get_spar_matrices( { for ( k = 0; k < dmx_ch; k++ ) { - pState->spar_coeffs.C_re[j][k][( b + 1 ) + i_ts * IVAS_MAX_NUM_BANDS] = pState->spar_coeffs.C_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS]; + hMdDec->spar_coeffs.C_re[j][k][( b + 1 ) + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.C_re[j][k][b + i_ts * IVAS_MAX_NUM_BANDS]; } } } @@ -1389,26 +1379,25 @@ static void ivas_mat_col_rearrange( /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_dec_gen_umx_mat() + * Function ivas_spar_dec_gen_umx_mat() * * generates upmix matrix *-----------------------------------------------------------------------------------------*/ -void ivas_spar_foa_dec_gen_umx_mat( - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t num_bands_out, /* i : number of output bands */ - const int16_t bfi /* i : bad frame indicator */ +void ivas_spar_dec_gen_umx_mat( + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t num_bands_out, /* i : number of output bands */ + const int16_t bfi /* i : bad frame indicator */ ) { - int16_t i, j, b, i_ts; - int16_t fb_ducking_flag = 0; - int16_t num_out_ch = hMdDec->spar_md_cfg.num_umx_chs; - ivas_spar_foa_md_dec_state_t *pState = hMdDec; + int16_t i, j, b, i_ts, num_out_ch; + + num_out_ch = hMdDec->spar_md_cfg.num_umx_chs; for ( i_ts = 0; i_ts < MAX_PARAM_SPATIAL_SUBFRAMES; i_ts++ ) { - if ( pState->td_decorr_flag == 1 ) + if ( hMdDec->td_decorr_flag == 1 ) { for ( i = 0; i < num_out_ch; i++ ) { @@ -1416,7 +1405,7 @@ void ivas_spar_foa_dec_gen_umx_mat( { for ( b = 0; b < num_bands_out; b++ ) { - pState->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = pState->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; + hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; } } } @@ -1427,15 +1416,10 @@ void ivas_spar_foa_dec_gen_umx_mat( { for ( b = 0; b < num_bands_out; b++ ) { - pState->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = pState->spar_coeffs.P_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; + hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.P_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; } } } - - if ( fb_ducking_flag ) - { - assert( 0 ); /* fb_ducking_flag not supported */ - } } else { @@ -1445,45 +1429,47 @@ void ivas_spar_foa_dec_gen_umx_mat( { for ( b = 0; b < num_bands_out; b++ ) { - pState->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = pState->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; + hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] = hMdDec->spar_coeffs.C_re[i][j][b + i_ts * IVAS_MAX_NUM_BANDS]; } } } } - } -#ifdef DEBUG_LBR_SBA // SPAR_HOA_DBG - /*for ( i_ts = 3; i_ts < MAX_PARAM_SPATIAL_SUBFRAMES; i_ts++ ) - { - for ( b = 0; b < 12; b++) + +#ifdef DEBUG_SBA_MD_DUMP { - fprintf( stdout, "\n\nMixer Matrix band %d\n\n", b ); + static FILE *f_mat = 0; + + if ( f_mat == 0 ) + f_mat = fopen( "mixer_mat_dec", "w" ); + for ( i = 0; i < num_out_ch; i++ ) { for ( j = 0; j < num_out_ch; j++ ) { - fprintf( stdout, "%.2f,\t", pState->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ); + for ( b = 0; b < num_bands_out; b++ ) + { + fprintf( f_mat, "%f\n", hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] ); + } } - fprintf( stdout, "\n" ); } - fprintf( stdout, "\n" ); } - }*/ #endif + } - ivas_spar_foa_dec_compute_ramp_down_post_matrix( pState, num_bands_out, bfi ); + ivas_spar_dec_compute_ramp_down_post_matrix( hMdDec, num_bands_out, bfi ); return; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_dec_parse_md_bs() + * Function ivas_spar_dec_parse_md_bs() * - * Parses MD bitstream + * Parse SPAR MD bitstream *-----------------------------------------------------------------------------------------*/ -static void ivas_spar_foa_dec_parse_md_bs( - ivas_spar_foa_md_dec_state_t *hMdDec, +static void ivas_spar_dec_parse_md_bs( + ivas_spar_md_dec_state_t *hMdDec, Decoder_State *st0, int16_t *nB, int16_t *bands_bw, @@ -1493,12 +1479,13 @@ static void ivas_spar_foa_dec_parse_md_bs( const int16_t sba_inactive_mode ) { int16_t i, j, k, num_bands; + int16_t ii, jj, ndec, ndm, b, idx; uint16_t qsi; ivas_quant_strat_t qs; - ivas_spar_foa_md_dec_state_t *pState = hMdDec; int16_t strat, freq_diff, no_ec; int16_t do_diff[IVAS_MAX_NUM_BANDS]; - int16_t planarCP = 0; + int16_t planarCP; + float quant[IVAS_SPAR_MAX_C_COEFF]; #ifdef LBR_SBA int16_t do_repeat[IVAS_MAX_NUM_BANDS]; #endif @@ -1506,358 +1493,304 @@ static void ivas_spar_foa_dec_parse_md_bs( *dtx_vad = 1; *bands_bw = 1; qsi = 0; - num_bands = pState->spar_md.num_bands; + num_bands = hMdDec->spar_md.num_bands; - if ( pState->spar_md_cfg.gen_bs == 1 ) + if ( ivas_total_brate > IVAS_SID_5k2 ) { - if ( ivas_total_brate > IVAS_SID_5k ) + if ( hMdDec->spar_md_cfg.quant_strat_bits > 0 ) { - if ( pState->spar_md_cfg.quant_strat_bits > 0 ) + if ( ivas_total_brate >= BRATE_SPAR_Q_STRAT ) { - if ( ivas_total_brate >= BRATE_SPAR_Q_STRAT ) + /*only one bit written for quantization strategy to indicate either a fixed quantization strategy or dtx_vad==0 */ + qsi = get_next_indice( st0, 1 ); + if ( qsi == 1 ) { - /*only one bit written for quantization strategy to indicate either a fixed quantization strategy or dtx_vad==0 */ - qsi = get_next_indice( st0, 1 ); - if ( qsi == 1 ) - { - *dtx_vad = 0; - } - } - else - { - if ( sba_inactive_mode == 1 ) - { - *dtx_vad = 0; - qsi = pState->spar_md_cfg.quant_strat_bits + 1; - } - else - { - qsi = get_next_indice( st0, pState->spar_md_cfg.quant_strat_bits ); - } + *dtx_vad = 0; } } else { - qsi = 0; + if ( sba_inactive_mode == 1 ) + { + *dtx_vad = 0; + qsi = hMdDec->spar_md_cfg.quant_strat_bits + 1; + } + else + { + qsi = get_next_indice( st0, hMdDec->spar_md_cfg.quant_strat_bits ); + } } } else { - *dtx_vad = 0; + qsi = 0; } + } + else + { + *dtx_vad = 0; + } - hMdDec->dtx_vad = *dtx_vad; + hMdDec->dtx_vad = *dtx_vad; - if ( *dtx_vad == 0 ) - { -#ifdef DEBUG_LBR_SBA - fprintf( stdout, "\nDTX Frame\n" ); -#endif - *nB = SPAR_DTX_BANDS; - *bands_bw = num_bands / *nB; + if ( *dtx_vad == 0 ) + { + *nB = SPAR_DTX_BANDS; + *bands_bw = num_bands / *nB; - for ( i = 0; i < *nB; i++ ) + for ( i = 0; i < *nB; i++ ) + { + for ( j = 0; j < IVAS_SPAR_MAX_CH - 1; j++ ) { - for ( j = 0; j < IVAS_SPAR_MAX_CH - 1; j++ ) - { - pState->spar_md.band_coeffs[i].pred_re[j] = 0; - pState->spar_md.band_coeffs[i].P_re[j] = 0; - } - pState->valid_bands[i] = 1; + hMdDec->spar_md.band_coeffs[i].pred_re[j] = 0; + hMdDec->spar_md.band_coeffs[i].P_re[j] = 0; } - for ( i = 0; i < num_bands; i++ ) + hMdDec->valid_bands[i] = 1; + } + + for ( i = 0; i < num_bands; i++ ) + { + for ( j = 0; j < ( IVAS_SPAR_MAX_CH - IVAS_SPAR_MAX_DMX_CHS ); j++ ) { - for ( j = 0; j < ( IVAS_SPAR_MAX_CH - IVAS_SPAR_MAX_DMX_CHS ); j++ ) + for ( k = 0; k < ( IVAS_SPAR_MAX_DMX_CHS - 1 ); k++ ) { - for ( k = 0; k < ( IVAS_SPAR_MAX_DMX_CHS - 1 ); k++ ) - { - pState->spar_md.band_coeffs[i].C_re[j][k] = 0; - } + hMdDec->spar_md.band_coeffs[i].C_re[j][k] = 0; } } + } + + ivas_parse_parameter_bitstream_dtx( &hMdDec->spar_md, st0, *bands_bw, *nB, hMdDec->spar_md_cfg.num_dmx_chans_per_band, hMdDec->spar_md_cfg.num_decorr_per_band ); + + for ( i = *nB - 1; i >= 0; i-- ) + { + ndec = hMdDec->spar_md_cfg.num_decorr_per_band[( *bands_bw ) * i]; - ivas_parse_parameter_bitstream_dtx( &pState->spar_md, st0, *bands_bw, *nB, - pState->spar_md_cfg.num_dmx_chans_per_band, pState->spar_md_cfg.num_decorr_per_band ); + for ( b = *bands_bw - 1; b >= 0; b-- ) { - int16_t ndec, b, idx; - for ( i = *nB - 1; i >= 0; i-- ) + idx = i * *bands_bw + b; + for ( j = 0; j < FOA_CHANNELS - 1; j++ ) { - ndec = pState->spar_md_cfg.num_decorr_per_band[( *bands_bw ) * i]; - - for ( b = *bands_bw - 1; b >= 0; b-- ) - { - idx = i * *bands_bw + b; - for ( j = 0; j < FOA_CHANNELS - 1; j++ ) - { - pState->spar_md.band_coeffs[idx].pred_re[j] = pState->spar_md.band_coeffs[i].pred_re[j]; - } - for ( j = 0; j < ndec; j++ ) - { - pState->spar_md.band_coeffs[idx].P_re[j] = pState->spar_md.band_coeffs[i].P_re[j]; - } - pState->valid_bands[idx] = 1; - } + hMdDec->spar_md.band_coeffs[idx].pred_re[j] = hMdDec->spar_md.band_coeffs[i].pred_re[j]; + } + for ( j = 0; j < ndec; j++ ) + { + hMdDec->spar_md.band_coeffs[idx].P_re[j] = hMdDec->spar_md.band_coeffs[i].P_re[j]; } - *nB = num_bands; - *bands_bw = 1; + hMdDec->valid_bands[idx] = 1; } - - return; } - qs = pState->spar_md_cfg.quant_strat[qsi]; - if ( ( qsi == 2 ) && ( use_planar_coeff ) ) - { - planarCP = 1; + *nB = num_bands; + *bands_bw = 1; + + return; + } + + qs = hMdDec->spar_md_cfg.quant_strat[qsi]; + + planarCP = 0; + if ( ( qsi == 2 ) && ( use_planar_coeff ) ) + { + planarCP = 1; #ifdef SPAR_HOA_DBG - fprintf( stdout, "planarCP = 1\n" ); + fprintf( stdout, "planarCP = 1\n" ); #endif - } - strat = get_next_indice( st0, 3 ); + } + strat = get_next_indice( st0, 3 ); + #ifdef SPAR_HOA_DBG - /*fprintf(stdout, "\n\n no_ec = %d, strat = %d\n", no_ec, strat);*/ + /*fprintf(stdout, "\n\n no_ec = %d, strat = %d\n", no_ec, strat);*/ #endif - freq_diff = 0; - no_ec = 0; + freq_diff = 0; + no_ec = 0; - if ( strat < 2 ) + if ( strat < 2 ) + { + *bands_bw = strat + 1; + *nB = num_bands / *bands_bw; + for ( i = 0; i < *nB; i++ ) { - *bands_bw = strat + 1; - *nB = num_bands / *bands_bw; - for ( i = 0; i < *nB; i++ ) - { - do_diff[i] = 0; + do_diff[i] = 0; #ifdef LBR_SBA - do_repeat[i] = 0; + do_repeat[i] = 0; #endif - } } - else if ( strat < 4 ) + } + else if ( strat < 4 ) + { + *bands_bw = strat - 1; + *nB = num_bands / *bands_bw; + for ( i = 0; i < *nB; i++ ) { - *bands_bw = strat - 1; - *nB = num_bands / *bands_bw; - for ( i = 0; i < *nB; i++ ) - { - do_diff[i] = 0; + do_diff[i] = 0; #ifdef LBR_SBA - do_repeat[i] = 0; + do_repeat[i] = 0; #endif - } - no_ec = 1; } - else - { -#ifdef LBR_SBA - if ( ivas_total_brate < IVAS_24k4 ) - { - *bands_bw = 2; - *nB = num_bands / *bands_bw; - - for ( i = 0; i < *nB; i++ ) - { - do_diff[i] = 0; - do_repeat[i] = ( ( strat % 2 ) == ( ( i + 1 ) % 2 ) ); - } - } - else -#endif - { - *bands_bw = 1; - *nB = num_bands; + no_ec = 1; + } + else #ifdef LBR_SBA + if ( ivas_total_brate < IVAS_24k4 ) + { + *bands_bw = 2; + *nB = num_bands / *bands_bw; + + for ( i = 0; i < *nB; i++ ) + { + do_diff[i] = 0; + do_repeat[i] = ( ( strat % 2 ) == ( ( i + 1 ) % 2 ) ); + } + } + else + { + *bands_bw = 1; + *nB = num_bands; + + for ( i = 0; i < *nB; i++ ) + { + do_diff[i] = ( ( ( i + 1 ) & 3 ) != strat - 4 ); + do_repeat[i] = 0; + } + + ivas_map_prior_coeffs_quant( &hMdDec->spar_md_prev, &hMdDec->spar_md_cfg, qsi, *nB ); + } +#else + { + *bands_bw = 1; + *nB = num_bands; - for ( i = 0; i < *nB; i++ ) - { - do_diff[i] = ( ( ( i + 1 ) & 3 ) != strat - 4 ); - do_repeat[i] = 0; - } - - ivas_map_prior_coeffs_quant( &pState->spar_md_prev, &pState->spar_md_cfg, qsi, *nB ); -#endif - } -#ifndef LBR_SBA - for ( i = 0; i < *nB; i++ ) - { - do_diff[i] = ( ( ( i + 1 ) & 3 ) != strat - 4 ); - } + for ( i = 0; i < *nB; i++ ) + { + do_diff[i] = ( ( ( i + 1 ) & 3 ) != strat - 4 ); + } - ivas_map_prior_coeffs_quant( &pState->spar_md_prev, &pState->spar_md_cfg, qsi, *nB ); + ivas_map_prior_coeffs_quant( &hMdDec->spar_md_prev, &hMdDec->spar_md_cfg, qsi, *nB ); + } #endif - } #ifdef SPAR_HOA_DBG - fprintf( stdout, "\n\n no_ec = %d, strat = %d\n", no_ec, strat ); + fprintf( stdout, "\n\n no_ec = %d, strat = %d\n", no_ec, strat ); #endif - pState->spar_md_cfg.prev_quant_idx = qsi; + hMdDec->spar_md_cfg.prev_quant_idx = qsi; - if ( no_ec == 0 ) - { - ivas_decode_arith_bs( pState, st0, qsi, *nB, *bands_bw, do_diff, freq_diff, planarCP + if ( no_ec == 0 ) + { + ivas_decode_arith_bs( hMdDec, st0, qsi, *nB, *bands_bw, do_diff, freq_diff, planarCP #ifdef LBR_SBA - , - strat, ivas_total_brate + , + strat, ivas_total_brate #endif - ); - } - else - { - ivas_decode_huffman_bs( pState, st0, qsi, *nB, *bands_bw, planarCP + ); + } + else + { + ivas_decode_huffman_bs( hMdDec, st0, qsi, *nB, *bands_bw, planarCP #ifdef LBR_SBA_PLANAR - , - ivas_total_brate + , + ivas_total_brate #endif - ); - } - - for ( i = 0; i < *nB; i++ ) - { - int16_t ii, jj; - int16_t *index_scratch[IVAS_SPAR_P_LOWERTRI]; - float *quant_scratch[IVAS_SPAR_P_LOWERTRI]; - int16_t ndec = pState->spar_md_cfg.num_decorr_per_band[( *bands_bw ) * i]; - int16_t ndm = pState->spar_md_cfg.num_dmx_chans_per_band[( *bands_bw ) * i]; - int16_t **index = (int16_t **) &index_scratch[0]; - float **quant = (float **) &quant_scratch[0]; - float coeff_decd[IVAS_SPAR_MAX_CH - 1]; - float coeff_decx_re[IVAS_SPAR_P_LOWERTRI]; - int16_t pred_index_re[IVAS_SPAR_MAX_CH - 1]; - int16_t drct_index_re[IVAS_SPAR_MAX_C_COEFF]; - int16_t decd_index_re[IVAS_SPAR_MAX_CH - 1]; - int16_t decx_index_re[IVAS_SPAR_P_LOWERTRI]; + ); + } - for ( j = 0; j < ndm + ndec - 1; j++ ) - { - pred_index_re[j] = pState->spar_md.band_coeffs_idx[i].pred_index_re[j]; - } - for ( j = 0; j < ndec * ( ndm - 1 ); j++ ) - { - drct_index_re[j] = pState->spar_md.band_coeffs_idx[i].drct_index_re[j]; - } - for ( j = 0; j < ndec; j++ ) - { - decd_index_re[j] = pState->spar_md.band_coeffs_idx[i].decd_index_re[j]; - } + for ( i = 0; i < *nB; i++ ) + { + ndec = hMdDec->spar_md_cfg.num_decorr_per_band[( *bands_bw ) * i]; + ndm = hMdDec->spar_md_cfg.num_dmx_chans_per_band[( *bands_bw ) * i]; - index[0] = &pred_index_re[0]; - quant[0] = &pState->spar_md.band_coeffs[i].pred_re[0]; + ivas_deindex_real_index( hMdDec->spar_md.band_coeffs_idx[i].pred_index_re, qs.PR.q_levels[0], qs.PR.min, qs.PR.max, hMdDec->spar_md.band_coeffs[i].pred_re, ndm + ndec - 1 ); - ivas_deindex_real_index( index, qs.PR.q_levels[0], qs.PR.min, qs.PR.max, quant, 1, ndm + ndec - 1 ); - for ( ii = 0; ii < ndec; ii++ ) - { - for ( jj = 0; jj < ndm - 1; jj++ ) - { - pState->spar_md.band_coeffs[i].C_re[ii][jj] = 0; - } - } - j = 0; - for ( ii = 0; ii < ndec; ii++ ) + j = 0; + for ( ii = 0; ii < ndec; ii++ ) + { + for ( jj = 0; jj < ndm - 1; jj++ ) { - for ( jj = 0; jj < ndm - 1; jj++ ) - { - index[j] = &drct_index_re[j]; - quant[j] = &pState->spar_md.band_coeffs[i].C_re[ii][jj]; - j++; - } + quant[j] = hMdDec->spar_md.band_coeffs[i].C_re[ii][jj]; + j++; } - ivas_deindex_real_index( index, qs.C.q_levels[0], qs.C.min, qs.C.max, quant, ndec * ( ndm - 1 ), 1 ); - - index[0] = &decd_index_re[0]; - quant[0] = &coeff_decd[0]; - ivas_deindex_real_index( index, qs.P_r.q_levels[0], qs.P_r.min, qs.P_r.max, quant, 1, ndm + ndec - 1 ); + } - index[0] = &decx_index_re[0]; - quant[0] = &coeff_decx_re[0]; - ivas_deindex_real_index( index, qs.P_c.q_levels[0], qs.P_c.min, qs.P_c.max, quant, 1, ndec * ( ndec - 1 ) >> 2 ); + ivas_deindex_real_index( hMdDec->spar_md.band_coeffs_idx[i].drct_index_re, qs.C.q_levels[0], qs.C.min, qs.C.max, quant, ndec * ( ndm - 1 ) ); - /* Store prior coefficient indices */ - for ( j = 0; j < ndm + ndec - 1; j++ ) - { - pState->spar_md_prev.band_coeffs_idx[i].pred_index_re[j] = pred_index_re[j]; - } - for ( j = 0; j < ndec * ( ndm - 1 ); j++ ) - { - pState->spar_md_prev.band_coeffs_idx[i].drct_index_re[j] = drct_index_re[j]; - } - for ( j = 0; j < ndec; j++ ) - { - pState->spar_md_prev.band_coeffs_idx[i].decd_index_re[j] = decd_index_re[j]; - } - for ( k = 0; k < ndec; k++ ) - { - pState->spar_md.band_coeffs[i].P_re[k] = 0; - } - for ( j = 0; j < ndec; j++ ) + j = 0; + for ( ii = 0; ii < ndec; ii++ ) + { + for ( jj = 0; jj < ndm - 1; jj++ ) { - /* Don't bother adding in the decx parameters */ - pState->spar_md.band_coeffs[i].P_re[j] = coeff_decd[j]; + hMdDec->spar_md.band_coeffs[i].C_re[ii][jj] = quant[j]; + j++; } + } + + ivas_deindex_real_index( hMdDec->spar_md.band_coeffs_idx[i].decd_index_re, qs.P_r.q_levels[0], qs.P_r.min, qs.P_r.max, hMdDec->spar_md.band_coeffs[i].P_re, ndm + ndec - 1 ); + /* Store prior coefficient indices */ + for ( j = 0; j < ndm + ndec - 1; j++ ) + { + hMdDec->spar_md_prev.band_coeffs_idx[i].pred_index_re[j] = hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[j]; + } + for ( j = 0; j < ndec * ( ndm - 1 ); j++ ) + { + hMdDec->spar_md_prev.band_coeffs_idx[i].drct_index_re[j] = hMdDec->spar_md.band_coeffs_idx[i].drct_index_re[j]; + } + for ( j = 0; j < ndec; j++ ) + { + hMdDec->spar_md_prev.band_coeffs_idx[i].decd_index_re[j] = hMdDec->spar_md.band_coeffs_idx[i].decd_index_re[j]; + } #ifdef LBR_SBA - pState->valid_bands[*bands_bw * i] |= ( do_diff[i] == 0 && do_repeat[i] == 0 ) ? 1 : 0; + hMdDec->valid_bands[*bands_bw * i] |= ( do_diff[i] == 0 && do_repeat[i] == 0 ) ? 1 : 0; for ( j = 1; j < *bands_bw; j++ ) { - pState->valid_bands[*bands_bw * i + j] = pState->valid_bands[*bands_bw * i]; + hMdDec->valid_bands[*bands_bw * i + j] = hMdDec->valid_bands[*bands_bw * i]; } #else - pState->valid_bands[i] |= ( do_diff[i] == 0 ) ? 1 : 0; + hMdDec->valid_bands[i] |= ( do_diff[i] == 0 ) ? 1 : 0; #endif - } } - else - { - *dtx_vad = pState->spar_md.dtx_vad; - *nB = num_bands; - *bands_bw = num_bands / *nB; - - for ( i = 0; i < *nB; i++ ) - { - pState->valid_bands[i] = 1; - } - } -#ifdef DEBUG_LBR_SBA // SPAR_HOA_DBG +#ifdef SPAR_HOA_DBG int16_t b; b = 0; - // if (0) + /*if ( 0 ) { for ( b = 0; b < *nB; b++ ) { - /*int16_t ndec = pState->spar_md_cfg.num_decorr_per_band[(*bands_bw) * b]; - int16_t ndm = pState->spar_md_cfg.num_dmx_chans_per_band[(*bands_bw) * b]; - fprintf(stdout, "\n\nMETADATA PR: band %d, qsi %d\n\n", b, qsi); - for (i = 0; i < ndm + ndec - 1; i++) + int16_t ndec = hMdDec->spar_md_cfg.num_decorr_per_band[( *bands_bw ) * b]; + int16_t ndm = hMdDec->spar_md_cfg.num_dmx_chans_per_band[( *bands_bw ) * b]; + fprintf( stdout, "\n\nMETADATA PR: band %d, qsi %d\n\n", b, qsi ); + for ( i = 0; i < ndm + ndec - 1; i++ ) { - fprintf(stdout, "i: %d -- %f\t %d\t %d\n", i, - pState->spar_md.band_coeffs[b].pred_re[i], - pState->spar_md_prev.band_coeffs_idx[b].pred_index_re[i], - pState->spar_md.band_coeffs_idx[b].pred_index_re[i]); + fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, + hMdDec->spar_md.band_coeffs[b].pred_re[i], + hMdDec->spar_md_prev.band_coeffs_idx[b].pred_index_re[i], + hMdDec->spar_md.band_coeffs_idx[b].pred_index_re[i] ); } - fprintf(stdout, "\n\n METADATA C: band %d\n\n", b); + fprintf( stdout, "\n\n METADATA C: band %d\n\n", b ); k = 0; - for (i = 0; i < ndec; i++) + for ( i = 0; i < ndec; i++ ) { - for (j = 0; j < (ndm - 1); j++) + for ( j = 0; j < ( ndm - 1 ); j++ ) { - fprintf(stdout, "i: %d -- %f\t %d\t %d\n", i, - pState->spar_md.band_coeffs[b].C_re[i][j], - pState->spar_md_prev.band_coeffs_idx[b].drct_index_re[k], - pState->spar_md.band_coeffs_idx[b].drct_index_re[k]); + fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, + hMdDec->spar_md.band_coeffs[b].C_re[i][j], + hMdDec->spar_md_prev.band_coeffs_idx[b].drct_index_re[k], + hMdDec->spar_md.band_coeffs_idx[b].drct_index_re[k] ); k++; } } - fprintf(stdout, "\n\n METADATA Pd: band %d\n\n", b); - for (i = 0; i < ndec; i++) + fprintf( stdout, "\n\n METADATA Pd: band %d\n\n", b ); + for ( i = 0; i < ndec; i++ ) { - fprintf(stdout, "i: %d -- %f\t %d\t %d\n", i, - pState->spar_md.band_coeffs[b].P_re[i], - pState->spar_md_prev.band_coeffs_idx[b].decd_index_re[i], - pState->spar_md.band_coeffs_idx[b].decd_index_re[i]); + fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, + hMdDec->spar_md.band_coeffs[b].P_re[i][i], + hMdDec->spar_md_prev.band_coeffs_idx[b].decd_index_re[i], + hMdDec->spar_md.band_coeffs_idx[b].decd_index_re[i] ); } - fprintf(stdout, "\n\n");*/ - /*int16_t ndec = pState->spar_md_cfg.num_decorr_per_band[( *bands_bw ) * b]; - int16_t ndm = pState->spar_md_cfg.num_dmx_chans_per_band[( *bands_bw ) * b]; + fprintf( stdout, "\n\n" ); + int16_t ndec = hMdDec->spar_md_cfg.num_decorr_per_band[( *bands_bw ) * b]; + int16_t ndm = hMdDec->spar_md_cfg.num_dmx_chans_per_band[( *bands_bw ) * b]; fprintf( stdout, "\n\n Metadata PR (15x1), C(15x15), P(15x15): band %d\n", b ); for ( i = 0; i < ndm + ndec - 1; i++ ) { - fprintf( stdout, "i: %d -- %.2f\t|\t", i, pState->spar_md.band_coeffs[b].pred_re[i] ); + fprintf( stdout, "i: %d -- %.2f\t|\t", i, hMdDec->spar_md.band_coeffs[b].pred_re[i] ); if ( i < ndec ) { if ( keep_planar[i] == 1 ) @@ -1870,16 +1803,19 @@ static void ivas_spar_foa_dec_parse_md_bs( } for ( j = 0; j < ndm - 1; j++ ) { - fprintf( stdout, "%.2f\t", pState->spar_md.band_coeffs[b].C_re[i][j] ); + fprintf( stdout, "%.2f\t", hMdDec->spar_md.band_coeffs[b].C_re[i][j] ); } fprintf( stdout, "|\t" ); - fprintf( stdout, "%.2f", pState->spar_md.band_coeffs[b].P_re[i] ); + for ( j = 0; j < ndec; j++ ) + { + fprintf( stdout, "%.2f\t", hMdDec->spar_md.band_coeffs[b].P_re[i][j] ); + } } fprintf( stdout, "\n" ); } - fprintf( stdout, "\n" );*/ + fprintf( stdout, "\n" ); } - } + }*/ #endif return; @@ -1889,11 +1825,11 @@ static void ivas_spar_foa_dec_parse_md_bs( /*-----------------------------------------------------------------------------------------* * Function ivas_decode_arith_bs() * - * decode bitstream with arith decoder + * Decode bitstream with arith decoder *-----------------------------------------------------------------------------------------*/ static void ivas_decode_arith_bs( - ivas_spar_foa_md_dec_state_t *pState, + ivas_spar_md_dec_state_t *hMdDec, Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ const uint16_t qsi, const int16_t nB, @@ -1905,20 +1841,22 @@ static void ivas_decode_arith_bs( , const int16_t strat, const int32_t ivas_total_brate -#endif +#endif ) { - int16_t i, ndm, ndec; + int16_t i, j, ndm, ndec; ivas_cell_dim_t pred_cell_dims[IVAS_MAX_NUM_BANDS]; ivas_cell_dim_t drct_cell_dims[IVAS_MAX_NUM_BANDS]; ivas_cell_dim_t decd_cell_dims[IVAS_MAX_NUM_BANDS]; ivas_cell_dim_t decx_cell_dims[IVAS_MAX_NUM_BANDS]; int16_t symbol_arr_re[IVAS_MAX_INPUT_LEN]; int16_t symbol_arr_old_re[IVAS_MAX_INPUT_LEN]; - int16_t any_diff = 0; + int16_t any_diff; for ( i = 0; i < nB; i++ ) { + ndm = hMdDec->spar_md_cfg.num_dmx_chans_per_band[bands_bw * i]; + ndec = hMdDec->spar_md_cfg.num_decorr_per_band[bands_bw * i]; #ifdef LBR_SBA if ( ( ivas_total_brate < IVAS_24k4 ) && ( strat > 3 ) && ( ( ( i % 2 == 1 ) && ( strat % 2 == 0 ) ) || ( ( i % 2 == 0 ) && ( strat % 2 == 1 ) ) ) ) { @@ -1932,19 +1870,23 @@ static void ivas_decode_arith_bs( decx_cell_dims[i].dim2 = 0; } else -#endif { - ndm = pState->spar_md_cfg.num_dmx_chans_per_band[bands_bw * i]; - ndec = pState->spar_md_cfg.num_decorr_per_band[bands_bw * i]; - - pred_cell_dims[i].dim1 = ndm + ndec - 1; - pred_cell_dims[i].dim2 = 1; - drct_cell_dims[i].dim1 = ndec; - drct_cell_dims[i].dim2 = ndm - 1; - decd_cell_dims[i].dim1 = ndec; - decd_cell_dims[i].dim2 = 1; - decx_cell_dims[i].dim1 = ( ndec * ( ndec - 1 ) ) >> 1; - decx_cell_dims[i].dim2 = 1; +#endif + pred_cell_dims[i].dim1 = ndm + ndec - 1; + if ( hMdDec->spar_hoa_md_flag ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + pred_cell_dims[i].dim1 -= ( FOA_CHANNELS - 1 ); + } + } + pred_cell_dims[i].dim2 = 1; + drct_cell_dims[i].dim1 = ndec; + drct_cell_dims[i].dim2 = ndm - 1; + decd_cell_dims[i].dim1 = ndec; + decd_cell_dims[i].dim2 = 1; + decx_cell_dims[i].dim1 = ( ndec * ( ndec - 1 ) ) >> 1; + decx_cell_dims[i].dim2 = 1; #ifdef LBR_SBA_PLANAR if ( ivas_total_brate < IVAS_24k4 ) { @@ -1952,9 +1894,12 @@ static void ivas_decode_arith_bs( decd_cell_dims[i].dim1 -= 1; } #endif +#ifdef LBR_SBA } +#endif } + any_diff = 0; for ( i = 0; i < nB; i++ ) { if ( pDo_diff[i] != 0 ) @@ -1966,17 +1911,50 @@ static void ivas_decode_arith_bs( if ( any_diff == 1 ) { - ivas_copy_band_coeffs_idx_to_arr( pState->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, pred_cell_dims, PRED_COEFF, planarCP ); + if ( hMdDec->spar_hoa_md_flag ) + { + for ( i = 0; i < nB; i++ ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + for ( j = 0; j < pred_cell_dims[i].dim1; j++ ) + { + hMdDec->spar_md_prev.band_coeffs_idx_mapped[i].pred_index_re[j] = + hMdDec->spar_md_prev.band_coeffs_idx_mapped[i].pred_index_re[j + ( FOA_CHANNELS - 1 )]; + } + } + } + } + ivas_copy_band_coeffs_idx_to_arr( hMdDec->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, pred_cell_dims, PRED_COEFF, planarCP ); } - ivas_arith_decode_cmplx_cell_array( &pState->arith_coeffs.pred_arith_re[qsi], &pState->arith_coeffs.pred_arith_re_diff[qsi], + ivas_arith_decode_cmplx_cell_array( &hMdDec->arith_coeffs.pred_arith_re[qsi], &hMdDec->arith_coeffs.pred_arith_re_diff[qsi], st0, pred_cell_dims, pDo_diff, nB, symbol_arr_re, symbol_arr_old_re ); - ivas_fill_band_coeffs_idx( pState->spar_md.band_coeffs_idx, nB, symbol_arr_re, pred_cell_dims, PRED_COEFF, planarCP ); + ivas_fill_band_coeffs_idx( hMdDec->spar_md.band_coeffs_idx, nB, symbol_arr_re, pred_cell_dims, PRED_COEFF, planarCP ); + + if ( hMdDec->spar_hoa_md_flag ) + { + for ( i = 0; i < nB; i++ ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + for ( j = pred_cell_dims[i].dim1 - 1; j >= 0; j-- ) + { + hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[j + ( FOA_CHANNELS - 1 )] = + hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[j]; + } + for ( j = 0; j < FOA_CHANNELS - 1; j++ ) + { + hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[j] = 0; + } + } + } + } if ( any_diff == 1 ) { - ivas_copy_band_coeffs_idx_to_arr( pState->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, drct_cell_dims, DRCT_COEFF, planarCP ); + ivas_copy_band_coeffs_idx_to_arr( hMdDec->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, drct_cell_dims, DRCT_COEFF, planarCP ); } if ( planarCP ) @@ -1987,14 +1965,14 @@ static void ivas_decode_arith_bs( } } - ivas_arith_decode_cmplx_cell_array( &pState->arith_coeffs.drct_arith_re[qsi], &pState->arith_coeffs.drct_arith_re_diff[qsi], + ivas_arith_decode_cmplx_cell_array( &hMdDec->arith_coeffs.drct_arith_re[qsi], &hMdDec->arith_coeffs.drct_arith_re_diff[qsi], st0, drct_cell_dims, pDo_diff, nB, symbol_arr_re, symbol_arr_old_re ); - ivas_fill_band_coeffs_idx( pState->spar_md.band_coeffs_idx, nB, symbol_arr_re, drct_cell_dims, DRCT_COEFF, planarCP ); + ivas_fill_band_coeffs_idx( hMdDec->spar_md.band_coeffs_idx, nB, symbol_arr_re, drct_cell_dims, DRCT_COEFF, planarCP ); if ( any_diff == 1 ) { - ivas_copy_band_coeffs_idx_to_arr( pState->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, decd_cell_dims, DECD_COEFF, planarCP ); + ivas_copy_band_coeffs_idx_to_arr( hMdDec->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, decd_cell_dims, DECD_COEFF, planarCP ); } if ( planarCP ) @@ -2005,27 +1983,27 @@ static void ivas_decode_arith_bs( } } - ivas_arith_decode_cmplx_cell_array( &pState->arith_coeffs.decd_arith_re[qsi], &pState->arith_coeffs.decd_arith_re_diff[qsi], + ivas_arith_decode_cmplx_cell_array( &hMdDec->arith_coeffs.decd_arith_re[qsi], &hMdDec->arith_coeffs.decd_arith_re_diff[qsi], st0, decd_cell_dims, pDo_diff, nB, symbol_arr_re, symbol_arr_old_re ); - ivas_fill_band_coeffs_idx( pState->spar_md.band_coeffs_idx, nB, symbol_arr_re, decd_cell_dims, DECD_COEFF, planarCP ); + ivas_fill_band_coeffs_idx( hMdDec->spar_md.band_coeffs_idx, nB, symbol_arr_re, decd_cell_dims, DECD_COEFF, planarCP ); if ( any_diff == 1 ) { - ivas_copy_band_coeffs_idx_to_arr( pState->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, decx_cell_dims, DECX_COEFF, planarCP ); + ivas_copy_band_coeffs_idx_to_arr( hMdDec->spar_md_prev.band_coeffs_idx_mapped, nB, symbol_arr_old_re, decx_cell_dims, DECX_COEFF, planarCP ); } - ivas_fill_band_coeffs_idx( pState->spar_md.band_coeffs_idx, nB, symbol_arr_re, decx_cell_dims, DECX_COEFF, planarCP ); + ivas_fill_band_coeffs_idx( hMdDec->spar_md.band_coeffs_idx, nB, symbol_arr_re, decx_cell_dims, DECX_COEFF, planarCP ); if ( freq_diff == 1 ) { #ifdef SPAR_HOA_DBG /* NOTE: This is currently unused code, and SPAR_HOA changes have not been made here. */ #endif - ivas_get_band_idx_from_differential( &pState->spar_md, pState->spar_md_cfg.quant_strat->PR.q_levels, 0, nB, PRED_COEFF ); - ivas_get_band_idx_from_differential( &pState->spar_md, pState->spar_md_cfg.quant_strat->C.q_levels, 0, nB, DRCT_COEFF ); - ivas_get_band_idx_from_differential( &pState->spar_md, pState->spar_md_cfg.quant_strat->P_r.q_levels, 1, nB, DECD_COEFF ); - ivas_get_band_idx_from_differential( &pState->spar_md, pState->spar_md_cfg.quant_strat->P_c.q_levels, 0, nB, DECX_COEFF ); + ivas_get_band_idx_from_differential( &hMdDec->spar_md, hMdDec->spar_md_cfg.quant_strat->PR.q_levels, 0, nB, PRED_COEFF ); + ivas_get_band_idx_from_differential( &hMdDec->spar_md, hMdDec->spar_md_cfg.quant_strat->C.q_levels, 0, nB, DRCT_COEFF ); + ivas_get_band_idx_from_differential( &hMdDec->spar_md, hMdDec->spar_md_cfg.quant_strat->P_r.q_levels, 1, nB, DECD_COEFF ); + ivas_get_band_idx_from_differential( &hMdDec->spar_md, hMdDec->spar_md_cfg.quant_strat->P_c.q_levels, 0, nB, DECX_COEFF ); } #ifdef LBR_SBA_PLANAR if ( ivas_total_brate < IVAS_24k4 ) @@ -2034,10 +2012,10 @@ static void ivas_decode_arith_bs( { if ( ( strat < 3 ) || ( ( strat > 3 ) && ( ( ( i % 2 == 0 ) && ( strat % 2 == 0 ) ) || ( ( i % 2 == 1 ) && ( strat % 2 == 1 ) ) ) ) ) { - pState->spar_md.band_coeffs_idx[i].pred_index_re[2] = pState->spar_md.band_coeffs_idx[i].pred_index_re[1]; - pState->spar_md.band_coeffs_idx[i].pred_index_re[1] = 0; + hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[2] = hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[1]; + hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[1] = 0; } - pState->spar_md.band_coeffs_idx[i].decd_index_re[2] = 0; /* shouldn't be needed */ + hMdDec->spar_md.band_coeffs_idx[i].decd_index_re[2] = 0; /* shouldn't be needed */ } } #endif @@ -2050,6 +2028,7 @@ static void ivas_decode_arith_bs( * * *-----------------------------------------------------------------------------------------*/ + #ifdef SPAR_HOA_DBG /* NOTE: No changes here as frequency differential coding is unused. */ #endif @@ -2209,11 +2188,11 @@ static void ivas_fill_band_coeffs_idx( /*-----------------------------------------------------------------------------------------* * Function ivas_decode_huffman_bs() * - * decode bitstream with huffman decoder + * Decode bitstream with huffman decoder *-----------------------------------------------------------------------------------------*/ static void ivas_decode_huffman_bs( - ivas_spar_foa_md_dec_state_t *pState, + ivas_spar_md_dec_state_t *hMdDec, Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/ const uint16_t qsi, const int16_t nB, @@ -2222,67 +2201,83 @@ static void ivas_decode_huffman_bs( #ifdef LBR_SBA_PLANAR , const int32_t ivas_total_brate -#endif +#endif ) { int16_t i, j; + int16_t ndm, ndec; + int16_t pred_dim, drct_dim, decd_dim, pred_offset; for ( i = 0; i < nB; i++ ) { - int16_t ndm, ndec; - int16_t pred_dim, drct_dim, decd_dim; - - ndm = pState->spar_md_cfg.num_dmx_chans_per_band[bands_bw * i]; - ndec = pState->spar_md_cfg.num_decorr_per_band[bands_bw * i]; + ndm = hMdDec->spar_md_cfg.num_dmx_chans_per_band[bands_bw * i]; + ndec = hMdDec->spar_md_cfg.num_decorr_per_band[bands_bw * i]; pred_dim = ndec + ndm - 1; drct_dim = ndec * ( ndm - 1 ); decd_dim = ndec; + pred_offset = 0; + if ( hMdDec->spar_hoa_md_flag ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + pred_offset = FOA_CHANNELS - 1; + } + } - for ( j = 0; j < pred_dim; j++ ) + for ( j = pred_offset; j < pred_dim; j++ ) { #ifdef LBR_SBA_PLANAR if ( ( j == 1 ) && ( ivas_total_brate < IVAS_24k4 ) ) { - pState->spar_md.band_coeffs_idx[i].pred_index_re[j] = 0; + hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[j] = 0; } else { #endif - ivas_huffman_decode( &pState->huff_coeffs.pred_huff_re[qsi], st0, - &pState->spar_md.band_coeffs_idx[i].pred_index_re[j] ); + ivas_huffman_decode( &hMdDec->huff_coeffs.pred_huff_re[qsi], st0, + &hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[j] ); #ifdef LBR_SBA_PLANAR } #endif } + if ( hMdDec->spar_hoa_md_flag ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + for ( j = 0; j < pred_offset; j++ ) + { + hMdDec->spar_md.band_coeffs_idx[i].pred_index_re[j] = 0; + } + } + } + for ( j = 0; j < drct_dim; j++ ) { +#ifdef LBR_SBA_PLANAR + if ( ( planarCP && !keep_planar[(int16_t) floor( j / ( ndm - 1 ) )] ) || ( ( j == 2 ) && ( ivas_total_brate < IVAS_24k4 ) ) ) +#else if ( planarCP && !keep_planar[(int16_t) floor( j / ( ndm - 1 ) )] ) +#endif { - pState->spar_md.band_coeffs_idx[i].drct_index_re[j] = 0; + hMdDec->spar_md.band_coeffs_idx[i].drct_index_re[j] = 0; } else { - ivas_huffman_decode( &pState->huff_coeffs.drct_huff_re[qsi], st0, - &pState->spar_md.band_coeffs_idx[i].drct_index_re[j] ); + ivas_huffman_decode( &hMdDec->huff_coeffs.drct_huff_re[qsi], st0, &hMdDec->spar_md.band_coeffs_idx[i].drct_index_re[j] ); } } for ( j = 0; j < decd_dim; j++ ) { -#ifdef LBR_SBA_PLANAR - if ( ( planarCP && !keep_planar[j] ) || ( ( j == 2 ) && ( ivas_total_brate < IVAS_24k4 ) ) ) -#else if ( planarCP && !keep_planar[j] ) -#endif { - pState->spar_md.band_coeffs_idx[i].decd_index_re[j] = 0; + hMdDec->spar_md.band_coeffs_idx[i].decd_index_re[j] = 0; } else { - ivas_huffman_decode( &pState->huff_coeffs.decd_huff_re[qsi], st0, - &pState->spar_md.band_coeffs_idx[i].decd_index_re[j] ); + ivas_huffman_decode( &hMdDec->huff_coeffs.decd_huff_re[qsi], st0, &hMdDec->spar_md.band_coeffs_idx[i].decd_index_re[j] ); } } } @@ -2294,14 +2289,14 @@ static void ivas_decode_huffman_bs( /*-----------------------------------------------------------------------------------------* * Function ivas_spar_md_fill_invalid_bands() * - * fill invalid bands in interpolation/extrapolation of valid bands + * Fill invalid bands in interpolation/extrapolation of valid bands * when PLC is to be done with partial time differential coding *-----------------------------------------------------------------------------------------*/ static void ivas_spar_md_fill_invalid_bands( ivas_spar_dec_matrices_t *pSpar_coeffs, ivas_spar_dec_matrices_t *pSpar_coeffs_prev, - int16_t *valid_bands, + const int16_t *valid_bands, int16_t *base_band_age, const int16_t num_bands, const int16_t sba_order /* i : SBA order */ @@ -2416,44 +2411,43 @@ static void ivas_spar_md_fill_invalid_bands( /*-----------------------------------------------------------------------------------------* -* Function ivas_spar_foa_dec_compute_ramp_down_post_matrix() -* -* ivas_spar_foa_dec_compute_ramp_down_post_matrix - -*-----------------------------------------------------------------------------------------*/ + * Function ivas_spar_dec_compute_ramp_down_post_matrix() + * + * + *-----------------------------------------------------------------------------------------*/ -static void ivas_spar_foa_dec_compute_ramp_down_post_matrix( - ivas_spar_foa_md_dec_state_t *pState, +static void ivas_spar_dec_compute_ramp_down_post_matrix( + ivas_spar_md_dec_state_t *hMdDec, const int16_t num_bands_out, const int16_t bfi ) { int16_t num_in_ch, num_out_ch, i, j, b; - num_in_ch = pState->spar_md_cfg.num_umx_chs; - num_out_ch = pState->spar_md_cfg.num_umx_chs; + num_in_ch = hMdDec->spar_md_cfg.num_umx_chs; + num_out_ch = hMdDec->spar_md_cfg.num_umx_chs; if ( bfi == 0 ) { - pState->spar_plc_num_lost_frames = 0; + hMdDec->spar_plc_num_lost_frames = 0; } else { - if ( pState->td_decorr_flag == 0 ) + if ( hMdDec->td_decorr_flag == 0 ) { assert( 0 ); } - pState->spar_plc_num_lost_frames += 1; - pState->spar_plc_num_lost_frames = min( pState->spar_plc_num_lost_frames, 100 ); + hMdDec->spar_plc_num_lost_frames += 1; + hMdDec->spar_plc_num_lost_frames = min( hMdDec->spar_plc_num_lost_frames, 100 ); - if ( pState->spar_plc_num_lost_frames > ivas_spar_dec_plc_num_frames_keep ) + if ( hMdDec->spar_plc_num_lost_frames > ivas_spar_dec_plc_num_frames_keep ) { int16_t num_fade_frames; int16_t gain_dB; float gain; float post_matrix[IVAS_SPAR_MAX_CH]; - num_fade_frames = max( pState->spar_plc_num_lost_frames - ivas_spar_dec_plc_num_frames_keep, 0 ); + num_fade_frames = max( hMdDec->spar_plc_num_lost_frames - ivas_spar_dec_plc_num_frames_keep, 0 ); gain_dB = -min( num_fade_frames, ivas_spar_dec_plc_max_num_frames_ramp_down ) * ivas_spar_dec_plc_per_frame_ramp_down_gain_dB; gain = powf( 10, ( ( (float) gain_dB ) / 20 ) ); @@ -2472,7 +2466,7 @@ static void ivas_spar_foa_dec_compute_ramp_down_post_matrix( { for ( b = 0; b < num_bands_out; b++ ) { - pState->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] *= post_matrix[i]; + hMdDec->mixer_mat[i][j][b + i_ts * IVAS_MAX_NUM_BANDS] *= post_matrix[i]; } } } @@ -2485,15 +2479,15 @@ static void ivas_spar_foa_dec_compute_ramp_down_post_matrix( /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_unquant_dtx_indicies() + * Function ivas_spar_unquant_dtx_indicies() * - * Unquantize spar md DYX indices + * Unquantize SPAR MD DYX indices *-----------------------------------------------------------------------------------------*/ #ifdef SPAR_HOA_DBG /* NOTE: No changes here as DTX only operates below 160kbps */ #endif -static void ivas_spar_foa_unquant_dtx_indicies( +static void ivas_spar_unquant_dtx_indicies( ivas_spar_md_t *pSpar_md, const int16_t nB, const int16_t bw, @@ -2501,35 +2495,29 @@ static void ivas_spar_foa_unquant_dtx_indicies( { int16_t i, b; int16_t q_lvl; - float **ppVal, *pVal, val; - int16_t **ppIdx, *pIdx, idx; + float val; + int16_t idx; float pr_min_max[2]; pr_min_max[0] = pSpar_md->min_max[0]; pr_min_max[1] = pSpar_md->min_max[1]; - ppVal = (float **) &pVal; - ppIdx = (int16_t **) &pIdx; - - ppVal[0] = (float *) &val; - ppIdx[0] = (int16_t *) &idx; - for ( b = 0; b < nB; b++ ) { for ( i = 0; i < FOA_CHANNELS - 1; i++ ) { q_lvl = dtx_pr_real_q_levels[ndm_per_band[bw * b] - 1][i]; - ppIdx[0][0] = pSpar_md->band_coeffs_idx[b].pred_index_re[i]; - ivas_deindex_real_index( ppIdx, q_lvl, pr_min_max[0], pr_min_max[1], ppVal, 1, 1 ); - pSpar_md->band_coeffs[b].pred_re[i] = ppVal[0][0]; + idx = pSpar_md->band_coeffs_idx[b].pred_index_re[i]; + ivas_deindex_real_index( &idx, q_lvl, pr_min_max[0], pr_min_max[1], &val, 1 ); + pSpar_md->band_coeffs[b].pred_re[i] = val; } for ( i = 0; i < FOA_CHANNELS - ndm_per_band[bw * b]; i++ ) { q_lvl = dtx_pd_real_q_levels[ndm_per_band[bw * b] - 1][i]; - ppIdx[0][0] = pSpar_md->band_coeffs_idx[b].decd_index_re[i]; - ivas_deindex_real_index( ppIdx, q_lvl, dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], ppVal, 1, 1 ); - pSpar_md->band_coeffs[b].P_re[i] = ppVal[0][0]; + idx = pSpar_md->band_coeffs_idx[b].decd_index_re[i]; + ivas_deindex_real_index( &idx, q_lvl, dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], &val, 1 ); + pSpar_md->band_coeffs[b].P_re[i] = val; } } @@ -2551,27 +2539,21 @@ static void ivas_parse_parameter_bitstream_dtx( int16_t *num_dmx_per_band, int16_t *num_dec_per_band ) { - int16_t i, j; - float **ppVal, *pVal, val; - int16_t **ppIdx, *pIdx, idx; + int16_t i, j, ndec, ndm; + float val; + int16_t idx; float pr_min_max[2]; int16_t pr_q_lvls, pr, pd, pd_q_lvls, pr_pd_bits; int16_t pr_q_lvls1, pr_q_lvls2, pr_idx1, pr_idx2, pr_pr_bits; int16_t zero_pad_bits, sid_bits_len; sid_bits_len = st0->next_bit_pos; - ppVal = (float **) &pVal; - ppIdx = (int16_t **) &pIdx; - - ppVal[0] = (float *) &val; - ppIdx[0] = (int16_t *) &idx; - pr_min_max[0] = pSpar_md->min_max[0]; pr_min_max[1] = pSpar_md->min_max[1]; for ( i = 0; i < num_bands; i++ ) { - int16_t ndec = num_dec_per_band[bw * i]; - int16_t ndm = num_dmx_per_band[bw * i]; + ndec = num_dec_per_band[bw * i]; + ndm = num_dmx_per_band[bw * i]; for ( j = 0; j < FOA_CHANNELS - 1; j++ ) { @@ -2604,16 +2586,13 @@ static void ivas_parse_parameter_bitstream_dtx( pr = (int16_t) floor( value / pd_q_lvls ); pd = value - pr * pd_q_lvls; + val = dtx_pd_real_min_max[0]; + ivas_quantise_real_values( &val, pd_q_lvls, dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], &idx, &val, 1 ); + pd = pd + idx; - ppVal[0][0] = dtx_pd_real_min_max[0]; - ivas_quantise_real_values( ppVal, pd_q_lvls, dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], ppIdx, ppVal, 1, 1 ); - - pd = pd + ppIdx[0][0]; - - ppVal[0][0] = pr_min_max[0]; - ivas_quantise_real_values( ppVal, pr_q_lvls, pr_min_max[0], pr_min_max[1], ppIdx, ppVal, 1, 1 ); - - pr = pr + ppIdx[0][0]; + val = pr_min_max[0]; + ivas_quantise_real_values( &val, pr_q_lvls, pr_min_max[0], pr_min_max[1], &idx, &val, 1 ); + pr = pr + idx; if ( ( j + 1 ) <= ndec ) { @@ -2633,17 +2612,15 @@ static void ivas_parse_parameter_bitstream_dtx( pr_idx2 = (int16_t) floor( value / pr_q_lvls1 ); pr_idx1 = value - pr_idx2 * pr_q_lvls1; + val = pr_min_max[0]; + ivas_quantise_real_values( &val, pr_q_lvls1, pr_min_max[0], pr_min_max[1], &idx, &val, 1 ); - ppVal[0][0] = pr_min_max[0]; - ivas_quantise_real_values( ppVal, pr_q_lvls1, pr_min_max[0], pr_min_max[1], ppIdx, ppVal, 1, 1 ); - - pr_idx1 += ppIdx[0][0]; - - ppVal[0][0] = pr_min_max[0]; - ivas_quantise_real_values( ppVal, pr_q_lvls2, pr_min_max[0], pr_min_max[1], ppIdx, ppVal, 1, 1 ); + pr_idx1 += idx; - pr_idx2 += ppIdx[0][0]; + val = pr_min_max[0]; + ivas_quantise_real_values( &val, pr_q_lvls2, pr_min_max[0], pr_min_max[1], &idx, &val, 1 ); + pr_idx2 += idx; pSpar_md->band_coeffs_idx[i].pred_index_re[pr_idx_1 - 1] = pr_idx1; pSpar_md->band_coeffs_idx[i].pred_index_re[pr_idx_2 - 1] = pr_idx2; } @@ -2659,7 +2636,7 @@ static void ivas_parse_parameter_bitstream_dtx( get_next_indice( st0, 1 ); } - ivas_spar_foa_unquant_dtx_indicies( pSpar_md, num_bands, bw, num_dmx_per_band ); + ivas_spar_unquant_dtx_indicies( pSpar_md, num_bands, bw, num_dmx_per_band ); return; } @@ -2668,19 +2645,18 @@ static void ivas_parse_parameter_bitstream_dtx( /*-----------------------------------------------------------------------------------------* * Function ivas_deindex_real_index() * - * deindex real index + * Deindex real index *-----------------------------------------------------------------------------------------*/ static ivas_error ivas_deindex_real_index( - int16_t **index, + const int16_t *index, const int16_t q_levels, const float min_value, const float max_value, - float **quant, - const int16_t num_ch, - const int16_t dim2 ) + float *quant, + const int16_t dim ) { - int16_t i, j; + int16_t i; float q_step; if ( q_levels == 0 ) @@ -2690,24 +2666,17 @@ static ivas_error ivas_deindex_real_index( if ( q_levels == 1 ) { - for ( i = 0; i < num_ch; i++ ) + for ( i = 0; i < dim; i++ ) { - for ( j = 0; j < dim2; j++ ) - { - quant[i][j] = 0; - } + quant[i] = 0; } } else { q_step = ( max_value - min_value ) / ( q_levels - 1 ); - - for ( i = 0; i < num_ch; i++ ) + for ( i = 0; i < dim; i++ ) { - for ( j = 0; j < dim2; j++ ) - { - quant[i][j] = index[i][j] * q_step; - } + quant[i] = index[i] * q_step; } } @@ -2723,9 +2692,9 @@ static ivas_error ivas_deindex_real_index( void ivas_spar_to_dirac( Decoder_Struct *st_ivas, - ivas_spar_foa_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ - const int16_t dtx_vad, /* i : DTX frame flag */ - const int16_t num_bands_out /* i : number of output bands */ + ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD decoder handle */ + const int16_t dtx_vad, /* i : DTX frame flag */ + const int16_t num_bands_out /* i : number of output bands */ #ifdef LBR_SBA , const int16_t bw /* i : band joining factor */ @@ -2756,23 +2725,22 @@ void ivas_spar_to_dirac( int16_t *dirac_to_spar_md_bands; int16_t enc_param_start_band; - sba_order_internal = min( st_ivas->sba_order, IVAS_MAX_SBA_ORDER ); - + sba_order_internal = min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ); start_band = 0; #ifdef LBR_SBA end_band = min( num_bands_out, SPAR_DIRAC_SPLIT_START_BAND ) / bw; hDirAC = st_ivas->hDirAC; - dirac_to_spar_md_bands = st_ivas->hSpar->hSparFoa->dirac_to_spar_md_bands; - enc_param_start_band = st_ivas->hSpar->hSparFoa->enc_param_start_band / bw; + dirac_to_spar_md_bands = st_ivas->hSpar->dirac_to_spar_md_bands; + enc_param_start_band = st_ivas->hSpar->enc_param_start_band / bw; int16_t active_w_vlbr; active_w_vlbr = ( st_ivas->hDecoderConfig->ivas_total_brate < IVAS_24k4 ) ? 1 : 0; #else end_band = min( num_bands_out, SPAR_DIRAC_SPLIT_START_BAND ); hDirAC = st_ivas->hDirAC; - dirac_to_spar_md_bands = st_ivas->hSpar->hSparFoa->dirac_to_spar_md_bands; - enc_param_start_band = st_ivas->hSpar->hSparFoa->enc_param_start_band; + dirac_to_spar_md_bands = st_ivas->hSpar->dirac_to_spar_md_bands; + enc_param_start_band = st_ivas->hSpar->enc_param_start_band; #endif if ( hDirAC != NULL ) { @@ -2937,11 +2905,12 @@ void ivas_spar_to_dirac( for ( ; band < num_bands_out / bw; band++ ) #else for ( ; band < num_bands_out; band++ ) -#endif +#endif { int16_t dirac_band_idx; dirac_band_idx = dirac_to_spar_md_bands[band] - enc_param_start_band; + #ifdef LBR_SBA int16_t num_subframes; num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; @@ -2953,7 +2922,7 @@ void ivas_spar_to_dirac( for ( block = 0; block < num_subframes; block++ ) #else for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) -#endif +#endif { if ( st_ivas->hQMetaData->q_direction->band_data[dirac_band_idx].azimuth[block] < 0.f ) { @@ -2969,13 +2938,12 @@ void ivas_spar_to_dirac( /* DirAC MD averaged over 4 subframes and converted to SPAR format similar to encoder processing */ if ( hMdDec->spar_md_cfg.nchan_transport > 1 ) { - ivas_get_spar_md_from_dirac( azi_dirac, ele_dirac, diffuseness, 1, NULL, &hMdDec->spar_md, &hMdDec->spar_md_cfg, - end_band, num_bands_out, sba_order_internal, dtx_vad, NULL + ivas_get_spar_md_from_dirac( azi_dirac, ele_dirac, diffuseness, 1, NULL, &hMdDec->spar_md, &hMdDec->spar_md_cfg, end_band, num_bands_out, ( hMdDec->spar_hoa_md_flag ) ? 1 : sba_order_internal, dtx_vad, NULL #ifdef LBR_SBA , st_ivas->hQMetaData->useLowerRes, active_w_vlbr #endif - ); + ); /* temporarily copy frame-wise prediction coefficients in DirAC bands*/ for ( pred_idx = 0; pred_idx < FOA_CHANNELS - 1; pred_idx++ ) @@ -3014,39 +2982,7 @@ void ivas_spar_to_dirac( } } #else - ivas_get_spar_md_from_dirac( azi_dirac, ele_dirac, diffuseness, MAX_PARAM_SPATIAL_SUBFRAMES, NULL, &hMdDec->spar_md, &hMdDec->spar_md_cfg, - end_band, num_bands_out, sba_order_internal, dtx_vad, NULL ); -#endif -#ifdef DEBUG_LBR_SBA // SPAR_HOA_DBG - /*for ( int b = 0; b < num_bands_out / bw; b++ ) - { - int16_t ndec = hMdDec->spar_md_cfg.num_decorr_per_band[( bw ) * b]; - int16_t ndm = hMdDec->spar_md_cfg.num_dmx_chans_per_band[( bw ) * b]; - fprintf( stdout, "\n\n Metadata PR (15x1), C(15x15), P(15x15): band %d\n", b ); - for ( int i = 0; i < ndm + ndec - 1; i++ ) - { - fprintf( stdout, "i: %d -- %.2f\t|\t", i, hMdDec->spar_md.band_coeffs[b].pred_re[i] ); - if ( i < ndec ) - { - if ( keep_planar[i] == 1 ) - { - fprintf( stdout, ">>" ); - } - else - { - fprintf( stdout, " " ); - } - for ( int j = 0; j < ndm - 1; j++ ) - { - fprintf( stdout, "%.2f\t", hMdDec->spar_md.band_coeffs[b].C_re[i][j] ); - } - fprintf( stdout, "|\t" ); - fprintf( stdout, "%.2f", hMdDec->spar_md.band_coeffs[b].P_re[i] ); - } - fprintf( stdout, "\n" ); - } - fprintf( stdout, "\n" ); - }*/ + ivas_get_spar_md_from_dirac( azi_dirac, ele_dirac, diffuseness, MAX_PARAM_SPATIAL_SUBFRAMES, NULL, &hMdDec->spar_md, &hMdDec->spar_md_cfg, end_band, num_bands_out, ( hMdDec->spar_hoa_md_flag ) ? 1 : sba_order_internal, dtx_vad, NULL ); #endif /* expand DirAC TC 20ms MD for residual channels to all subframes*/ for ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index a9ba163265d50d281a52d05157383dd7f6a6e0bf..8c27a09baf05bb2de82c968601beaceab2f45e17 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,35 +36,10 @@ #include #include "options.h" #include "cnst.h" -#include "stat_dec.h" #include "ivas_cnst.h" +#include "stat_dec.h" #include "ivas_stat_com.h" - - -/*----------------------------------------------------------------------------------* - * Output configuration for renderer (e.g. DirAC, MASA, Binaural Renderer...) - *----------------------------------------------------------------------------------*/ - -typedef struct ivas_output_setup_structure -{ - AUDIO_CONFIG output_config; - int16_t nchan_out_woLFE; /* number of output audio channels without LFE */ - int16_t ambisonics_order; - int8_t is_loudspeaker_setup; - int8_t is_planar_setup; - int8_t is_binaural_setup; - - int16_t num_lfe; - int16_t index_lfe[1]; - const float *ls_azimuth; - const float *ls_elevation; - - uint8_t separateChannelEnabled; - int16_t separateChannelIndex; - -} IVAS_OUTPUT_SETUP, *IVAS_OUTPUT_SETUP_HANDLE; - - +#include "ivas_stat_rend.h" /*----------------------------------------------------------------------------------* * DFT Stereo decoder structure *----------------------------------------------------------------------------------*/ @@ -123,7 +98,6 @@ typedef struct stereo_dft_dec_data_struct const float *win_8k; /* DFT window residual */ - /*Bands*/ int16_t band_res[STEREO_DFT_DEC_DFT_NB]; int16_t band_limits[STEREO_DFT_BAND_MAX + 1]; @@ -144,6 +118,16 @@ typedef struct stereo_dft_dec_data_struct float itd[STEREO_DFT_DEC_DFT_NB]; + float itd_xfade_step; + float itd_xfade_target; + int16_t itd_xfade_counter; + float itd_xfade_prev; + int32_t last_active_element_brate; + float ipd_xfade_target; + float ipd_xfade_step; + int16_t ipd_xfade_counter; + float ipd_xfade_prev; + /*residual prediction*/ int16_t res_pred_mode[STEREO_DFT_DEC_DFT_NB]; /* residual prediction mode: 0(off), 1(stereo filling only), 2(enhanced stereo filling) */ float res_pred_gain[STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX]; /* prediction gain for the residual HFs */ @@ -216,14 +200,16 @@ typedef struct stereo_dft_dec_data_struct float smooth_buf[SBA_DIRAC_STEREO_NUM_BANDS][SBA_DIRAC_NRG_SMOOTH_LONG + 1]; float smooth_fac[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS]; + int16_t first_frame; + float mixer_mat_smooth[2][4][2 * IVAS_MAX_NUM_BANDS]; + float g_L_prev; + float g_R_prev; + const float *max_smooth_gains, *min_smooth_gains; } STEREO_DFT_DEC_DATA, *STEREO_DFT_DEC_DATA_HANDLE; -/*----------------------------------------------------------------------------------* - * DFT Stereo mono output structure - *----------------------------------------------------------------------------------*/ - +/* DFT Stereo mono output structure */ typedef struct stereo_dft_dmx_out_data_structure { float targetGain; /* TCA gain norm applied on target (or right) channel in current frame */ @@ -253,7 +239,7 @@ typedef struct stereo_dec_cng int16_t xfade_length; /* number of frames to perform xfade */ int16_t nr_dft_frames; /* dft frame counter */ int16_t nr_corr_frames; /* correlation frame counter */ - int16_t nr_sid_frames; /* sid frame counter */ + int16_t nr_sid_frames; /* SID frame counter */ int16_t last_act_element_mode; /* Element mode of last active frame */ float olapBufferSynth22[FFTLEN]; /* overlap buffer for secondary channel CNA */ int16_t flag_cna_fade; /* flag enabling CNA fade out */ @@ -320,10 +306,9 @@ typedef struct stereo_mdct_dec_data_structure int16_t prev_ms_mask[NB_DIV][MAX_SFB]; float lastCoh; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT int16_t noise_seeds_channels[CPE_CHANNELS]; int16_t noise_seed_common; -#endif + int16_t isSBAStereoMode; } STEREO_MDCT_DEC_DATA, *STEREO_MDCT_DEC_DATA_HANDLE; @@ -344,10 +329,8 @@ typedef struct stereo_tca_dec_data_structure int16_t corrLagStats; /* corr lag stats in current frame */ int16_t prevCorrLagStats; /* corr lag stats in previous frame */ -#ifdef DEC_ICA_DELAY_INTERP int16_t interp_dec_prevNCShift; /* NC Shift in previous frame */ int16_t interp_dec_switch_to_zero_diff; /* switch flag for interpolation */ -#endif float memChanL[L_DEC_MEM_LEN_ICA]; /* left channel input to correct at the cross-over */ float memChanR[L_DEC_MEM_LEN_ICA]; /* right channel input to correct at the cross-over */ @@ -399,6 +382,21 @@ typedef struct stereo_icbwe_dec_data_structure } STEREO_ICBWE_DEC_DATA, *STEREO_ICBWE_DEC_HANDLE; +/*----------------------------------------------------------------------------------* + * ISM DTX structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + int16_t dtx_flag; + int16_t sce_id_dtx; + +#ifdef DISCRETE_ISM_DTX_CNG + int16_t ism_dtx_hangover_cnt; /* hangover counter for ISM DTX decoder */ +#endif + +} ISM_DTX_DATA_DEC; + /*----------------------------------------------------------------------------------* * DirAC decoder structure *----------------------------------------------------------------------------------*/ @@ -431,6 +429,7 @@ typedef struct dirac_dec_stack_mem float *reference_power; float *onset_filter; + } DIRAC_DEC_STACK_MEM, *DIRAC_DEC_STACK_MEM_HANDLE; typedef struct param_ism_rendering @@ -660,14 +659,13 @@ typedef struct ivas_dirac_dec_data_structure int16_t spar_to_dirac_write_idx; int16_t dirac_md_buffer_length; - int16_t numSimultaneousDirections; /* 1 or 2 */ DIFFUSE_DISTRIBUTION_HANDLE hDiffuseDist; /*Parameter estimation*/ int16_t index_buffer_intensity; float *buffer_intensity_real[DIRAC_NUM_DIMS][DIRAC_NO_COL_AVG_DIFF]; - float buffer_energy[DIRAC_NO_COL_AVG_DIFF * CLDFB_NO_CHANNELS_MAX]; + float *buffer_energy; /*Decoder parameters */ /*Prototypes*/ @@ -699,7 +697,6 @@ typedef struct ivas_dirac_dec_data_structure float *proto_frame_dec_f; DIRAC_DEC_STACK_MEM stack_mem; - MASA_STEREO_TYPE_DETECT *masa_stereo_type_detect; int16_t num_ele_spk_no_diffuse_rendering; @@ -716,6 +713,7 @@ typedef struct ivas_dirac_dec_data_structure PARAM_ISM_RENDERING_HANDLE hParamIsmRendering; IVAS_FB_MIXER_HANDLE hFbMdft; int16_t dirac_to_spar_md_bands[DIRAC_MAX_NBANDS]; + } DIRAC_DEC_DATA, *DIRAC_DEC_HANDLE; @@ -780,7 +778,7 @@ typedef struct ivas_param_mc_dec_data_structure * SPAR decoder structures *------------------------------------------------------------------------------------------*/ -/* SPAR FOA MD structure */ +/* SPAR MD structure */ typedef struct ivas_spar_dec_matrices_t { float ***C_re; @@ -788,7 +786,7 @@ typedef struct ivas_spar_dec_matrices_t } ivas_spar_dec_matrices_t; -typedef struct ivas_spar_foa_md_dec_state_t +typedef struct ivas_spar_md_dec_state_t { ivas_spar_md_t spar_md; ivas_spar_md_prev_t spar_md_prev; @@ -805,13 +803,14 @@ typedef struct ivas_spar_foa_md_dec_state_t float ***mixer_mat; /*TODO : reuse hFbMixer->prior_mixer for this as that buffer is unused in decoder with FB_HARMONIZATION*/ float mixer_mat_prev[MAX_PARAM_SPATIAL_SUBFRAMES + 1][IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH][IVAS_MAX_NUM_BANDS]; - ivas_spar_foa_md_com_cfg spar_md_cfg; + ivas_spar_md_com_cfg spar_md_cfg; ivas_arith_coeffs_t arith_coeffs; ivas_huff_coeffs_t huff_coeffs; int16_t table_idx; int16_t dtx_vad; + int16_t spar_hoa_md_flag; -} ivas_spar_foa_md_dec_state_t; +} ivas_spar_md_dec_state_t; /* AGC structure */ @@ -830,28 +829,6 @@ typedef struct ivas_agc_dec_state_t } ivas_agc_dec_state_t; -/* TD decorr */ -typedef struct ivas_td_decorr_APD_filt_state_t -{ - int16_t order[IVAS_MAX_DECORR_APD_SECTIONS]; - int16_t idx[IVAS_MAX_DECORR_APD_SECTIONS]; - float coeffs[IVAS_MAX_DECORR_APD_SECTIONS]; - float *state[IVAS_MAX_DECORR_APD_SECTIONS]; - -} ivas_td_decorr_APD_filt_state_t; - -typedef struct ivas_td_decorr_state_t -{ - ivas_trans_det_state_t *pTrans_det; - float *look_ahead_buf; - ivas_td_decorr_APD_filt_state_t APD_filt_state[IVAS_MAX_DECORR_CHS]; - - int16_t num_apd_outputs; - int16_t num_apd_sections; - int16_t ducking_flag; - -} ivas_td_decorr_state_t; - /* PCA structure */ typedef struct { @@ -865,26 +842,24 @@ typedef struct } PCA_DEC_STATE; -/* SPAR FOA structures */ -typedef struct ivas_spar_foa_dec_state_t +/* main SPAR decoder structure */ +typedef struct ivas_spar_dec_lib_t { ivas_td_decorr_state_t *hTdDecorr; - ivas_spar_foa_md_dec_state_t *hMdDec; + ivas_spar_md_dec_state_t *hMdDec; IVAS_FB_MIXER_HANDLE hFbMixer; int16_t AGC_flag; ivas_agc_dec_state_t *hAgcDec; PCA_DEC_STATE *hPCA; int16_t dirac_to_spar_md_bands[DIRAC_MAX_NBANDS]; int16_t enc_param_start_band; - int32_t core_nominal_brate; /* Nominal bitrate for core coding */ - int32_t i_subframe; -} ivas_spar_foa_dec_state_t; + int16_t i_subframe; -/* main SPAR decoder structure */ -typedef struct ivas_spar_dec_lib_t -{ - ivas_spar_foa_dec_state_t *hSparFoa; +#ifdef DEBUG_SBA_AUDIO_DUMP + int16_t numOutChannels; + int16_t pca_ingest_channels; +#endif } SPAR_DEC_DATA, *SPAR_DEC_HANDLE; @@ -979,87 +954,49 @@ typedef struct mct_dec_data_structure int16_t chBitRatios[MCT_MAX_CHANNELS]; int16_t lowE_ch[MCT_MAX_CHANNELS]; /* note: pointer to local parameter */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE int16_t LFE_off; +#endif uint16_t mc_global_ild[MCT_MAX_CHANNELS]; /* note: pointer to local parameter */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE int16_t num_lfe; - +#endif } MCT_DEC_DATA, *MCT_DEC_HANDLE; /*----------------------------------------------------------------------------------* - * EFAP structures + * LFE decoder structure *----------------------------------------------------------------------------------*/ -typedef struct EFAP_VERTEX -{ - float azi; /* azimuth of the loudspeaker */ - float ele; /* elevation of the loudspeaker */ - float pos[3]; /* [x y z] cartesian coordinate vector */ - int16_t idx; /* integer, that corresponds to the first index for the LS in the 1D output */ - int16_t isNaN; /* used to indicate if the vertex is a virtual speaker */ - EFAP_VTX_DMX_TYPE dmxType; /* virtual speaker downmix type */ -} EFAP_VERTEX; - -typedef struct EFAP_VERTEX_DATA -{ - EFAP_VERTEX *vertexArray; /* Array of vertices */ - int16_t numVtx; /* Number of vertices */ - int16_t *vtxOrder; /* Array that indicates the order of the vertex ranked by increasing azimuth */ - -} EFAP_VERTEX_DATA; - -typedef struct EFAP_POLYSET -{ - int16_t chan[EFAP_MAX_CHAN_NUM]; /* An array indicating the loudspeaker index of the polygon vertices */ - int16_t isNaN[EFAP_MAX_CHAN_NUM]; /* Indicates if one of the vertices isNaN */ - int16_t numChan; /* An integer between 0 and EFAP_MAX_CHAN_NUM corresponding to the number of vertices of the polygon */ - float polyAzi[EFAP_MAX_CHAN_NUM]; /* An array (same length as "chan"), with the azimuth of the channels */ - float polyEle[EFAP_MAX_CHAN_NUM]; /* An array (same length as "chan"), with the elevation of the channels */ - -} EFAP_POLYSET; - -typedef struct EFAP_LS_TRIANGLE +typedef struct ivas_lfe_dec_data_structure { - int16_t LS[3]; /* Array indicating the loudspeaker index of the triangle vertices */ + ivas_filters_process_state_t filter_state; + LFE_WINDOW_HANDLE pWindow_state; + const uint16_t *cum_freq_models[IVAS_MAX_NUM_QUANT_STRATS][IVAS_MAX_NUM_DCT_COEF_GROUPS]; + int16_t lfe_dec_indices_coeffs_tbl[IVAS_MAX_NUM_QUANT_STRATS][IVAS_MAX_NUM_DCT_COEF_GROUPS]; + float lfe_block_delay_s; + int16_t lfe_prior_buf_len; +#ifndef ISSUE_24_CLEANUP_MCT_LFE + float *prior_out_buffer; -} EFAP_LS_TRIANGLE; + float *prevsynth_buf; +#else + float prior_out_buffer[L_FRAME48k]; -typedef struct EFAP_POLYSET_DATA -{ - EFAP_POLYSET polysetArray[EFAP_MAX_POLY_SET]; /* Array of polygons */ - int16_t numPoly; /* Number of polygons */ - EFAP_LS_TRIANGLE triArray[EFAP_MAX_POLY_SET]; /* Array of triangles */ - int16_t numTri; /* Number of triangles */ + float prevsynth_buf[LFE_PLC_BUFLEN]; +#endif + float *lfe_delay_buf; + int16_t lfe_addl_delay; + int16_t bfi_count; -} EFAP_POLYSET_DATA; +} LFE_DEC_DATA, *LFE_DEC_HANDLE; -typedef struct EFAP -{ - int16_t numSpk; /* Number of loudspeakers */ - float *aziSpk; /* Loudspeaker azimuths */ - float *eleSpk; /* Loudspeaker elevations */ - EFAP_VERTEX_DATA vtxData; /* Vertex Data, contains all the data concerning the vertex */ - EFAP_POLYSET_DATA polyData; /* Polygon data */ - float **dmTranspose; /* Downmix Matrix used for redistributing the energy of ghosts LS and its transpose */ - float *bufferLong; /* tmp buffer that will be given as a parameter for computing the gain; this is a 1D array of length numVtx */ - float *bufferShort; /* tmp buffer that will be given as a parameter for computing the gain; this is the result of downMixMatrix*bufferLong, length is numSpk */ - int16_t numTot; /* Total number of real + ghost loudspeakers, used later for freeing memory */ - -} EFAP, *EFAP_HANDLE; +// Note: the following structures are used only in lib_dec but this would likely change in the future /*----------------------------------------------------------------------------------* * VBAP structures *----------------------------------------------------------------------------------*/ -enum SpeakerNodeGroup -{ - SPEAKER_NODE_BOTTOM_HALF, - SPEAKER_NODE_HORIZONTAL, - SPEAKER_NODE_TOP_HALF, - SPEAKER_NODE_BACK, - SPEAKER_NODE_ALL -}; - /* Defines a single virtual surface triplet of loudspeakers * with a precalculated inverse matrix */ typedef struct vbap_vs_triplet_structure @@ -1069,15 +1006,6 @@ typedef struct vbap_vs_triplet_structure } VBAP_VS_TRIPLET; -/* Defines a single speaker node */ -typedef struct vbap_speaker_node_structure -{ - float azi_deg; - float ele_deg; - float unit_vec[3]; - enum SpeakerNodeGroup group; - -} VBAP_SPEAKER_NODE; /* Storage structure for fast runtime triplet search */ typedef struct triplet_search_structure @@ -1088,6 +1016,7 @@ typedef struct triplet_search_structure } VBAP_SEARCH_STRUCT; + /* VBAP data structure. Contains the formed virtual surface arrangement * and supporting data. */ typedef struct vbap_data_structure { @@ -1116,58 +1045,30 @@ typedef struct renderer_struct } ISM_RENDERER_DATA, *ISM_RENDERER_HANDLE; -/*----------------------------------------------------------------------------------* - * Loudspeaker Configuration Conversion structure - *----------------------------------------------------------------------------------*/ - -typedef struct ivas_LS_setupconversion_struct -{ - float *dmxMtx[MAX_OUTPUT_CHANNELS]; - float *targetEnergyPrev[MAX_OUTPUT_CHANNELS]; - float *dmxEnergyPrev[MAX_OUTPUT_CHANNELS]; - int16_t sfbOffset[MAX_SFB + 2]; - int16_t sfbCnt; - -} LSSETUP_CONVERSION_STRUCT, *LSSETUP_CONVERSION_HANDLE; - - -typedef struct ivas_LS_setupconversion_matrix -{ - int16_t index; - float value; -} LS_CONVERSION_MATRIX; - -typedef struct ivas_LS_setupconversion_mapping -{ - AUDIO_CONFIG input_config; - AUDIO_CONFIG output_config; - const LS_CONVERSION_MATRIX *conversion_matrix; -} LS_CONVERSION_MAPPING; -typedef struct ivas_mono_downmix_renderer_struct +/* Fastconv binaural data structure */ +typedef struct ivas_binaural_rendering_struct { - float inputEnergy[CLDFB_NO_CHANNELS_MAX]; - float protoEnergy[CLDFB_NO_CHANNELS_MAX]; - -} MONO_DOWNMIX_RENDERER_STRUCT, *MONO_DOWNMIX_RENDERER_HANDLE; - + /* Common variables for all modules */ + IVAS_OUTPUT_SETUP_HANDLE hInputSetup; /* pointer to input spatial format for binaural renderer*/ + EFAP_HANDLE hEFAPdata; /* EFAP structure*/ + float *hoa_dec_mtx; /* pointer to HOA decoder mtx */ + int8_t rotInCldfb; /* Flag to enable rotation within bin Renderer in CLDFB*/ + int16_t max_band; /* band upto which rendering is performed */ + int16_t conv_band; /* band upto which convolution in cldfb domain is performed */ + int16_t timeSlots; /* number of time slots of binaural renderer */ + int16_t nInChannels; /* number input channels */ + int8_t render_lfe; /* Flag to render LFE in binaural rendering*/ + IVAS_FORMAT ivas_format; /* format; corresponds to st_ivas->ivas_format, unless the signal gets transormed to a different domain for rendering */ -/*----------------------------------------------------------------------------------* - * Custom Loudspeaker configuration structure - *----------------------------------------------------------------------------------*/ + /* Convolution module structure */ + BINRENDERER_CONV_MODULE_HANDLE hBinRenConvModule; -typedef struct ivas_LS_setup_custom -{ - int16_t is_planar_setup; /* flag to indicate if setup is planar or not */ - int16_t num_spk; /* number of custom loudspeakers */ - float ls_azimuth[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker azimuths */ - float ls_elevation[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker elevations */ - int16_t num_lfe; /* number of LFE channels */ - int16_t lfe_idx[MAX_OUTPUT_CHANNELS]; /* index for LFE channel insertion */ - int16_t separate_ch_found; /* flag to indicate if a center channel was found */ - float separate_ch_gains[MAX_OUTPUT_CHANNELS]; /* gains to pan McMASA separateChannel in case no center channel is present */ + /* Variables related to reverberator module */ + float earlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; + REVERB_STRUCT_HANDLE hReverb; -} LSSETUP_CUSTOM_STRUCT, *LSSETUP_CUSTOM_HANDLE; +} BINAURAL_RENDERER, *BINAURAL_RENDERER_HANDLE; /*----------------------------------------------------------------------------------* @@ -1207,11 +1108,29 @@ typedef struct ivas_mcmasa_lfe_synth_struct } MCMASA_LFE_SYNTH_DATA, *MCMASA_LFE_SYNTH_DATA_HANDLE; +#ifdef FIX_350_MASA_DELAY_COMP +typedef struct ivas_masa_decoder_ext_out_meta_struct +{ + MASA_DECRIPTIVE_META descriptiveMeta; + + uint16_t directionIndex[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + uint8_t directToTotalRatio[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + uint8_t spreadCoherence[MASA_MAXIMUM_DIRECTIONS][MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + + uint8_t surroundCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + uint8_t diffuseToTotalRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + +} MASA_DECODER_EXT_OUT_META; +#endif + typedef struct ivas_masa_decoder_data_struct { int16_t band_mapping[MASA_FREQUENCY_BANDS + 1]; SPHERICAL_GRID_DATA *sph_grid16; +#ifdef FIX_350_MASA_DELAY_COMP + MASA_DECODER_EXT_OUT_META *extOutMeta; +#endif float dir_decode_quality; } MASA_DECODER_DATA; @@ -1224,679 +1143,6 @@ typedef struct ivas_masa_decoder_struct } MASA_DECODER, *MASA_DECODER_HANDLE; - -/*----------------------------------------------------------------------------------* - * Binaural Rendering structure - *----------------------------------------------------------------------------------*/ - -/* Binaural reverberator structure */ -typedef struct ivas_binaural_reverb_struct -{ - float *loopBufReal[CLDFB_NO_CHANNELS_MAX]; - float *loopBufImag[CLDFB_NO_CHANNELS_MAX]; - float preDelayBufferReal[REVERB_PREDELAY_MAX + 1][CLDFB_NO_CHANNELS_MAX]; - float preDelayBufferImag[REVERB_PREDELAY_MAX + 1][CLDFB_NO_CHANNELS_MAX]; - float **tapPointersReal[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; - float **tapPointersImag[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; - - float binauralCoherenceCrossmixGains[CLDFB_NO_CHANNELS_MAX]; - float binauralCoherenceDirectGains[CLDFB_NO_CHANNELS_MAX]; - float reverbEqGains[CLDFB_NO_CHANNELS_MAX]; - float loopAttenuationFactor[CLDFB_NO_CHANNELS_MAX]; - - float *outputBufferReal[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; - float *outputBufferImag[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; - - int16_t numBins; - - int16_t useBinauralCoherence; - int16_t loopBufLength[CLDFB_NO_CHANNELS_MAX]; - int16_t loopBufLengthMax[CLDFB_NO_CHANNELS_MAX]; - int16_t preDelayBufferIndex; - int16_t preDelayBufferLength; - - int16_t taps[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; - int16_t *tapPhaseShiftType[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; - - int16_t blockSize; - uint32_t binRend_RandNext; - int16_t highestBinauralCoherenceBin; - - float dmxmtx[BINAURAL_CHANNELS][MAX_OUTPUT_CHANNELS]; - float foa_enc[MAX_OUTPUT_CHANNELS][FOA_CHANNELS]; - -} REVERB_STRUCT, *REVERB_STRUCT_HANDLE; - -/* Parametric binaural data structure */ -typedef struct ivas_dirac_dec_binaural_data_structure -{ - float ChEnePrev[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float ChCrossRePrev[CLDFB_NO_CHANNELS_MAX]; - float ChCrossImPrev[CLDFB_NO_CHANNELS_MAX]; - float ChEne[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float ChCrossRe[CLDFB_NO_CHANNELS_MAX]; - float ChCrossIm[CLDFB_NO_CHANNELS_MAX]; - float ChEneOutPrev[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float ChCrossReOutPrev[CLDFB_NO_CHANNELS_MAX]; - float ChCrossImOutPrev[CLDFB_NO_CHANNELS_MAX]; - float ChEneOut[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float ChCrossReOut[CLDFB_NO_CHANNELS_MAX]; - float ChCrossImOut[CLDFB_NO_CHANNELS_MAX]; - float processMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; /* +1 refers to SeparateChannel */ - float processMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; - float processMtxDecRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float processMtxDecIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float diffuseFieldCoherence[CLDFB_NO_CHANNELS_MAX]; - float diffuseFieldCoherenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS]; - float diffuseFieldCoherenceY[BINAURAL_COHERENCE_DIFFERENCE_BINS]; - float diffuseFieldCoherenceZ[BINAURAL_COHERENCE_DIFFERENCE_BINS]; - float earlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; - REVERB_STRUCT_HANDLE hReverb; - uint8_t renderStereoOutputInsteadOfBinaural; - float frameMeanDiffuseness[CLDFB_NO_CHANNELS_MAX]; - float processMtxRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; - float processMtxImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; - float processMtxDecRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float processMtxDecImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - uint16_t useSubframeMode; /* 0 = process in 20 ms frames, 1 = process in 5 ms subframes */ - uint16_t useTdDecorr; - ivas_td_decorr_state_t *hTdDecorr; - -} DIRAC_DEC_BIN_DATA, *DIRAC_DEC_BIN_HANDLE; - -typedef struct ivas_binaural_rendering_conv_module_struct -{ - const float *filterTapsLeftReal[CLDFB_NO_CHANNELS_MAX][MAX_OUTPUT_CHANNELS]; - const float *filterTapsLeftImag[CLDFB_NO_CHANNELS_MAX][MAX_OUTPUT_CHANNELS]; - const float *filterTapsRightReal[CLDFB_NO_CHANNELS_MAX][MAX_OUTPUT_CHANNELS]; - const float *filterTapsRightImag[CLDFB_NO_CHANNELS_MAX][MAX_OUTPUT_CHANNELS]; - - float filterStatesLeftReal[BINAURAL_CONVBANDS][MAX_OUTPUT_CHANNELS][BINAURAL_NTAPS_MAX]; - float filterStatesLeftImag[BINAURAL_CONVBANDS][MAX_OUTPUT_CHANNELS][BINAURAL_NTAPS_MAX]; - - int16_t numTapsArray[BINAURAL_CONVBANDS]; - int16_t numTaps; - -} BINRENDERER_CONV_MODULE, *BINRENDERER_CONV_MODULE_HANDLE; - -/* Fastconv binaural data structure */ -typedef struct ivas_binaural_rendering_struct -{ - /* Common variables for all modules */ - IVAS_OUTPUT_SETUP_HANDLE hInputSetup; /* pointer to input spatial format for binaural renderer*/ - EFAP_HANDLE hEFAPdata; /* EFAP structure*/ - float *hoa_dec_mtx; /* pointer to hoa decoder mtx */ - int8_t rotInCldfb; /* Flag to enable rotation within bin Renderer in CLDFB*/ - int16_t max_band; /* band upto which rendering is performed */ - int16_t conv_band; /* band upto which convolution in cldfb domain is performed */ - int16_t timeSlots; /* number of time slots of binaural renderer */ - int16_t nInChannels; /* number input channels */ - int8_t render_lfe; /* Flag to render LFE in binaural rendering*/ - IVAS_FORMAT ivas_format; /* format; corresponds to st_ivas->ivas_format, unless the signal gets transormed to a different domain for rendering */ - - /* Convolution module structure */ - BINRENDERER_CONV_MODULE_HANDLE hBinRenConvModule; - - /* Variables related to reverb module */ - float earlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; - REVERB_STRUCT_HANDLE hReverb; - -} BINAURAL_RENDERER, *BINAURAL_RENDERER_HANDLE; - - -/*----------------------------------------------------------------------------------* - * Head tracking data structure - *----------------------------------------------------------------------------------*/ - -/* Quaternion type for head orientation */ -typedef struct Quaternion_struct -{ - float w, x, y, z; - -} Quaternion; - -typedef struct ivas_binaural_head_track_struct -{ - int16_t num_quaternions; - Quaternion Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES]; - float Rmat[3][3]; - float Rmat_prev[3][3]; - - uint8_t lrSwitchedNext; - uint8_t lrSwitchedCurrent; - float lrSwitchInterpVal; - - int16_t shd_rot_max_order; - -} HEAD_TRACK_DATA, *HEAD_TRACK_DATA_HANDLE; - - -/*----------------------------------------------------------------------------------* - * TD ISm Object Renderer structure - *----------------------------------------------------------------------------------*/ - -typedef struct -{ - SFX_OpMode_t OpMode; /* Operating mode. This effect can only be TRANSIENT or OFF. */ - int16_t TurningOffEffect; /* Flag showing if the effect is being turned off. */ - int16_t TurningOnEffect; /* Flag showing if the effect is being turned on. */ - int16_t InitializeParams; /* Flag showing if parameters should be initialized the next SetParam call. */ - int16_t FirstUpdate; /* Flag showing if it SetParams has only been called once (TRUE) or more (FALSE). */ - - int32_t TotNoOfOutputSamples; /* The total number of output samples produced since last SetParam call. */ - int32_t MaxTargetTime; /* The maximum allowed target time. Also used for turning the effect on or off. */ - int32_t MaxBlockLength; /* The maximum block length */ - - int16_t TargetTime; /* Time left until the parameters should have reached the new parameters values. */ - float ItdIncrForResampling; /* Resampling factor for adjusting the ITD. */ - float *LeftOldBuffer; /* Buffer with old samples for the Resampling function */ - int16_t NoOfLeftOldBufferSamples; /* Number of samples in LeftOldBuffer */ - float Left_Tf; /* The left fractional delay. */ - float *RightOldBuffer; /* Buffer with old samples for the Resampling function */ - int16_t NoOfRightOldBufferSamples; /* Number of samples in RightOldBuffer */ - float ResampledBufferLeft[SFX_SPAT_BIN_MAX_NO_OF_OUTPUT_SAMPLES + SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1]; /* Buffers getting the resampled output and having the old samples used for HR-filtering */ - float ResampledBufferRight[SFX_SPAT_BIN_MAX_NO_OF_OUTPUT_SAMPLES + SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1]; - int16_t TransientTime; /* Transient time when turning off the effect */ - - int16_t FilterLength; /* HR-filter length */ - - /* HR-filters */ - float *LeftFilter_p; /* Pointer to left filter */ - float *LeftFilterIncr_p; /* Left filter adjustment step */ - float *RightFilter_p; /* Pointer to right filter */ - float *RightFilterIncr_p; /* Right filter adjustment step */ - -#ifdef TDREND_HRTF_TABLE_METHODS - int16_t HrFilterInterpOn; /* Indicates whether to interpolate filter from previous frame */ - float LeftFilterStored[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; /* Stored previous filter for interpolation */ - float RightFilterStored[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; /* Stored previous filter for interpolation */ -#endif - -} SFX_SpatBin_t; - -/* Container struct for setting new parameters in SFX_SpatBin */ -typedef struct -{ - int16_t TurnOn; - int16_t Reset; - /* Rendering parameters */ - float Itd; - int16_t FilterLength; - float *LeftFilter_p; - float *RightFilter_p; - float LeftVolume; - float RightVolume; - -} SFX_SpatBin_Params_t; - -typedef struct TDREND_LIST_Item_s -{ - int16_t Ind; /* Index number of item */ - void *Data_p; /* Pointer to the item data struct */ - struct TDREND_LIST_Item_s *Prev_p; /* Pointer to the prev item */ - struct TDREND_LIST_Item_s *Next_p; /* Pointer to the next item */ - -} TDREND_LIST_Item_t; - - -typedef struct -{ - int16_t modelROM; /* Flag that indicates that the model resides in ROM (controls init/dealloc). */ - int16_t UseItdModel; /* Controls whether ITD model is used. */ - int16_t SplineDegree; /* Degree of the spline functions */ - int16_t K; /* Length of filter */ - int16_t elevDim2; - int16_t elevDim3; - int16_t AlphaN; /* Number of rows in Alpha matrices */ - int16_t num_unique_azim_splines; - int16_t elevSegSamples; - - int16_t elevBsLen[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - int16_t elevBsStart[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - const int16_t *azimDim2; - const int16_t *azimDim3; - const int16_t *azim_start_idx; - const int16_t *azimSegSamples; - const int16_t *azimShapeIdx; - const int16_t *azimShapeSampFactor; - - const float *elevKSeq; /* Array, N x elevDim2 x elevDim3 */ - const float *AlphaL; /* Array, size AlphaN x K */ - const float *AlphaR; /* Array, size AlphaN x K */ - const float *elevBsShape; - float **azimKSeq; /* Array, length azimDim3+1 */ - const float **azimBsShape; - - int16_t azimDim3Max; - int16_t iSecFirst[HRTF_MODEL_N_SECTIONS]; /* Indices for start of sections */ - int16_t iSecLast[HRTF_MODEL_N_SECTIONS]; /* Indices for end of sections */ - const float *EL; /* Array, size (AlphaN*HRTF_MODEL_N_SECTIONS) */ - const float *ER; /* Array, size (AlphaN*HRTF_MODEL_N_SECTIONS) */ - - /* Pointers for allocation of dynamic memory */ - float *AlphaL_dyn; - float *AlphaR_dyn; - float *EL_dyn; - float *ER_dyn; - float *elevBsShape_dyn; - float *elevKSeq_dyn; - int16_t *azimDim2_dyn; - int16_t *azimDim3_dyn; - int16_t *azim_start_idx_dyn; - int16_t *azimSegSamples_dyn; - int16_t *azimShapeIdx_dyn; - int16_t *azimShapeSampFactor_dyn; - float **azimBsShape_dyn; - -} ModelParams_t; - -typedef struct -{ - int16_t N; /* Polynomial degree */ - - int16_t elevDim2; - int16_t elevDim3; - const float *elevKSeq; /* Array, length elevDim3-2 */ - int16_t azimDim2; - int16_t azimDim3; - const float *azimKSeq; /* Array, length azimDim3-2 */ - const float *W; /* Array, size (elevDim3*azimDim3) x K */ - - int16_t azimBsLen[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - int16_t azimBsStart[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - const float *azimBsShape; - int16_t azimSegSamples; - - int16_t elevBsLen[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - int16_t elevBsStart[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - const float *elevBsShape; - int16_t elevSegSamples; - float resamp_factor; - - /* Pointers for allocation of dynamic memory */ - float *elevKSeq_dyn; - float *azimKSeq_dyn; - float *W_dyn; - float *azimBsShape_dyn; - float *elevBsShape_dyn; -} ModelParamsITD_t; - -typedef struct -{ - float val; - int16_t i; - -} ValueIndex_t; - -/* Shared memory for use when evaluating BSpline HR filter model*/ -typedef struct -{ - float BM[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - ValueIndex_t BMEnergiesL[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - ValueIndex_t BMEnergiesR[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - int16_t UseIndsL[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - int16_t UseIndsR[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - float *hrfModL; - float *hrfModR; - float elevBfVec[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - float azimBfVec[HRTF_MODEL_BSPLINE_NUM_COEFFS][HRTF_MODEL_BSPLINE_NUM_COEFFS]; - float BM_ITD[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; - float elevBfVecITD[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - float azimBfVecITD[HRTF_MODEL_BSPLINE_NUM_COEFFS]; - float itdMod; - -} ModelEval_t; - -/* Mixer listener */ -typedef struct -{ - int16_t PoseUpdated; - float Pos[3]; - float Front[3]; - float Up[3]; - float Right[3]; - - int16_t VelUpdated; - float Vel[3]; - -} TDREND_MIX_Listener_t; - -/* HR filter */ -typedef struct TDREND_HRFILT_FiltSet_struct -{ - int32_t SampleRate; /* Sample rate of the HR filter */ - int16_t NumPos; - int16_t NumElev; - float Dist; - float *ItdSet_p; - int16_t FiltLength; - float *Azim_p; - float *Elev_p; - float *ItdSetNominal_p; - float *LeftFiltSet_p; - float *RightFiltSet_p; -#ifdef TDREND_HRTF_TABLE_METHODS - int16_t *AzimStartIdx_p; - int16_t *NumAzim_p; - float *ElevFull_p; - float ElevIncr; -#endif - ModelParams_t ModelParams; - ModelEval_t ModelEval; - ModelParamsITD_t ModelParamsITD; - TDREND_HRFILT_Method_t FilterMethod; /* HR filtering method */ - -} TDREND_HRFILT_FiltSet_t; - - -/* Distance attenuation */ -typedef struct -{ - TDREND_DistAttenModel_t DistAttenModel; - float RefDist; - float MaxDist; - float RollOffFactor; - -} TDREND_DistAtten_t; - -/* Directional attenuation */ -typedef struct -{ - float ConeInnerAngle; - float ConeOuterAngle; - float ConeOuterGain; - -} TDREND_DirAtten_t; - -/* Mixer spatial specification */ -typedef struct -{ - int16_t UseCommonDistAttenModel; /* Common distance attenuation model flag */ - TDREND_DistAttenModel_t DistAttenModel; /* Distance attenuation model */ - -} TDREND_MixSpatSpec_t; - - -typedef struct TDREND_SRC_REND_s -{ - int16_t InputAvailable; - TDREND_PlayStatus_t PlayStatus; - - /* Gains */ - int16_t SrcGainUpdated; - float SrcGain_p[SPAT_BIN_MAX_INPUT_CHANNELS]; - float SrcGainMin_p[SPAT_BIN_MAX_INPUT_CHANNELS]; - float SrcGainMax_p[SPAT_BIN_MAX_INPUT_CHANNELS]; - float DirGain_p[SPAT_BIN_MAX_INPUT_CHANNELS]; - float DistGain_p[SPAT_BIN_MAX_INPUT_CHANNELS]; - - /* HR filtering parameters */ - SFX_SpatBin_t *SfxSpatBin_p; - -} TDREND_SRC_REND_t; - - -/* Source spatial parameters */ -typedef struct -{ - int16_t Updated; - TDREND_PosType_t PosType; - float Pos_p[3 * SPAT_BIN_MAX_INPUT_CHANNELS]; - float Front_p[3 * SPAT_BIN_MAX_INPUT_CHANNELS]; - int16_t DirAttenEnabled; - TDREND_DirAtten_t DirAtten; - int16_t DistAttenEnabled; - TDREND_DistAtten_t DistAtten; - -} TDREND_SRC_SPATIAL_t; - -typedef struct -{ - float *InputFrame_p; /* Input frame pointer */ - TDREND_SRC_SPATIAL_t *SrcSpatial_p; - TDREND_SRC_REND_t *SrcRend_p; - -} TDREND_SRC_t; - -/* Top level TD binaural renderer handle */ -typedef struct ivas_binaural_td_rendering_struct -{ - TDREND_MixSpatSpec_t *TdRend_MixSpatSpec_p; - TDREND_DirAtten_t *DirAtten_p; - int16_t NumOfSrcs; - int16_t MaxSrcInd; - - TDREND_SRC_t *Sources[MAX_NUM_TDREND_CHANNELS]; - - float Gain; /* Mixer gain */ - TDREND_MIX_Listener_t *Listener_p; /* The virtual listener */ - TDREND_HRFILT_FiltSet_t *HrFiltSet_p; /* HR filter set */ - - int16_t UseCommonDistAttenModel; /* Use common dist atten model (TRUE/FALSE) */ - int16_t DistAttenEnabled; /* (TRUE/FALSE) */ - TDREND_DistAttenModel_t DistAttenModel; /* Common distance attenuation model */ - -} BINAURAL_TD_OBJECT_RENDERER, *BINAURAL_TD_OBJECT_RENDERER_HANDLE; - - -/*------------------------------------------------------------------------------------------* - * Crend structures - *------------------------------------------------------------------------------------------*/ - -typedef struct ivas_hrtfs_structure -{ - float *pOut_to_bin_re[IVAS_MAX_NUM_CH][BINAURAL_CHANNELS]; - float *pOut_to_bin_im[IVAS_MAX_NUM_CH][BINAURAL_CHANNELS]; - float *pOut_to_bin_diffuse_re[BINAURAL_CHANNELS]; - float *pOut_to_bin_diffuse_im[BINAURAL_CHANNELS]; - float latency_s; - uint16_t num_iterations[IVAS_MAX_NUM_CH][BINAURAL_CHANNELS]; - uint16_t num_iterations_diffuse[BINAURAL_CHANNELS]; - uint16_t *pIndex_frequency_max[IVAS_MAX_NUM_CH][BINAURAL_CHANNELS]; - uint16_t *pIndex_frequency_max_diffuse[BINAURAL_CHANNELS]; - uint16_t index_frequency_max_diffuse; - int16_t max_num_ir; - int16_t max_num_iterations; - float inv_diffuse_weight[IVAS_MAX_NUM_CH]; /* inverse diffuse weights array, access one inverse weight by pInvDiffuseWeight[channel] */ - float gain_lfe; - -} HRTFS_DATA, *HRTFS_HANDLE; - -/* Reverberator structures */ - - -typedef struct ivas_roomAcoustics_t -{ - int16_t override; - int16_t use_brir; - int16_t late_reverb_on; - int16_t nBands; /* Number of frequency bands for which reverb properties are provided, integer, range [2..256] */ - float pFc_input[CLDFB_NO_CHANNELS_MAX]; /* Center frequencies for which following values are provided: */ - float pAcoustic_rt60[CLDFB_NO_CHANNELS_MAX]; /* - The room's T60 per center frequency */ - float pAcoustic_dsr[CLDFB_NO_CHANNELS_MAX]; /* - The room's Diffuse to Source Ratio per center frequency */ - float acousticPreDelay; /* Time elapsed between input signal and late reverberation start, float, range [0.001..10] */ - float inputPreDelay; /* Offset in seconds from where DSR is computed in the RIR (0 = at source), float, range [0.001..10] */ -} ivas_roomAcoustics_t; - -typedef struct ivas_render_config_t -{ -#ifdef DEBUGGING - ivas_renderTypeOverride renderer_type_override; -#endif - ivas_roomAcoustics_t roomAcoustics; -} RENDER_CONFIG_DATA, *RENDER_CONFIG_HANDLE; - - -typedef struct ivas_rev_delay_line_t -{ - float *pBuffer; - uint16_t MaxDelay; - int16_t Delay; - uint16_t BufferPos; - float Gain; - -} ivas_rev_delay_line_t; - -typedef struct ivas_rev_iir_filter_t -{ - uint16_t MaxTaps; - uint16_t nr_taps; - uint16_t isFIR; - float Output; - float CoefA[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - float CoefB[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - float pBuffer[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - -} ivas_rev_iir_filter_t; - - -typedef float rv_fftwf_type_complex[2]; /* complex type of fftwf library */ - -/* Convertion block for FFT filter: from time domain to frequency domain (with OLS) and back */ -typedef struct ivas_reverb_t2f_f2t_t -{ - int16_t fft_size; - int16_t log2_fft_size; - int16_t block_size; - int16_t hist_size; /* rv_fft_size - rv_block_size */ - float fft_history_L[RV_FILTER_MAX_HISTORY]; - float fft_history_R[RV_FILTER_MAX_HISTORY]; - -} ivas_reverb_t2f_f2t_t; - -/* FFT filter with its frequency response coefficients */ -typedef struct ivas_reverb_fft_filter_t -{ - int16_t fft_size; - float fft_spectrum[RV_FILTER_MAX_FFT_SIZE]; - -} ivas_reverb_fft_filter_t; - - -typedef struct ivas_reverb_state_t -{ - RENDER_CONFIG_DATA pConfig; - - /* input downmixer: */ - float dmx_gain; /* downmix gain */ - - /* predelay: */ - ivas_rev_delay_line_t predelay_line; - float *pPredelay_buffer; - - /* jot reverberator: */ - uint16_t nr_of_branches; /* number of feedback loops */ - ivas_rev_delay_line_t delay_line[IVAS_REV_MAX_NR_BRANCHES]; /* feedback loop delays */ - float *loop_delay_buffer[IVAS_REV_MAX_NR_BRANCHES]; /* feedback loop delay sample buffers */ - ivas_rev_iir_filter_t t60[IVAS_REV_MAX_NR_BRANCHES]; /* feedback loop filters */ - float gain_matrix[IVAS_REV_MAX_NR_BRANCHES][IVAS_REV_MAX_NR_BRANCHES]; /* feedback matrix */ - float mixer[BINAURAL_CHANNELS][IVAS_REV_MAX_NR_BRANCHES]; /* output mixer matrix */ - - /* binauralization filters: */ - int16_t do_corr_filter; - ivas_reverb_t2f_f2t_t fft_filter_ols; - ivas_reverb_fft_filter_t fft_filter_correl_0; - ivas_reverb_fft_filter_t fft_filter_correl_1; - ivas_reverb_fft_filter_t fft_filter_color_0; - ivas_reverb_fft_filter_t fft_filter_color_1; - uint16_t fft_size; /* fft processing size */ - uint16_t fft_subblock_size; /* fft block processing size */ - uint16_t num_fft_subblocks; /* number of fft subblocks */ - uint16_t full_block_size; /* full block processing size */ - -} REVERB_DATA, *REVERB_HANDLE; - - -typedef struct ivas_orient_trk_state_t -{ - OTR_TRACKING_T trackingType; - float centerAdaptationRate; - float offCenterAdaptationRate; - float adaptationAngle; - - float alpha; - - float absYaw; /* absolute orientation */ - float absPitch; - float absRoll; - - float absAvgYaw; /* average absolute orientation */ - float absAvgPitch; - float absAvgRoll; - - float refYaw; /* reference orientation */ - float refPitch; - float refRoll; - - float trkYaw; /* tracked orientation */ - float trkPitch; - float trkRoll; - -} ivas_orient_trk_state_t; - - -/* Crend structures */ -typedef struct ivas_crend_state_t -{ - float *freq_buffer_re[IVAS_MAX_NUM_CH]; - float *freq_buffer_im[IVAS_MAX_NUM_CH]; - float *freq_buffer_re_diffuse; - float *freq_buffer_im_diffuse; - float *prev_out_buffer[BINAURAL_CHANNELS]; - float *lfe_delay_line; - float m_fYaw; - float m_fPitch; - float m_fRoll; - ivas_orient_trk_state_t *hTrack; - REVERB_HANDLE hReverb; - int16_t delay_line_rw_index; - int16_t diffuse_delay_line_rw_index; - -} CREND_DATA, *CREND_HANDLE; - - -/*----------------------------------------------------------------------------------* - * LFE decoder structures - *----------------------------------------------------------------------------------*/ - -typedef struct ivas_lfe_dec_data_structure -{ - ivas_filters_process_state_t filter_state; - LFE_WINDOW_HANDLE pWindow_state; - const uint16_t *cum_freq_models[IVAS_MAX_NUM_QUANT_STRATS][IVAS_MAX_NUM_DCT_COEF_GROUPS]; - float lfe_block_delay_s; - int16_t lfe_prior_buf_len; - float *prior_out_buffer; - - float *prevsynth_buf; - float *lfe_delay_buf; - int16_t lfe_addl_delay; - int16_t bfi_count; - -} LFE_DEC_DATA, *LFE_DEC_HANDLE; - - -/*----------------------------------------------------------------------------------* - * Limiter structure - *----------------------------------------------------------------------------------*/ - -typedef struct -{ - int16_t max_num_channels; - int16_t num_channels; - float **channel_ptrs; - int32_t sampling_rate; - float gain; - float release_heuristic; - float attack_constant; - int16_t strong_saturation_count; -#ifdef DEBUGGING - int32_t cnt_frames_limited; /* counter of frames in which the limiter is applied */ -#endif - -} IVAS_LIMITER, *IVAS_LIMITER_HANDLE; - - /*----------------------------------------------------------------------------------* * Decoder configuration structure *----------------------------------------------------------------------------------*/ @@ -1908,23 +1154,21 @@ typedef struct decoder_config_structure int32_t output_Fs; /* output signal sampling frequency in Hz */ int16_t nchan_out; /* number of output audio channels */ AUDIO_CONFIG output_config; /* output audio configuration */ - - int16_t Opt_LsCustom; /* indicates whether loudspeaker custom setup is used */ - int16_t Opt_HRTF_binary; /* indicates whether HRTF binary file is used */ - int16_t Opt_Headrotation; /* indicates whether head-rotation is used */ - int16_t orientation_tracking; /* indicates orientation tracking type */ + int16_t Opt_LsCustom; /* indicates whether loudspeaker custom setup is used */ + int16_t Opt_HRTF_binary; /* indicates whether HRTF binary file is used */ + int16_t Opt_Headrotation; /* indicates whether head-rotation is used */ + int16_t Opt_RendConfigCustom; /* indicates whether Renderer configuration custom setup is used */ + int16_t orientation_tracking; /* indicates orientation tracking type */ float no_diegetic_pan; int16_t Opt_AMR_WB; /* flag indicating AMR-WB IO mode */ /* temp. development parameters */ #ifdef DEBUGGING - int16_t forceSubframeBinauralization; /* Flag for forcing Parametric binauralizer to subframe mode */ - int16_t force_rend; /* forced TD/CLDFB binaural renderer (for ISM and MC) */ + int16_t force_rend; /* forced TD/CLDFB binaural renderer (for ISM and MC) */ #endif } DECODER_CONFIG, *DECODER_CONFIG_HANDLE; - /*----------------------------------------------------------------------------------* * * Main IVAS decoder structure @@ -1969,6 +1213,7 @@ typedef struct Decoder_Struct /* multichannel modules */ ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS]; /* ISM metadata handles (storage for one frame of read ISM metadata) */ + ISM_DTX_DATA_DEC hISMDTX; /* ISM DTX structure */ ISM_RENDERER_HANDLE hIsmRendererData; /* ISM renderer handle */ DIRAC_DEC_HANDLE hDirAC; /* DirAC handle */ SPAR_DEC_HANDLE hSpar; /* SPAR handle */ @@ -1979,11 +1224,14 @@ typedef struct Decoder_Struct LFE_DEC_HANDLE hLFE; /* LFE handle */ ISM_MODE ism_mode; /* ISM format mode */ +#ifdef NCHAN_ISM_PARAMETER + int16_t nchan_ism; /* number of ISM channels */ +#endif SBA_MODE sba_mode; /* SBA format mode */ MC_MODE mc_mode; /* MC format mode */ - int16_t sba_order; /* Ambisonic (SBA) order */ int16_t sba_planar; /* Ambisonic (SBA) planar flag */ + int16_t sba_analysis_order; /* Ambisonic (SBA) order used for analysis and coding */ int16_t sba_dirac_stereo_flag; /* flag indicating stereo output for SBA DirAC modes with 1 TC */ /* rendering modules */ @@ -1998,17 +1246,25 @@ typedef struct Decoder_Struct EFAP_HANDLE hEFAPdata; /* EFAP structure */ VBAP_HANDLE hVBAPdata; /* VBAP structure */ MONO_DOWNMIX_RENDERER_HANDLE hMonoDmxRenderer; /* Mono downmix structure */ - CREND_HANDLE hCrend; /* Convolution mixer renderer structure */ - HRTFS_HANDLE hHrtf; /* HRTFs handle */ + CREND_WRAPPER_HANDLE hCrendWrapper; + REVERB_HANDLE hReverb; /* Reverb handle */ + HRTFS_CREND_HANDLE hSetOfHRTF; /* Set of HRTFs handle (CRend) */ + HRTFS_FASTCONV_HANDLE hHrtfFastConv; /* FASTCONV HRTF tables for binaural rendering */ + HRTFS_PARAMBIN_HANDLE hHrtfParambin; /* HRTF tables for parametric binauralizer */ LSSETUP_CUSTOM_HANDLE hLsSetupCustom; /* Custom LS configuration handle */ float *hoa_dec_mtx; /* Pointer to decoder matrix for SBA */ HEAD_TRACK_DATA_HANDLE hHeadTrackData; /* Head tracking data structure */ RENDER_CONFIG_DATA *hRenderConfig; /* Renderer config pointer */ - int32_t binaural_latency_ns; /* HRTF binauralization latency in ns */ + int32_t binaural_latency_ns; /* Binauralization latency in ns */ #ifdef DEBUGGING int32_t noClipping; /* number of clipped samples */ #endif + int32_t last_active_ivas_total_brate; +#ifdef FIX_379_EXT_METADATA + int16_t ism_extmeta_active; /* Extended metadata active in decoder */ + int16_t ism_extmeta_cnt; /* Change frame counter for extended metadata */ +#endif } Decoder_Struct; diff --git a/lib_dec/ivas_stereo_adapt_GR_dec.c b/lib_dec/ivas_stereo_adapt_GR_dec.c index ec84df98310be274e43335b55e6d0e899e70161b..7e698f6169b94aeb6dc749d1173a614f9456ae27 100644 --- a/lib_dec/ivas_stereo_adapt_GR_dec.c +++ b/lib_dec/ivas_stereo_adapt_GR_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" #include "ivas_rom_com.h" #include "rom_dec.h" diff --git a/lib_dec/ivas_stereo_cng_dec.c b/lib_dec/ivas_stereo_cng_dec.c index 05e9222ddbde2aa767c01199a1fe420d083448fa..b55cf4cfbdbda5037c08726630424a19321bfd20 100644 --- a/lib_dec/ivas_stereo_cng_dec.c +++ b/lib_dec/ivas_stereo_cng_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * Local constants @@ -90,7 +90,8 @@ void stereo_dft_dec_sid_coh( int16_t bits_tmp; int16_t b; - nr_of_sid_stereo_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + /* TODO: still use old number of bits to keep bitexactness in output */ + nr_of_sid_stereo_bits = ( 4400 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; /* If the coherence is not encoded due to lack of bits set alpha to zero which leads to that the coherence */ /* from the previous frame is used. */ @@ -173,6 +174,8 @@ void stereo_dft_dec_sid_coh( ( *nb_bits )++; } + dtx_read_padding_bits( st, ( IVAS_SID_5k2 - 4400 ) / FRAMES_PER_SEC ); + return; } @@ -223,7 +226,7 @@ static void stereo_dft_generate_comfort_noise( hFdCngCom = st->hFdCngDec->hFdCngCom; - wmops_sub_start( "DFT_CNG" ); + push_wmops( "DFT_CNG" ); set_f( dmpf, 0.0f, M + 2 ); set_f( Atmp, 0.0f, M + 2 ); @@ -343,7 +346,7 @@ static void stereo_dft_generate_comfort_noise( ptr2 = ptr1 + 1; for ( i = 0; i < st->L_frame / 2 - 1; i++ ) { - *ptr0++ = 2.0f * sqrtf( st->lp_ener / st->L_frame * 0.5f ) / sqrtf( *ptr1 * *ptr1 + *ptr2 * *ptr2 ); + *ptr0++ = 2.0f * sqrtf( st->lp_ener / st->L_frame * 0.5f ) * inv_sqrt( *ptr1 * *ptr1 + *ptr2 * *ptr2 ); ptr1 += 2; ptr2 += 2; } @@ -623,7 +626,7 @@ static void stereo_dft_generate_comfort_noise( st->hFdCngDec->ms_last_inactive_bwidth = st->bwidth; } - wmops_sub_end(); + pop_wmops(); return; } @@ -653,9 +656,9 @@ void stereo_dtf_cng( hCPE->hStereoCng->nr_dft_frames++; } - if ( ivas_total_brate <= IVAS_SID_4k4 ) + if ( ivas_total_brate <= IVAS_SID_5k2 ) { - if ( hCPE->hStereoCng->nr_sid_frames < SID_INIT && ivas_total_brate == IVAS_SID_4k4 ) + if ( hCPE->hStereoCng->nr_sid_frames < SID_INIT && ivas_total_brate == IVAS_SID_5k2 ) { hCPE->hStereoCng->nr_sid_frames++; } @@ -707,7 +710,7 @@ void stereo_cng_dec_update( if ( hCPE->element_mode == IVAS_CPE_DFT ) { - if ( ivas_total_brate == IVAS_SID_4k4 || ivas_total_brate == FRAME_NO_DATA ) + if ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) { hCPE->hStereoCng->prev_sid_nodata = 1; } @@ -769,7 +772,9 @@ void stereo_cng_compute_PScorr( enrS += *outputSptr * *outputSptr; dotPS += *outputPptr++ * *outputSptr++; } - c_PS = ( dotPS + EPSILON ) / sqrtf( enrP * enrS + EPSILON ); + + c_PS = ( dotPS + EPSILON ) * inv_sqrt( enrP * enrS + EPSILON ); + *c_PS_LT = STEREO_TD_PS_CORR_FILT * *c_PS_LT + ( 1 - STEREO_TD_PS_CORR_FILT ) * c_PS; return; @@ -806,7 +811,7 @@ static void stereo_cng_compute_LRcorr( dotLR += output[0][i] * output[1][i]; } - c_LR = fabsf( dotLR + EPSILON ) / sqrtf( enrL * enrR + EPSILON ); + c_LR = fabsf( dotLR + EPSILON ) * inv_sqrt( enrL * enrR + EPSILON ); c = ( enrL + DELTA ) / ( enrR + DELTA ); hCPE->hStereoTD->c_LR_LT = STEREO_TD_PS_CORR_FILT * hCPE->hStereoTD->c_LR_LT + ( 1 - STEREO_TD_PS_CORR_FILT ) * c_LR; hCPE->hStereoCng->c_LR_LT = hCPE->hStereoTD->c_LR_LT; @@ -930,7 +935,7 @@ void stereo_cna_update_params( } /* estimate L/R correlation factor and ILD in time domain */ - c_LR = fabsf( dotLR + EPSILON ) / sqrtf( enrL * enrR + EPSILON ); + c_LR = fabsf( dotLR + EPSILON ) * inv_sqrt( enrL * enrR + EPSILON ); c = ( enrL + DELTA ) / ( enrR + DELTA ); c_ILD = ( c - 1 ) / ( c + 1 ); } diff --git a/lib_dec/ivas_stereo_dft_dec.c b/lib_dec/ivas_stereo_dft_dec.c index fbdfab03720dd1571758943663ba2986ef0b1959..769f6016b487b16c2f1824ad302af50b9a6136ee 100644 --- a/lib_dec/ivas_stereo_dft_dec.c +++ b/lib_dec/ivas_stereo_dft_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -76,7 +76,7 @@ * Local function prototypes *-------------------------------------------------------------------------*/ -static void stereo_dft_dec_open( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, const int32_t output_Fs ); +static void stereo_dft_dec_open( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, const int32_t output_Fs, const int16_t nchan_transport ); static void stereo_dft_compute_td_stefi_params( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, const float samp_ratio ); @@ -101,8 +101,8 @@ static void stereo_dft_dequantize_res_gains( for ( i = 0; i < N; i++ ) { /* Ensure the indices are within range -- may go out of range due to frame loss */ - check_bounds_s( &ind1[i], 0, 30 ); - check_bounds_s( &ind2[i], 0, 7 ); + ind1[i] = check_bounds_s( ind1[i], 0, 30 ); + ind2[i] = check_bounds_s( ind2[i], 0, 7 ); index = ( ( ind1[i] < 15 ? 15 - ind1[i] : ind1[i] - 15 ) << 3 ) + ind2[i]; gout[i] = ind1[i] < 15 ? -dft_res_gains_q[index][0] : dft_res_gains_q[index][0]; rout[i] = dft_res_gains_q[index][1]; @@ -130,8 +130,8 @@ static void stereo_dft_dequantize_res_gains_f( for ( i = 0; i < N; i++ ) { /* Ensure the indices are within range -- may go out of range due to frame loss */ - check_bounds( &ind1[i], 0, 31 ); - check_bounds( &ind2[i], 0, 7 ); + ind1[i] = check_bounds( ind1[i], 0, 31 ); + ind2[i] = check_bounds( ind2[i], 0, 7 ); /* compensate for the offset and extract/remove sign of first index */ sign = ind1[i] < 15 ? -1 : 1; @@ -251,7 +251,8 @@ ivas_error stereo_dft_dec_create( STEREO_DFT_DEC_DATA_HANDLE *hStereoDft, /* i/o: decoder DFT stereo handle */ const int32_t element_brate, /* i : element bitrate */ const int32_t output_Fs, /* i : output sampling rate */ - const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ + const int16_t sba_dirac_stereo_flag, /* i : signal stereo output for SBA DirAC */ + const int16_t nchan_transport /* i : number of transport channels */ ) { STEREO_DFT_DEC_DATA_HANDLE hStereoDft_loc; @@ -262,22 +263,22 @@ ivas_error stereo_dft_dec_create( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: DFT Stereo memory already allocated\n" ); } - if ( ( hStereoDft_loc = (STEREO_DFT_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_DFT_DEC_DATA ) ) ) == NULL ) + if ( ( hStereoDft_loc = (STEREO_DFT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_DFT_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT Stereo\n" ) ); } - if ( ( hStereoDft_loc->hConfig = (STEREO_DFT_CONFIG_DATA_HANDLE) count_malloc( sizeof( STEREO_DFT_CONFIG_DATA ) ) ) == NULL ) + if ( ( hStereoDft_loc->hConfig = (STEREO_DFT_CONFIG_DATA_HANDLE) malloc( sizeof( STEREO_DFT_CONFIG_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT Stereo Config\n" ) ); } - if ( ( hStereoDft_loc->hBpf = (BPF_DEC_HANDLE) count_malloc( sizeof( BPF_DEC_DATA ) ) ) == NULL ) + if ( ( hStereoDft_loc->hBpf = (BPF_DEC_HANDLE) malloc( sizeof( BPF_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for BPF handle\n" ) ); } - if ( ( hStereoDft_loc->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) count_malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL ) + if ( ( hStereoDft_loc->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TCX-LTP handle\n" ) ); } @@ -293,7 +294,8 @@ ivas_error stereo_dft_dec_create( stereo_dft_config( hStereoDft_loc->hConfig, element_brate, &tmpS, &tmpS ); } - stereo_dft_dec_open( hStereoDft_loc, output_Fs ); + stereo_dft_dec_open( hStereoDft_loc, output_Fs, + nchan_transport ); *hStereoDft = hStereoDft_loc; @@ -309,10 +311,10 @@ ivas_error stereo_dft_dec_create( static void stereo_dft_dec_open( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */ - const int32_t output_Fs /* i : output sampling rate */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t nchan_transport /* i : number of transport channels */ ) { - /*Sizes*/ hStereoDft->N = (int16_t) ( STEREO_DFT_HOP_MAX * output_Fs / 48000 ); @@ -365,6 +367,17 @@ static void stereo_dft_dec_open( hStereoDft->hb_stefi_delay = NS2SA( output_Fs, STEREO_DFT_TD_STEFI_DELAY_NS ); + if ( nchan_transport > 2 ) + { + hStereoDft->min_smooth_gains = min_smooth_gains2; + hStereoDft->max_smooth_gains = max_smooth_gains2; + } + else + { + hStereoDft->min_smooth_gains = min_smooth_gains1; + hStereoDft->max_smooth_gains = max_smooth_gains1; + } + /* reset DFT stereo memories */ stereo_dft_dec_reset( hStereoDft ); @@ -383,6 +396,7 @@ void stereo_dft_dec_reset( ) { int16_t i; + int16_t j, b; /*Configuration*/ set_s( hStereoDft->prm_res, hStereoDft->hConfig->prm_res, STEREO_DFT_DEC_DFT_NB ); @@ -480,6 +494,31 @@ void stereo_dft_dec_reset( set_zero( hStereoDft->smooth_fac[0], SBA_DIRAC_STEREO_NUM_BANDS ); set_zero( hStereoDft->smooth_fac[1], SBA_DIRAC_STEREO_NUM_BANDS ); + hStereoDft->itd_xfade_target = 0.0f; + hStereoDft->itd_xfade_step = 0.0f; + hStereoDft->itd_xfade_counter = 0; + hStereoDft->itd_xfade_prev = 0.0f; + hStereoDft->last_active_element_brate = 0; + hStereoDft->ipd_xfade_target = 0.0f; + hStereoDft->ipd_xfade_step = 0.0f; + hStereoDft->ipd_xfade_counter = 0; + hStereoDft->ipd_xfade_prev = 0.0f; + + for ( b = 0; b < hStereoDft->nbands; b++ ) + { + for ( i = 0; i < 2; i++ ) + { + for ( j = 0; j < 4; j++ ) + { + hStereoDft->mixer_mat_smooth[i][j][b] = 0.0f; + } + } + } + hStereoDft->first_frame = 1; + hStereoDft->g_L_prev = 0.f; + hStereoDft->g_R_prev = 0.f; + + return; } @@ -580,23 +619,23 @@ void stereo_dft_dec_destroy( if ( hStereoDft->hConfig != NULL ) { - count_free( hStereoDft->hConfig ); + free( hStereoDft->hConfig ); hStereoDft->hConfig = NULL; } if ( hStereoDft->hBpf != NULL ) { - count_free( hStereoDft->hBpf ); + free( hStereoDft->hBpf ); hStereoDft->hBpf = NULL; } if ( hStereoDft->hTcxLtpDec != NULL ) { - count_free( hStereoDft->hTcxLtpDec ); + free( hStereoDft->hTcxLtpDec ); hStereoDft->hTcxLtpDec = NULL; } - count_free( hStereoDft ); + free( hStereoDft ); hStereoDft = NULL; return; @@ -640,7 +679,7 @@ void stereo_dft_dec_analyze( int16_t mem_size; int16_t ovl2; - wmops_sub_start( "DFT_analysis" ); + push_wmops( "DFT_analysis" ); hStereoDft = hCPE->hStereoDft; @@ -762,7 +801,7 @@ void stereo_dft_dec_analyze( if ( hCPE->nchan_out == 1 && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) { - wmops_sub_end(); + pop_wmops(); return; } @@ -913,7 +952,7 @@ void stereo_dft_dec_analyze( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -943,7 +982,7 @@ void stereo_dft_dec_synthesize( int16_t ovl2, flat_portion_end; float ola_buff[STEREO_DFT32MS_OVL2_MAX]; int16_t moffset; - wmops_sub_start( "DFT_synthesis" ); + push_wmops( "DFT_synthesis" ); /*-----------------------------------------------------------------* * Initialization @@ -1069,7 +1108,7 @@ void stereo_dft_dec_synthesize( } #endif - wmops_sub_end(); + pop_wmops(); return; } @@ -1086,7 +1125,14 @@ void stereo_dft_dec( float DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */ float *input_mem, /* i/o: mem of buffer DFT analysis */ STEREO_CNG_DEC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ - const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ + const int16_t sba_dirac_stereo_flag, /* i : signal stereo output for SBA DirAC */ +#ifdef SBA2MONO + const int16_t sba_mono_flag, /* i : signal mono output for SBA DirAC */ +#endif + ivas_spar_md_dec_state_t *hMdDec, /* i : SPAR MD handle for upmixing */ + const int16_t cross_fade_start_offset, /* i : SPAR mixer delay compensation */ + const int32_t output_Fs, /* i : Fs for delay calculation */ + const int16_t nchan_transport /* i : number of transpor channels */ ) { int16_t i, k, b, N_div, stop; @@ -1094,6 +1140,7 @@ void stereo_dft_dec( float DFT_R[STEREO_DFT32MS_N_MAX]; float DFT_PRED_RES[STEREO_DFT32MS_N_32k]; float *pDFT_DMX; + float *pDFT_DMX1; float *pDFT_RES; float g, tmp; float *pPredGain; @@ -1117,6 +1164,8 @@ void stereo_dft_dec( HANDLE_FD_CNG_COM hFdCngCom = hFdCngDec->hFdCngCom; int16_t *cna_seed = &( hFdCngCom->seed ); + float DFT_W, DFT_Y; + output_frame = (int16_t) ( st0->output_Fs / FRAMES_PER_SEC ); /*------------------------------------------------------------------* @@ -1158,11 +1207,14 @@ void stereo_dft_dec( /* Smoothing for the current frame */ if ( sba_dirac_stereo_flag ) { - ivas_sba_dirac_stereo_smooth_parameters( hStereoDft ); + ivas_sba_dirac_stereo_smooth_parameters( hStereoDft, + hMdDec, + cross_fade_start_offset, + output_Fs ); } else { - stereo_dft_dec_smooth_parameters( hStereoDft, hStereoCng->prev_sid_nodata ); + stereo_dft_dec_smooth_parameters( hStereoDft, hStereoCng->prev_sid_nodata, hStereoCng->active_frame_counter, st0->element_brate ); } } @@ -1183,6 +1235,11 @@ void stereo_dft_dec( { pDFT_DMX = DFT[0] + k * STEREO_DFT32MS_N_MAX; pDFT_RES = DFT[1] + k * STEREO_DFT32MS_N_MAX; + pDFT_DMX1 = 0; + if ( nchan_transport > 1 ) + { + pDFT_DMX1 = DFT[1] + k * STEREO_DFT32MS_N_MAX; + } /*Apply Stereo*/ if ( hStereoDft->hConfig->dmx_active ) @@ -1226,7 +1283,10 @@ void stereo_dft_dec( hStereoDft->past_DMX_pos = ( hStereoDft->past_DMX_pos + STEREO_DFT_PAST_MAX - 1 ) % STEREO_DFT_PAST_MAX; } - stereo_dft_generate_res_pred( hStereoDft, samp_ratio, pDFT_DMX, DFT_PRED_RES, pPredGain, k, DFT[1] + k * STEREO_DFT32MS_N_MAX, &stop, st0->bfi ); + if ( !( sba_dirac_stereo_flag && nchan_transport >= 2 ) ) + { + stereo_dft_generate_res_pred( hStereoDft, samp_ratio, pDFT_DMX, DFT_PRED_RES, pPredGain, k, DFT[1] + k * STEREO_DFT32MS_N_MAX, &stop, st0->bfi ); + } if ( hStereoDft->res_cod_band_max > 0 ) { @@ -1298,7 +1358,7 @@ void stereo_dft_dec( #endif /* No residual coding in inactive frames, instead pDFT_RES is used for the second channel */ - if ( b >= hStereoDft->res_cod_band_max && !hStereoDft->frame_sid_nodata ) + if ( b >= hStereoDft->res_cod_band_max && !hStereoDft->frame_sid_nodata && !( sba_dirac_stereo_flag && hMdDec ) ) { /*filter non-coded frequencies. It removes some MDCT frequency aliasing*/ for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) @@ -1348,10 +1408,143 @@ void stereo_dft_dec( } } } + else if ( sba_dirac_stereo_flag && hMdDec ) + { + + if ( nchan_transport == 1 ) + { +#ifdef SBA2MONO + if ( sba_mono_flag ) + { + if ( b == 0 ) + { + i = 0; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i]; + DFT_L[2 * i] = DFT_W; + DFT_R[2 * i] = 0.f; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1]; + DFT_L[2 * i + 1] = DFT_W; + DFT_R[2 * i + 1] = 0.f; + } + for ( i = hStereoDft->band_limits[b]; i < min( stop, hStereoDft->band_limits[b + 1] ); i++ ) + { + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i] + ( hStereoDft->mixer_mat_smooth[0][1][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][2][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][3][b + k * IVAS_MAX_NUM_BANDS] ) * DFT_PRED_RES[2 * i]; + DFT_L[2 * i] = DFT_W; + DFT_R[2 * i] = 0.f; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1] + ( hStereoDft->mixer_mat_smooth[0][1][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][2][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][3][b + k * IVAS_MAX_NUM_BANDS] ) * DFT_PRED_RES[2 * i + 1]; + DFT_L[2 * i + 1] = DFT_W; + DFT_R[2 * i + 1] = 0.f; + } + for ( ; i < hStereoDft->band_limits[b + 1]; i++ ) + { + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i]; + DFT_L[2 * i] = DFT_W; + DFT_R[2 * i] = 0.f; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1]; + DFT_L[2 * i + 1] = DFT_W; + DFT_R[2 * i + 1] = 0.f; + } + } + else + { +#endif + if ( b == 0 ) + { + i = 0; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i]; + + DFT_L[2 * i] = DFT_W + DFT_Y; + DFT_R[2 * i] = DFT_W - DFT_Y; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1]; + + DFT_L[2 * i + 1] = DFT_W + DFT_Y; + DFT_R[2 * i + 1] = DFT_W - DFT_Y; + } + for ( i = hStereoDft->band_limits[b]; i < min( stop, hStereoDft->band_limits[b + 1] ); i++ ) + { + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i] + ( hStereoDft->mixer_mat_smooth[0][1][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][2][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][3][b + k * IVAS_MAX_NUM_BANDS] ) * DFT_PRED_RES[2 * i]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i] + ( hStereoDft->mixer_mat_smooth[1][1][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][2][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][3][b + k * IVAS_MAX_NUM_BANDS] ) * DFT_PRED_RES[2 * i]; + + DFT_L[2 * i] = DFT_W + DFT_Y; + DFT_R[2 * i] = DFT_W - DFT_Y; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1] + ( hStereoDft->mixer_mat_smooth[0][1][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][2][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[0][3][b + k * IVAS_MAX_NUM_BANDS] ) * DFT_PRED_RES[2 * i + 1]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1] + ( hStereoDft->mixer_mat_smooth[1][1][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][2][b + k * IVAS_MAX_NUM_BANDS] + hStereoDft->mixer_mat_smooth[1][3][b + k * IVAS_MAX_NUM_BANDS] ) * DFT_PRED_RES[2 * i + 1]; + + DFT_L[2 * i + 1] = DFT_W + DFT_Y; + DFT_R[2 * i + 1] = DFT_W - DFT_Y; + } + for ( ; i < hStereoDft->band_limits[b + 1]; i++ ) + { + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i]; + + DFT_L[2 * i] = DFT_W + DFT_Y; + DFT_R[2 * i] = DFT_W - DFT_Y; + + DFT_W = hStereoDft->mixer_mat_smooth[0][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1]; + + DFT_L[2 * i + 1] = DFT_W + DFT_Y; + DFT_R[2 * i + 1] = DFT_W - DFT_Y; + } +#ifdef SBA2MONO + } +#endif + } + else if ( nchan_transport >= 2 ) + { + if ( b == 0 ) + { + i = 0; + + DFT_W = pDFT_DMX[2 * i]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i] + pDFT_DMX1[2 * i]; + + DFT_L[2 * i] = DFT_W + DFT_Y; + DFT_R[2 * i] = DFT_W - DFT_Y; + + DFT_W = pDFT_DMX[2 * i + 1]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1] + pDFT_DMX1[2 * i + 1]; + + DFT_L[2 * i + 1] = DFT_W + DFT_Y; + DFT_R[2 * i + 1] = DFT_W - DFT_Y; + } + for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) + { + DFT_W = pDFT_DMX[2 * i]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i] + pDFT_DMX1[2 * i]; + + DFT_L[2 * i] = DFT_W + DFT_Y; + DFT_R[2 * i] = DFT_W - DFT_Y; + + DFT_W = pDFT_DMX[2 * i + 1]; + DFT_Y = hStereoDft->mixer_mat_smooth[1][0][b + k * IVAS_MAX_NUM_BANDS] * pDFT_DMX[2 * i + 1] + pDFT_DMX1[2 * i + 1]; + + DFT_L[2 * i + 1] = DFT_W + DFT_Y; + DFT_R[2 * i + 1] = DFT_W - DFT_Y; + } + } + else + { + assert( "nhcan_transport must be 1 or 1!" ); + } + } else { + + for ( i = hStereoDft->band_limits[b]; i < min( stop, hStereoDft->band_limits[b + 1] ); i++ ) { + tmp = g * pDFT_DMX[2 * i] + pDFT_RES[2 * i] + DFT_PRED_RES[2 * i]; DFT_L[2 * i] = pDFT_DMX[2 * i] + tmp; @@ -1746,7 +1939,9 @@ void stereo_dft_dec_read_BS( * Initialization *-----------------------------------------------------------------*/ - if ( ivas_total_brate == IVAS_SID_4k4 ) + k_offset = STEREO_DFT_OFFSET; + + if ( ivas_total_brate == IVAS_SID_5k2 ) { if ( ivas_format == MASA_FORMAT ) { @@ -1760,7 +1955,7 @@ void stereo_dft_dec_read_BS( hStereoDft->frame_nodata = 0; hStereoDft->frame_sid_nodata = 1; hStereoDft->frame_sid = 1; - *nb_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + *nb_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; } } else if ( ivas_total_brate == FRAME_NO_DATA ) @@ -1770,6 +1965,8 @@ void stereo_dft_dec_read_BS( hStereoDft->frame_sid = 0; *nb_bits = 0; *total_brate = 0; + hStereoDft->itd[k = hStereoDft->prm_res[k_offset] - 1 + k_offset] = hStereoDft->itd_xfade_target; + hStereoDft->gipd[hStereoDft->prm_res[k_offset] - 1 + k_offset] = hStereoDft->ipd_xfade_target; return; } @@ -1800,10 +1997,9 @@ void stereo_dft_dec_read_BS( /*init*/ max_bits = *nb_bits; *nb_bits = 0; - k_offset = STEREO_DFT_OFFSET; N_div = STEREO_DFT_NBDIV; - if ( ivas_total_brate > IVAS_SID_4k4 ) + if ( ivas_total_brate > IVAS_SID_5k2 ) { mvr2r( hStereoDft->side_gain + 2 * STEREO_DFT_BAND_MAX, sg_tmp, STEREO_DFT_BAND_MAX ); mvr2r( hStereoDft->res_pred_gain + 2 * STEREO_DFT_BAND_MAX, res_pred_gain_tmp, STEREO_DFT_BAND_MAX ); @@ -1893,7 +2089,7 @@ void stereo_dft_dec_read_BS( fprintf( pF, "ITD: %d ", hStereoDft->hConfig->itd_mode ); #endif - if ( !( ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_4k4 ) ) + if ( !( ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_5k2 ) ) { /*------------------------------------------------------------------* * read Side gains @@ -1974,7 +2170,7 @@ void stereo_dft_dec_read_BS( #endif } } - else if ( *nb_bits <= ( ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 - SID_FORMAT_NBITS ) ) + else if ( *nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 - SID_FORMAT_NBITS ) ) { itd_mode = get_next_indice( st, STEREO_DFT_ITD_MODE_NBITS ); ( *nb_bits ) += STEREO_DFT_ITD_MODE_NBITS; /*ITD mode flag: 1bit*/ @@ -2016,7 +2212,7 @@ void stereo_dft_dec_read_BS( stereo_dft_dequantize_ipd( &ind1_ipd[0], hStereoDft->gipd + ( k + k_offset ), 1, STEREO_DFT_GIPD_NBITS ); } } - else if ( *nb_bits <= ( ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - STEREO_DFT_FLAG_BITS - STEREO_DFT_SID_GIPD_NBITS - SID_FORMAT_NBITS ) ) + else if ( *nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - STEREO_DFT_FLAG_BITS - STEREO_DFT_SID_GIPD_NBITS - SID_FORMAT_NBITS ) ) { /* SID frame, only read IPD only if enough bits left in bitstream */ hStereoDft->no_ipd_flag = st->bit_stream[nb]; @@ -2177,7 +2373,7 @@ void stereo_dft_dec_read_BS( #endif } - if ( !( ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_4k4 ) ) + if ( !( ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_5k2 ) ) { if ( hStereoDft->side_gain_flag_1 != 2 ) { @@ -2185,7 +2381,7 @@ void stereo_dft_dec_read_BS( } } - if ( ivas_total_brate > IVAS_SID_4k4 ) + if ( ivas_total_brate > IVAS_SID_5k2 ) { hStereoDft->recovery_flg = stereo_dft_sg_recovery( hStereoDft ); @@ -2212,7 +2408,7 @@ void stereo_dft_dec_read_BS( fprintf( pF, "\nGain: %d ", I ); #endif - wmops_sub_start( "residual_decode" ); + push_wmops( "residual_decode" ); if ( I != ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO ) { ECSQ_init_instance( &ecsq_inst, 0 /*dummy index*/, &range_uni_dec_state ); @@ -2244,7 +2440,7 @@ void stereo_dft_dec_read_BS( } ( *nb_bits ) += n_bits; - wmops_sub_end(); + pop_wmops(); #ifdef DEBUG_MODE_DFT fprintf( pF, "%d (max: %d)", n_bits + STEREO_DFT_RES_GLOBAL_GAIN_BITS, max_bits ); @@ -2252,12 +2448,12 @@ void stereo_dft_dec_read_BS( #endif } - if ( hStereoDft->frame_sid && !( ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_4k4 ) ) + if ( hStereoDft->frame_sid && !( ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_5k2 ) ) { stereo_dft_dec_sid_coh( st, hStereoDft->nbands, coh, nb_bits ); } - if ( ivas_total_brate == IVAS_SID_4k4 && ivas_format != MASA_FORMAT ) + if ( ivas_total_brate == IVAS_SID_5k2 && ivas_format != MASA_FORMAT ) { *nb_bits = (int16_t) ( ( element_brate - SID_2k40 ) / FRAMES_PER_SEC ); /* => hCPE->hCoreCoder[0]->total_brate = SID_2k40; */ } @@ -2401,7 +2597,7 @@ void stereo_dft_generate_res_pred( float g2; int16_t nbands_respred; - wmops_sub_start( "gen_respred" ); + push_wmops( "gen_respred" ); /* smoothing and limiting parameters */ alpha = hStereoDft->wasTransient ? 0 : 0.2f; /* no smoothing after transients */ @@ -2733,7 +2929,7 @@ void stereo_dft_generate_res_pred( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -2747,7 +2943,9 @@ void stereo_dft_generate_res_pred( void stereo_dft_dec_smooth_parameters( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */ - const int16_t prev_sid_nodata /* i : Previous SID/No data indicator */ + const int16_t prev_sid_nodata, /* i : Previous SID/No data indicator */ + const int16_t active_frame_counter, /* i : Active frame counter */ + const int32_t element_brate /* i : Element bitrate */ ) { int16_t k_offset, k, k2, b, N_div; @@ -2769,11 +2967,81 @@ void stereo_dft_dec_smooth_parameters( *( hStereoDft->side_gain + ( ( k + k_offset ) - 1 ) * STEREO_DFT_BAND_MAX + b ) = *( hStereoDft->side_gain + ( k + k_offset ) * STEREO_DFT_BAND_MAX + b ); } + if ( hStereoDft->frame_sid_nodata ) + { + /* set new xfade target if new itd received */ + if ( hStereoDft->gipd[k + k_offset] != hStereoDft->ipd_xfade_target ) + { + if ( ( hStereoDft->gipd[k + k_offset] - hStereoDft->ipd_xfade_prev ) > EVS_PI ) + { + hStereoDft->ipd_xfade_target = hStereoDft->gipd[k + k_offset] - 2 * EVS_PI; + hStereoDft->ipd_xfade_step = ( hStereoDft->ipd_xfade_target - hStereoDft->ipd_xfade_prev ) / ( STEREO_DFT_ITD_CNG_XFADE - hStereoDft->ipd_xfade_counter ); + } + else if ( ( hStereoDft->ipd_xfade_prev - hStereoDft->gipd[k + k_offset] ) > EVS_PI ) + { + hStereoDft->ipd_xfade_target = hStereoDft->gipd[k + k_offset] + 2 * EVS_PI; + hStereoDft->ipd_xfade_step = ( hStereoDft->ipd_xfade_target - hStereoDft->ipd_xfade_prev ) / ( STEREO_DFT_ITD_CNG_XFADE - hStereoDft->ipd_xfade_counter ); + } + else + { + hStereoDft->ipd_xfade_target = hStereoDft->gipd[k + k_offset]; + hStereoDft->ipd_xfade_step = ( hStereoDft->ipd_xfade_target - hStereoDft->ipd_xfade_prev ) / ( STEREO_DFT_ITD_CNG_XFADE - hStereoDft->ipd_xfade_counter ); + } + } + + /* xfade */ + if ( hStereoDft->ipd_xfade_prev != hStereoDft->ipd_xfade_target && hStereoDft->ipd_xfade_counter < STEREO_DFT_ITD_CNG_XFADE && hStereoDft->last_active_element_brate <= 24400 ) + { + hStereoDft->gipd[k + k_offset] = hStereoDft->ipd_xfade_prev + hStereoDft->ipd_xfade_step; + hStereoDft->ipd_xfade_prev = hStereoDft->gipd[k + k_offset]; + hStereoDft->ipd_xfade_counter++; + } + } + else + { + /* First active frame, "reset" everything if long enough active encoding, only triggered if STEREO_DFT_ITD_CNG_XFADE_RESET = -1 */ + if ( active_frame_counter > STEREO_DFT_ITD_CNG_XFADE_RESET ) + { + hStereoDft->ipd_xfade_target = hStereoDft->gipd[k + k_offset]; + hStereoDft->ipd_xfade_prev = hStereoDft->gipd[k + k_offset]; + hStereoDft->ipd_xfade_counter = 0; + } + } + for ( k2 = 1; k2 < hStereoDft->prm_res[k + k_offset]; k2++ ) { hStereoDft->gipd[( k + k_offset ) - k2] = hStereoDft->gipd[k + k_offset]; } + if ( hStereoDft->frame_sid_nodata ) + { + /* set new xfade target if new itd received */ + if ( hStereoDft->itd[k + k_offset] != hStereoDft->itd_xfade_target ) + { + hStereoDft->itd_xfade_target = hStereoDft->itd[k + k_offset]; + hStereoDft->itd_xfade_step = ( hStereoDft->itd_xfade_target - hStereoDft->itd_xfade_prev ) / ( STEREO_DFT_ITD_CNG_XFADE - hStereoDft->itd_xfade_counter ); + } + + /* xfade */ + if ( hStereoDft->itd_xfade_prev != hStereoDft->itd_xfade_target && hStereoDft->itd_xfade_counter < STEREO_DFT_ITD_CNG_XFADE && hStereoDft->last_active_element_brate <= 24400 ) + { + hStereoDft->itd[k + k_offset] = hStereoDft->itd_xfade_prev + hStereoDft->itd_xfade_step; + hStereoDft->itd_xfade_prev = hStereoDft->itd[k + k_offset]; + hStereoDft->itd_xfade_counter++; + } + } + else + { + /* First active frame, "reset" everything if long enough active encoding, only triggered if STEREO_DFT_ITD_CNG_XFADE_RESET = -1 */ + if ( active_frame_counter > STEREO_DFT_ITD_CNG_XFADE_RESET ) + { + hStereoDft->itd_xfade_target = hStereoDft->itd[k + k_offset]; + hStereoDft->itd_xfade_prev = hStereoDft->itd[k + k_offset]; + hStereoDft->itd_xfade_counter = 0; + } + + hStereoDft->last_active_element_brate = element_brate; + } for ( k2 = 1; k2 < hStereoDft->prm_res[k + k_offset]; k2++ ) { hStereoDft->itd[( k + k_offset ) - k2] = hStereoDft->itd[k + k_offset]; @@ -2782,6 +3050,19 @@ void stereo_dft_dec_smooth_parameters( return; } + /* Active frame, "reset" everything "reset" everything if long enough active encoding */ + if ( active_frame_counter > STEREO_DFT_ITD_CNG_XFADE_RESET ) + { + hStereoDft->itd_xfade_counter = 0; + hStereoDft->itd_xfade_target = hStereoDft->itd[STEREO_DFT_NBDIV - 1]; + hStereoDft->itd_xfade_prev = hStereoDft->itd[STEREO_DFT_NBDIV - 1]; + hStereoDft->ipd_xfade_counter = 0; + hStereoDft->ipd_xfade_target = hStereoDft->gipd[STEREO_DFT_NBDIV - 1]; + hStereoDft->ipd_xfade_prev = hStereoDft->gipd[STEREO_DFT_NBDIV - 1]; + } + + hStereoDft->last_active_element_brate = element_brate; + for ( k = hStereoDft->prm_res[k_offset] - 1; k < N_div; k += hStereoDft->prm_res[k + k_offset] ) { max_res_pred_ind = 0; diff --git a/lib_dec/ivas_stereo_dft_dec_dmx.c b/lib_dec/ivas_stereo_dft_dec_dmx.c index 48ee7cf4e67a1c77a9262be212feba8ec5f56fe6..561f9d016b1c6a69173f92b13500eaa75024a5af 100644 --- a/lib_dec/ivas_stereo_dft_dec_dmx.c +++ b/lib_dec/ivas_stereo_dft_dec_dmx.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -130,7 +130,7 @@ void stereo_dft_unify_dmx( ( st0->core == TCX_20_CORE && ( ( st0->hTcxCfg->tcx_last_overlap_mode == MIN_OVERLAP ) || ( st0->hTcxCfg->tcx_last_overlap_mode == HALF_OVERLAP ) ) ) || ( st0->core == TCX_10_CORE ); /* Smoothing for the current frame */ - stereo_dft_dec_smooth_parameters( hStereoDft, prev_sid_nodata ); + stereo_dft_dec_smooth_parameters( hStereoDft, prev_sid_nodata, st0->hFdCngDec->hFdCngCom->active_frame_counter, st0->element_brate ); for ( k = 0; k < N_div; k++ ) { diff --git a/lib_dec/ivas_stereo_dft_plc.c b/lib_dec/ivas_stereo_dft_plc.c index 34eaa2013c12cb3d400c3bfc5e7833575b5807e6..4c026dfb79cf800282b05f8c3deeb8edfa678aa0 100644 --- a/lib_dec/ivas_stereo_dft_plc.c +++ b/lib_dec/ivas_stereo_dft_plc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- * Local constants diff --git a/lib_dec/ivas_stereo_eclvq_dec.c b/lib_dec/ivas_stereo_eclvq_dec.c index 41ed8924d1e25186b0c900cb4cd63edb0b6085e8..b47c3d219ca768a924ae5590e48882da1a802219 100644 --- a/lib_dec/ivas_stereo_eclvq_dec.c +++ b/lib_dec/ivas_stereo_eclvq_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "ivas_rom_dec.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- diff --git a/lib_dec/ivas_stereo_esf_dec.c b/lib_dec/ivas_stereo_esf_dec.c index 0ab8bcdb499912d41bbae9e98fe3803883baf3c4..ff7e810e88e9993e2c374fb4237cd2f4b06878fb 100644 --- a/lib_dec/ivas_stereo_esf_dec.c +++ b/lib_dec/ivas_stereo_esf_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * init_basic_allpass() diff --git a/lib_dec/ivas_stereo_ica_dec.c b/lib_dec/ivas_stereo_ica_dec.c index 38f160ce360a573d5352dc09e8c88e7230e6a88d..b62857a8697ee25bec66d502791c6b3702f29bcc 100644 --- a/lib_dec/ivas_stereo_ica_dec.c +++ b/lib_dec/ivas_stereo_ica_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "rom_com.h" #include "ivas_rom_com.h" @@ -151,7 +151,6 @@ void stereo_tca_dec( /* IVAS_fmToDo: QCTodo: Need to address [16, 32] kHz @ Encoder --> 48 kHz Decoder. 48kHz-->48kHz is ok */ /*target_idx = (hStereoTCA->refChanIndx == L_CH_INDX) ? R_CH_INDX : L_CH_INDX;*/ -#ifdef DEC_ICA_DELAY_INTERP if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode == IVAS_CPE_TD ) { if ( hStereoTCA->corrLagStats == hStereoTCA->prevCorrLagStats && hStereoTCA->interp_dec_switch_to_zero_diff == 0 ) @@ -176,7 +175,6 @@ void stereo_tca_dec( hStereoTCA->interp_dec_prevNCShift = currentNCShift; hStereoTCA->interp_dec_switch_to_zero_diff = 0; } -#endif ref = ptrChanL; target = ptrChanR; @@ -203,11 +201,7 @@ void stereo_tca_dec( } /* target signal adjustment for temporal shift variations */ -#ifdef DEC_ICA_DELAY_INTERP if ( hStereoTCA->prevCorrLagStats != hStereoTCA->corrLagStats || bothChannelShift || ( hStereoTCA->interp_dec_switch_to_zero_diff == 1 && hCPE->element_mode == IVAS_CPE_TD ) ) -#else - if ( ( hStereoTCA->prevCorrLagStats != hStereoTCA->corrLagStats ) || bothChannelShift ) -#endif { l_shift_adapt = L_SHIFT_ADAPT_16k; if ( output_Fs > 16000 ) @@ -366,10 +360,8 @@ void stereo_tca_init_dec( hStereoTCA->corrLagStats = 0; hStereoTCA->prevCorrLagStats = 0; -#ifdef DEC_ICA_DELAY_INTERP hStereoTCA->interp_dec_prevNCShift = 0; hStereoTCA->interp_dec_switch_to_zero_diff = 0; -#endif set_f( hStereoTCA->memChanL, 0.0f, L_DEC_MEM_LEN_ICA ); set_f( hStereoTCA->memChanR, 0.0f, L_DEC_MEM_LEN_ICA ); diff --git a/lib_dec/ivas_stereo_icbwe_dec.c b/lib_dec/ivas_stereo_icbwe_dec.c index 6c3fef9eae7642edcbb106364121c02d996d04d6..78196eaaa8522dbbb31c96757d5ea3104efbb0c9 100644 --- a/lib_dec/ivas_stereo_icbwe_dec.c +++ b/lib_dec/ivas_stereo_icbwe_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "ivas_cnst.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "rom_com.h" #include "ivas_rom_com.h" #ifdef DEBUGGING diff --git a/lib_dec/ivas_stereo_mdct_core_dec.c b/lib_dec/ivas_stereo_mdct_core_dec.c index d87be7f23a050874e2128e7040f7e738ddb39608..ab8844c8e895bef1a7d5fe025b9e245b6cdee640 100644 --- a/lib_dec/ivas_stereo_mdct_core_dec.c +++ b/lib_dec/ivas_stereo_mdct_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -50,9 +50,9 @@ *-------------------------------------------------------------------------*/ static void apply_dmx_weights( CPE_DEC_HANDLE hCPE, float *x[CPE_CHANNELS][NB_DIV], int16_t transform_type_left[NB_DIV], int16_t transform_type_right[NB_DIV] ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT + static void run_min_stats( Decoder_State **sts, float *x[CPE_CHANNELS][NB_DIV] ); -#endif + /*-------------------------------------------------------------------* * convert_coeffs_to_higher_res() @@ -116,12 +116,12 @@ static void stereo_mdct_dec_stereo( sts = hCPE->hCoreCoder; - parse_stereo_from_bitstream( hCPE->hStereoMdct, hCPE->hCoreCoder, 0, hCPE->hCoreCoder[0], ms_mask ); + parse_stereo_from_bitstream( hCPE->hStereoMdct, hCPE->hCoreCoder, 0, hCPE->hStereoMdct->isSBAStereoMode, hCPE->hCoreCoder[0], ms_mask ); /*Split available bits between channels */ availableBits = sts[0]->bits_frame_channel + sts[1]->bits_frame_channel - sts[0]->next_bit_pos - sts[0]->core * ( NF_GAIN_BITS + SMDCT_MINIMUM_ARITH_BITS ) - sts[1]->core * ( NF_GAIN_BITS + SMDCT_MINIMUM_ARITH_BITS ); - splitAvailableBits( availableBits, hCPE->hStereoMdct->split_ratio, &sts[0]->bits_frame_channel, &sts[1]->bits_frame_channel ); + splitAvailableBits( availableBits, hCPE->hStereoMdct->split_ratio, hCPE->hStereoMdct->isSBAStereoMode, &sts[0]->bits_frame_channel, &sts[1]->bits_frame_channel ); sts[0]->bits_frame_channel += sts[0]->core * SMDCT_MINIMUM_ARITH_BITS; sts[1]->bits_frame_channel += sts[1]->core * SMDCT_MINIMUM_ARITH_BITS; @@ -183,7 +183,7 @@ void stereo_mdct_core_dec( float signal_out_tmp[CPE_CHANNELS][L_FRAME_PLUS]; - wmops_sub_start( "stereo_mdct_core_dec" ); + push_wmops( "stereo_mdct_core_dec" ); /*--------------------------------------------------------------------------------* * Initializations @@ -217,9 +217,15 @@ void stereo_mdct_core_dec( initMdctStereoDecData( hCPE->hStereoMdct, sts[0]->igf, sts[0]->hIGFDec->igfData.igfInfo.grid, hCPE->element_brate, sts[0]->bwidth ); + hCPE->hStereoMdct->isSBAStereoMode = ( ( st_ivas->ivas_format == SBA_FORMAT ) && ( st_ivas->nchan_transport == 2 ) ); + if ( !bfi ) { - ivas_mdct_dec_side_bits_frame_channel( hCPE, param_lpc, p_param, hCPE->hCoreCoder[0], NULL, nTnsBitsTCX10, param, 0, 0 ); + ivas_mdct_dec_side_bits_frame_channel( hCPE, param_lpc, p_param, hCPE->hCoreCoder[0], +#ifndef ISSUE_24_CLEANUP_MCT_LFE + NULL, +#endif + nTnsBitsTCX10, param, 0, 0 ); if ( sts[0]->igf ) { @@ -250,7 +256,11 @@ void stereo_mdct_core_dec( } } - ivas_mdct_core_invQ( hCPE, 0, nTnsBitsTCX10, p_param, param_lpc, param, fUseTns, tnsData, x_0, x, Aq, ms_mask, 0 ); + ivas_mdct_core_invQ( hCPE, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + 0, +#endif + nTnsBitsTCX10, p_param, param_lpc, param, fUseTns, tnsData, x_0, x, Aq, ms_mask, 0 ); for ( ch = 0; ch < nChannels; ch++ ) { @@ -287,12 +297,12 @@ void stereo_mdct_core_dec( for ( k = 0; k < nSubframes[0]; k++ ) { - if ( hCPE->hStereoMdct->IGFStereoMode[k] != SMDCT_DUAL_MONO || hCPE->hStereoMdct->mdct_stereo_mode[k] != SMDCT_DUAL_MONO ) + if ( ( hCPE->hStereoMdct->IGFStereoMode[k] != SMDCT_DUAL_MONO || hCPE->hStereoMdct->mdct_stereo_mode[k] != SMDCT_DUAL_MONO ) && !hCPE->hStereoMdct->isSBAStereoMode ) { assert( ( sts[0]->core == sts[1]->core ) || ( hCPE->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) ); /* stereo IGF decoding */ - decoder_tcx_IGF_stereo( sts, hCPE->hStereoMdct, ms_mask, x, L_frame[0], left_rect[0], k, bfi ); + decoder_tcx_IGF_stereo( sts, hCPE->hStereoMdct, ms_mask, x, L_frame[0], left_rect[0], k, bfi, 0 /* MCT_flag */ ); } else { @@ -322,37 +332,9 @@ void stereo_mdct_core_dec( sns_interpolate_scalefactors( &sns_int_scf[0], &Aq[ch][k * M], DEC ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( st->hTonalMDCTConc != NULL && ( ( k + 1 ) == nSubframes[ch] ) ) -#else - if ( st->hTonalMDCTConc != NULL ) -#endif { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - int16_t infoIGFStartLine; - - if ( st->igf == 0 ) - { - if ( st->narrowBand == 0 ) - { - /* minimum needed for output with sampling rates lower then the - nominal sampling rate */ - infoIGFStartLine = min( L_frameTCX[ch], L_frame[ch] ); - } - else - { - infoIGFStartLine = L_frameTCX[ch]; - } - } - else - { - infoIGFStartLine = min( st->hIGFDec->infoIGFStartLine, L_frameTCX[ch] ); - } - - TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0], infoIGFStartLine ); -#else - TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0] ); -#endif + TonalMDCTConceal_SaveFreqSignal( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0], get_igf_startline( st, L_frame[ch], L_frameTCX[ch] ) ); } } @@ -363,32 +345,37 @@ void stereo_mdct_core_dec( mvs2s( ms_mask[1], hCPE->hStereoMdct->prev_ms_mask[1], MAX_SFB ); } - if ( !bfi || !( sts[0]->core == ACELP_CORE && sts[1]->core == ACELP_CORE ) ) + if ( ( !bfi || !( sts[0]->core == ACELP_CORE && sts[1]->core == ACELP_CORE ) ) && !hCPE->hStereoMdct->isSBAStereoMode ) { #ifdef DEBUGGING assert( ( sts[0]->core == sts[1]->core ) || ( ( hCPE->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) && ( hCPE->hStereoMdct->mdct_stereo_mode[1] == SMDCT_DUAL_MONO ) ) ); #endif - stereo_decoder_tcx( hCPE->hStereoMdct, ms_mask, x_0[1], x[0], x[1], &hCPE->hStereoMdct->mdct_stereo_mode[0], - sts[0]->core, sts[1]->core, sts[0]->igf, L_frameTCX[0], 0, sts[0]->last_core, sts[1]->last_core, 0 ); + stereo_decoder_tcx( hCPE->hStereoMdct, ms_mask, x_0[1], x[0], x[1], &hCPE->hStereoMdct->mdct_stereo_mode[0], sts[0]->core, sts[1]->core, sts[0]->igf, L_frameTCX[0], L_frameTCX[1], 0, sts[0]->last_core, sts[1]->last_core, 0 ); } - ivas_mdct_core_tns_ns( hCPE, 0, fUseTns, tnsData, x, Aq, 0 ); + ivas_mdct_core_tns_ns( hCPE, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + 0, +#endif + fUseTns, tnsData, x, Aq, 0 ); - if ( st_ivas != NULL && st_ivas->renderer_type == RENDERER_MC_PARAMMC && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) ) + if ( st_ivas->renderer_type == RENDERER_MC_PARAMMC && ( st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == AUDIO_CONFIG_STEREO ) ) { ivas_ls_setup_conversion_process_mdct_param_mc( st_ivas, x ); } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT run_min_stats( sts, x ); -#endif if ( hCPE->nchan_out == 1 && ( !bfi || ( bfi && sts[0]->core != ACELP_CORE && sts[1]->core != ACELP_CORE ) ) ) { apply_dmx_weights( hCPE, x, sts[0]->transform_type, sts[1]->transform_type ); } - ivas_mdct_core_reconstruct( hCPE, x, signal_outFB_tmp, 0, fUseTns, 0 ); + ivas_mdct_core_reconstruct( hCPE, x, signal_outFB_tmp, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + 0, +#endif + fUseTns, 0 ); mvr2r( signal_out_tmp[0], signal_out[0], L_FRAME48k ); mvr2r( signal_out_tmp[1], signal_out[1], L_FRAME48k ); @@ -396,7 +383,7 @@ void stereo_mdct_core_dec( mvr2r( signal_outFB_tmp[0], signal_outFB[0], hCPE->hCoreCoder[0]->hTcxDec->L_frameTCX ); mvr2r( signal_outFB_tmp[1], signal_outFB[1], hCPE->hCoreCoder[1]->hTcxDec->L_frameTCX ); - wmops_sub_end(); + pop_wmops(); return; } @@ -600,7 +587,6 @@ static void apply_dmx_weights( return; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT /*-------------------------------------------------------------------* * run_min_stats() * @@ -679,5 +665,6 @@ static void run_min_stats( /* restore VAD (see above) */ st->VAD = save_VAD[ch]; } + + return; } -#endif diff --git a/lib_dec/ivas_stereo_mdct_stereo_dec.c b/lib_dec/ivas_stereo_mdct_stereo_dec.c index 298e77a131f3d6d5fdb1db860e3120cfb6c396d1..cccef8ec84b5553b7761be21f3f2ee9f3ccd9c41 100644 --- a/lib_dec/ivas_stereo_mdct_stereo_dec.c +++ b/lib_dec/ivas_stereo_mdct_stereo_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include "ivas_cnst.h" #include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -57,6 +57,7 @@ void parse_stereo_from_bitstream( STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo decoder structure */ Decoder_State **sts, /* i/o: decoder state structure */ const int16_t mct_on, /* i : flag mct block (1) or stereo (0)*/ + const int16_t isSBAStereoMode, /* i : flag core coding for SBA */ Decoder_State *st0, /* i/o: decoder state structure for Bstr*/ int16_t ms_mask[NB_DIV][MAX_SFB] /* o : bandwise MS mask */ ) @@ -67,110 +68,113 @@ void parse_stereo_from_bitstream( int16_t nbits_start = st0->next_bit_pos; #endif - nSubframes = ( sts[0]->core == TCX_10_CORE || ( sts[0]->core != sts[1]->core ) ) ? NB_DIV : 1; - sfbConf = ( sts[0]->core == TCX_20_CORE ) ? &hStereoMdct->stbParamsTCX20 : &hStereoMdct->stbParamsTCX10; - if ( sts[0]->last_core_from_bs == ACELP_CORE ) + if ( !isSBAStereoMode ) { - sfbConf = &hStereoMdct->stbParamsTCX20afterACELP; - } - - if ( hStereoMdct->use_itd ) - { - int16_t I; - - hStereoMdct->itd_mode = get_next_indice( st0, STEREO_DFT_ITD_MODE_NBITS ); - /*(*nb_bits) += STEREO_DFT_ITD_MODE_NBITS;*/ /*ITD mode flag: 1bit*/ - - hStereoMdct->itd = 0.f; - if ( hStereoMdct->itd_mode ) + nSubframes = ( sts[0]->core == TCX_10_CORE || ( sts[0]->core != sts[1]->core ) ) ? NB_DIV : 1; + sfbConf = ( sts[0]->core == TCX_20_CORE ) ? &hStereoMdct->stbParamsTCX20 : &hStereoMdct->stbParamsTCX10; + if ( sts[0]->last_core_from_bs == ACELP_CORE ) { - /*(*nb_bits) += */ read_itd( st0, &I ); - stereo_dft_dequantize_itd( &I, &hStereoMdct->itd, st0->output_Fs ); + sfbConf = &hStereoMdct->stbParamsTCX20afterACELP; } - } - for ( k = 0; k < nSubframes; k++ ) - { - mdct_stereo_mode = get_next_indice( st0, 1 ); - if ( mdct_stereo_mode ) - { - mdct_stereo_mode = 1 + get_next_indice( st0, 1 ); - } - switch ( mdct_stereo_mode ) + if ( hStereoMdct->use_itd ) { - case 0: - hStereoMdct->mdct_stereo_mode[k] = SMDCT_DUAL_MONO; - break; - case 1: - hStereoMdct->mdct_stereo_mode[k] = SMDCT_MS_FULL; - break; - case 2: - hStereoMdct->mdct_stereo_mode[k] = SMDCT_BW_MS; - break; - default: - assert( !"Not supported stereo mode\n" ); - } + int16_t I; - if ( !mct_on ) - { - if ( sts[0]->core == sts[1]->core || k == 0 ) - { - hStereoMdct->global_ild[k] = get_next_indice( st0, SMDCT_GLOBAL_ILD_BITS ); - assert( ( hStereoMdct->global_ild[k] > 0 ) && ( hStereoMdct->global_ild[k] < SMDCT_ILD_RANGE ) ); - } - else - { - hStereoMdct->global_ild[1] = hStereoMdct->global_ild[0]; - } - } - - set_s( ms_mask[k], ( hStereoMdct->mdct_stereo_mode[k] == SMDCT_MS_FULL ) ? 1 : 0, sfbConf->nBandsStereoCore ); + hStereoMdct->itd_mode = get_next_indice( st0, STEREO_DFT_ITD_MODE_NBITS ); + /*(*nb_bits) += STEREO_DFT_ITD_MODE_NBITS;*/ /*ITD mode flag: 1bit*/ - if ( hStereoMdct->mdct_stereo_mode[k] == SMDCT_BW_MS ) - { - for ( i = 0; i < sfbConf->nBandsStereoCore; i++ ) + hStereoMdct->itd = 0.f; + if ( hStereoMdct->itd_mode ) { - ms_mask[k][i] = get_next_indice( st0, 1 ); + /*(*nb_bits) += */ read_itd( st0, &I ); + stereo_dft_dequantize_itd( &I, &hStereoMdct->itd, st0->output_Fs ); } } - if ( st0->igf ) + for ( k = 0; k < nSubframes; k++ ) { - mdct_stereo_mode = get_next_indice( st0, 1 ); if ( mdct_stereo_mode ) { mdct_stereo_mode = 1 + get_next_indice( st0, 1 ); } - switch ( mdct_stereo_mode ) { case 0: - hStereoMdct->IGFStereoMode[k] = SMDCT_DUAL_MONO; + hStereoMdct->mdct_stereo_mode[k] = SMDCT_DUAL_MONO; break; case 1: - hStereoMdct->IGFStereoMode[k] = SMDCT_MS_FULL; + hStereoMdct->mdct_stereo_mode[k] = SMDCT_MS_FULL; break; case 2: - hStereoMdct->IGFStereoMode[k] = SMDCT_BW_MS; + hStereoMdct->mdct_stereo_mode[k] = SMDCT_BW_MS; break; default: assert( !"Not supported stereo mode\n" ); } - set_s( &ms_mask[k][sfbConf->nBandsStereoCore], ( hStereoMdct->IGFStereoMode[k] == SMDCT_MS_FULL ) ? 1 : 0, sfbConf->sfbCnt - sfbConf->nBandsStereoCore ); + if ( !mct_on ) + { + if ( sts[0]->core == sts[1]->core || k == 0 ) + { + hStereoMdct->global_ild[k] = get_next_indice( st0, SMDCT_GLOBAL_ILD_BITS ); + assert( ( hStereoMdct->global_ild[k] > 0 ) && ( hStereoMdct->global_ild[k] < SMDCT_ILD_RANGE ) ); + } + else + { + hStereoMdct->global_ild[1] = hStereoMdct->global_ild[0]; + } + } + + set_s( ms_mask[k], ( hStereoMdct->mdct_stereo_mode[k] == SMDCT_MS_FULL ) ? 1 : 0, sfbConf->nBandsStereoCore ); - if ( hStereoMdct->IGFStereoMode[k] == SMDCT_BW_MS ) + if ( hStereoMdct->mdct_stereo_mode[k] == SMDCT_BW_MS ) { - for ( i = sfbConf->nBandsStereoCore; i < sfbConf->sfbCnt; i++ ) + for ( i = 0; i < sfbConf->nBandsStereoCore; i++ ) { ms_mask[k][i] = get_next_indice( st0, 1 ); } } - } - else - { - hStereoMdct->IGFStereoMode[k] = SMDCT_DUAL_MONO; + + if ( st0->igf ) + { + + mdct_stereo_mode = get_next_indice( st0, 1 ); + if ( mdct_stereo_mode ) + { + mdct_stereo_mode = 1 + get_next_indice( st0, 1 ); + } + + switch ( mdct_stereo_mode ) + { + case 0: + hStereoMdct->IGFStereoMode[k] = SMDCT_DUAL_MONO; + break; + case 1: + hStereoMdct->IGFStereoMode[k] = SMDCT_MS_FULL; + break; + case 2: + hStereoMdct->IGFStereoMode[k] = SMDCT_BW_MS; + break; + default: + assert( !"Not supported stereo mode\n" ); + } + + set_s( &ms_mask[k][sfbConf->nBandsStereoCore], ( hStereoMdct->IGFStereoMode[k] == SMDCT_MS_FULL ) ? 1 : 0, sfbConf->sfbCnt - sfbConf->nBandsStereoCore ); + + if ( hStereoMdct->IGFStereoMode[k] == SMDCT_BW_MS ) + { + for ( i = sfbConf->nBandsStereoCore; i < sfbConf->sfbCnt; i++ ) + { + ms_mask[k][i] = get_next_indice( st0, 1 ); + } + } + } + else + { + hStereoMdct->IGFStereoMode[k] = SMDCT_DUAL_MONO; + } } } @@ -212,7 +216,8 @@ void stereo_decoder_tcx( const int16_t core_l, /* i : core for left channel (TCX20/TCX10) */ const int16_t core_r, /* i : core for right channel (TCX20/TCX10) */ const int16_t igf, /* i : flag for IGF activity */ - const int16_t L_frame, /* i : TCX frame length */ + const int16_t L_frameTCX_l, /* i : TCX frame length of left channel */ + const int16_t L_frameTCX_r, /* i : TCX frame length of right channel */ const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ const int16_t last_core_l, /* i : last core for left channel */ const int16_t last_core_r, /* i : last core for right channel */ @@ -324,13 +329,13 @@ void stereo_decoder_tcx( hStereoMdct->reverse_dmx = 0; } - if ( ( nrgRatio > 1.0f ) && ( k < ( ( core_r == TCX_20_CORE ) ? 1 : NB_DIV ) ) ) + if ( ( nrgRatio > 1.0f ) && ( k < ( ( core_r == TCX_10_CORE ) ? NB_DIV : 1 ) ) ) { - v_multc( spec_r[k], nrgRatio, spec_r[k], L_frame / ( ( core_r == TCX_20_CORE ) ? 1 : NB_DIV ) ); + v_multc( spec_r[k], nrgRatio, spec_r[k], L_frameTCX_r ); } - else if ( ( nrgRatio < 1.0f ) && ( k < ( ( core_l == TCX_20_CORE ) ? 1 : NB_DIV ) ) ) + else if ( ( nrgRatio < 1.0f ) && ( k < ( ( core_l == TCX_10_CORE ) ? NB_DIV : 1 ) ) ) { - v_multc( spec_l[k], 1.0f / nrgRatio, spec_l[k], L_frame / ( ( core_l == TCX_20_CORE ) ? 1 : NB_DIV ) ); + v_multc( spec_l[k], 1.0f / nrgRatio, spec_l[k], L_frameTCX_l ); } } } /* for k */ @@ -461,10 +466,9 @@ ivas_error initMdctStereoDtxData( return error; } - /* Init FD-CNG */ initFdCngDec( st ); - if ( ( ch == 1 ) && ( st->cng_spar_flag == 1 ) ) + if ( ch == 1 && st->cng_sba_flag ) { st->hFdCngDec->hFdCngCom->seed += 3; } @@ -558,13 +562,13 @@ void updateBuffersForDmxMdctStereo( sts[1] = hCPE->hCoreCoder[1]; /* synch buffers for inactive frames, but not for transition frames */ - if ( hCPE->last_element_brate <= IVAS_SID_4k4 ) + if ( hCPE->last_element_brate <= IVAS_SID_5k2 ) { mvr2r( output[0], output[1], output_frame ); mvr2r( synth[0], synth[1], output_frame ); } - if ( hCPE->element_brate == IVAS_SID_4k4 && hCPE->last_element_brate > IVAS_SID_4k4 ) + if ( hCPE->element_brate == IVAS_SID_5k2 && hCPE->last_element_brate > IVAS_SID_5k2 ) { /* in the first SID frame after an active frame, create mid noise shape here, in SID frames that follow inactive frames, it is done directly in the SID decoding since the mid shape is being used in CNG then */ for ( int16_t p = 0; p < sts[0]->hFdCngDec->hFdCngCom->npart; p++ ) @@ -574,7 +578,7 @@ void updateBuffersForDmxMdctStereo( } /* for transition of active->inactive frame, apply passive downmix on buffers */ - if ( hCPE->last_element_brate <= IVAS_SID_4k4 ) + if ( hCPE->last_element_brate <= IVAS_SID_5k2 ) { delta = 1; if ( output_frame == L_FRAME16k ) @@ -640,20 +644,20 @@ void applyDmxMdctStereo( fade = 1.f; dmx_len = output_frame; - if ( hCPE->last_element_brate <= IVAS_SID_4k4 ) + if ( hCPE->last_element_brate <= IVAS_SID_5k2 ) { crossfade_len = NS2SA( hCPE->hCoreCoder[0]->output_Fs, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ); step /= crossfade_len; } /* for first inactive CNG frame after active decoding we have to do a fade-OUT FROM the passive DMX */ - else if ( hCPE->element_brate <= IVAS_SID_4k4 && hCPE->last_element_brate > IVAS_SID_4k4 ) + else if ( hCPE->element_brate <= IVAS_SID_5k2 && hCPE->last_element_brate > IVAS_SID_5k2 ) { crossfade_len = output_frame / 4; step /= -crossfade_len; fade = 0.f; dmx_len = crossfade_len; } - else if ( hCPE->last_element_mode == IVAS_CPE_DFT && hCPE->last_element_brate <= IVAS_24k4 ) + else if ( hCPE->last_element_mode == IVAS_CPE_DFT && hCPE->last_element_brate <= IVAS_32k ) { crossfade_len = NS2SA( hCPE->hCoreCoder[0]->output_Fs, DELAY_CLDFB_NS ); step /= crossfade_len; diff --git a/lib_dec/ivas_stereo_switching_dec.c b/lib_dec/ivas_stereo_switching_dec.c index e4c5021dbc03c5eaf3e9a668b28db5dfc90f2ca9..144f7950e976bf44af0a64acd3b43dd84ea68b74 100644 --- a/lib_dec/ivas_stereo_switching_dec.c +++ b/lib_dec/ivas_stereo_switching_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,8 @@ #include "prot.h" #include "ivas_prot.h" #include "ivas_rom_com.h" -#include "wmops.h" +#include "assert.h" +#include "wmc_auto.h" #include @@ -56,7 +57,7 @@ static ivas_error allocate_CoreCoder_TCX( { if ( st->hTcxDec == NULL ) { - if ( ( st->hTcxDec = (TCX_DEC_HANDLE) count_malloc( sizeof( TCX_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTcxDec = (TCX_DEC_HANDLE) malloc( sizeof( TCX_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for hTcxDec" ) ); } @@ -70,7 +71,7 @@ static ivas_error allocate_CoreCoder_TCX( if ( st->hTcxCfg == NULL ) { - if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) count_malloc( sizeof( TCX_config ) ) ) == NULL ) + if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for hTcxCfg" ) ); } @@ -79,7 +80,7 @@ static ivas_error allocate_CoreCoder_TCX( /* allocated TCX-LTP structure for second channel */ if ( st->hTcxLtpDec == NULL ) { - if ( ( st->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) count_malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for TCX-LTP handle\n" ) ); } @@ -90,7 +91,7 @@ static ivas_error allocate_CoreCoder_TCX( /* allocate HQ structure */ if ( st->hHQ_core == NULL ) { - if ( ( st->hHQ_core = (HQ_DEC_HANDLE) count_malloc( sizeof( HQ_DEC_DATA ) ) ) == NULL ) + if ( ( st->hHQ_core = (HQ_DEC_HANDLE) malloc( sizeof( HQ_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for HQ core\n" ) ); } @@ -100,7 +101,7 @@ static ivas_error allocate_CoreCoder_TCX( if ( st->hIGFDec == NULL ) { - if ( ( st->hIGFDec = (IGF_DEC_INSTANCE_HANDLE) count_malloc( sizeof( IGFDEC_INSTANCE ) ) ) == NULL ) + if ( ( st->hIGFDec = (IGF_DEC_INSTANCE_HANDLE) malloc( sizeof( IGFDEC_INSTANCE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IGF\n" ) ); } @@ -111,7 +112,7 @@ static ivas_error allocate_CoreCoder_TCX( if ( st->hTonalMDCTConc == NULL ) { - if ( ( st->hTonalMDCTConc = (TonalMDCTConcealPtr) count_malloc( sizeof( TonalMDCTConceal_INSTANCE ) ) ) == NULL ) + if ( ( st->hTonalMDCTConc = (TonalMDCTConcealPtr) malloc( sizeof( TonalMDCTConceal_INSTANCE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for TonalMDCTConcealment\n" ) ); } @@ -140,7 +141,7 @@ static ivas_error allocate_CoreCoder( if ( st->hGSCDec == NULL ) { - if ( ( st->hGSCDec = (GSC_DEC_HANDLE) count_malloc( sizeof( GSC_DEC_DATA ) ) ) == NULL ) + if ( ( st->hGSCDec = (GSC_DEC_HANDLE) malloc( sizeof( GSC_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for GSC\n" ) ); } @@ -150,7 +151,7 @@ static ivas_error allocate_CoreCoder( if ( st->hPFstat == NULL ) { - if ( ( st->hPFstat = (PFSTAT_HANDLE) count_malloc( sizeof( PFSTAT ) ) ) == NULL ) + if ( ( st->hPFstat = (PFSTAT_HANDLE) malloc( sizeof( PFSTAT ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for NB/formant postflter\n" ) ); } @@ -161,7 +162,7 @@ static ivas_error allocate_CoreCoder( if ( st->hMusicPF == NULL ) { - if ( ( st->hMusicPF = (MUSIC_POSTFILT_HANDLE) count_malloc( sizeof( MUSIC_POSTFILT_DATA ) ) ) == NULL ) + if ( ( st->hMusicPF = (MUSIC_POSTFILT_HANDLE) malloc( sizeof( MUSIC_POSTFILT_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LD music postflter\n" ) ); } @@ -171,7 +172,7 @@ static ivas_error allocate_CoreCoder( if ( st->hBPF == NULL ) { - if ( ( st->hBPF = (BPF_DEC_HANDLE) count_malloc( sizeof( BPF_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBPF = (BPF_DEC_HANDLE) malloc( sizeof( BPF_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for BPF\n" ) ); } @@ -181,7 +182,7 @@ static ivas_error allocate_CoreCoder( if ( st->hBWE_zero == NULL ) { - if ( ( st->hBWE_zero = (ZERO_BWE_DEC_HANDLE) count_malloc( sizeof( ZERO_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_zero = (ZERO_BWE_DEC_HANDLE) malloc( sizeof( ZERO_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for zero BWE\n" ) ); } @@ -223,25 +224,25 @@ static void deallocate_CoreCoder_TCX( { if ( st->hTcxDec != NULL ) { - count_free( st->hTcxDec ); + free( st->hTcxDec ); st->hTcxDec = NULL; } if ( st->hTcxCfg != NULL ) { - count_free( st->hTcxCfg ); + free( st->hTcxCfg ); st->hTcxCfg = NULL; } if ( st->hIGFDec != NULL ) { - count_free( st->hIGFDec ); + free( st->hIGFDec ); st->hIGFDec = NULL; } if ( st->hTonalMDCTConc != NULL ) { - count_free( st->hTonalMDCTConc ); + free( st->hTonalMDCTConc ); st->hTonalMDCTConc = NULL; } @@ -261,31 +262,31 @@ static void deallocate_CoreCoder( { if ( st->hGSCDec != NULL ) { - count_free( st->hGSCDec ); + free( st->hGSCDec ); st->hGSCDec = NULL; } if ( st->hPFstat != NULL ) { - count_free( st->hPFstat ); + free( st->hPFstat ); st->hPFstat = NULL; } if ( st->hMusicPF != NULL ) { - count_free( st->hMusicPF ); + free( st->hMusicPF ); st->hMusicPF = NULL; } if ( st->hBPF != NULL ) { - count_free( st->hBPF ); + free( st->hBPF ); st->hBPF = NULL; } if ( st->hBWE_zero != NULL ) { - count_free( st->hBWE_zero ); + free( st->hBWE_zero ); st->hBWE_zero = NULL; } @@ -342,6 +343,7 @@ ivas_error stereo_memory_dec( const int16_t nb_bits_metadata, /* i : number of metadata bits */ const int32_t output_Fs, /* i : output sampling rate */ const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const MC_MODE mc_mode, /* i : MC mode */ const int16_t nchan_transport /* i : number of transport channels*/ ) { @@ -351,6 +353,9 @@ ivas_error stereo_memory_dec( error = IVAS_ERR_OK; + assert( hCPE->last_element_mode >= IVAS_CPE_DFT && "Switching from SCE to CPE is not a valid configuration!" ); + + hCPE->hCoreCoder[0]->element_mode = hCPE->element_mode; hCPE->hCoreCoder[1]->element_mode = hCPE->element_mode; @@ -402,13 +407,13 @@ ivas_error stereo_memory_dec( /* deallocate data structure of the previous CPE mode */ if ( hCPE->hStereoTD != NULL ) { - count_free( hCPE->hStereoTD ); + free( hCPE->hStereoTD ); hCPE->hStereoTD = NULL; } if ( hCPE->hStereoMdct != NULL ) { - count_free( hCPE->hStereoMdct ); + free( hCPE->hStereoMdct ); hCPE->hStereoMdct = NULL; } @@ -416,7 +421,8 @@ ivas_error stereo_memory_dec( deallocate_CoreCoder( hCPE->hCoreCoder[1] ); /* allocate DFT stereo data structure */ - if ( ( error = stereo_dft_dec_create( &( hCPE->hStereoDft ), hCPE->element_brate, output_Fs, 0 ) ) != IVAS_ERR_OK ) + if ( ( error = stereo_dft_dec_create( &( hCPE->hStereoDft ), hCPE->element_brate, output_Fs, 0, + nchan_transport ) ) != IVAS_ERR_OK ) { return error; } @@ -424,9 +430,7 @@ ivas_error stereo_memory_dec( if ( hCPE->last_element_mode == IVAS_CPE_MDCT ) { cpy_tcx_ltp_data( hCPE->hCoreCoder[1]->hTcxLtpDec, hCPE->hStereoDft->hTcxLtpDec, output_Fs ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT deleteFdCngDec( &hCPE->hCoreCoder[1]->hFdCngDec ); -#endif } /* memory update - needed in TD stereo, TCX/HQ frame -> DFT stereo, ACELP frame switching */ @@ -435,7 +439,7 @@ ivas_error stereo_memory_dec( /* allocate ICBWE structure */ if ( hCPE->hStereoICBWE == NULL ) { - if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) count_malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); } @@ -447,7 +451,7 @@ ivas_error stereo_memory_dec( st = hCPE->hCoreCoder[0]; if ( st->hHQ_core == NULL ) { - if ( ( st->hHQ_core = (HQ_DEC_HANDLE) count_malloc( sizeof( HQ_DEC_DATA ) ) ) == NULL ) + if ( ( st->hHQ_core = (HQ_DEC_HANDLE) malloc( sizeof( HQ_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ core\n" ) ); } @@ -458,7 +462,7 @@ ivas_error stereo_memory_dec( /* allocate TD CNG handle */ if ( st->idchan == 0 && st->hTdCngDec == NULL ) { - if ( ( st->hTdCngDec = (TD_CNG_DEC_HANDLE) count_malloc( sizeof( TD_CNG_DEC_DATA ) ) ) == NULL ) + if ( ( st->hTdCngDec = (TD_CNG_DEC_HANDLE) malloc( sizeof( TD_CNG_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n" ) ); } @@ -482,19 +486,17 @@ ivas_error stereo_memory_dec( if ( hCPE->hStereoMdct != NULL ) { - count_free( hCPE->hStereoMdct ); + free( hCPE->hStereoMdct ); hCPE->hStereoMdct = NULL; } /* deallocated TCX/IGF structures for second channel */ deallocate_CoreCoder_TCX( hCPE->hCoreCoder[1] ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT if ( hCPE->last_element_mode == IVAS_CPE_MDCT ) { deleteFdCngDec( &hCPE->hCoreCoder[1]->hFdCngDec ); } -#endif /* allocate TD stereo data structure */ if ( hCPE->hStereoTD != NULL ) @@ -502,7 +504,7 @@ ivas_error stereo_memory_dec( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: TD Stereo memory already allocated\n" ); } - if ( ( hCPE->hStereoTD = (STEREO_TD_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_TD_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTD = (STEREO_TD_DEC_DATA_HANDLE) malloc( sizeof( STEREO_TD_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) ); } @@ -526,7 +528,7 @@ ivas_error stereo_memory_dec( st = hCPE->hCoreCoder[1]; if ( st->hTcxLtpDec != 0 ) { - count_free( st->hTcxLtpDec ); + free( st->hTcxLtpDec ); st->hTcxLtpDec = NULL; } @@ -542,14 +544,14 @@ ivas_error stereo_memory_dec( /* deallocated HQ-core for second channel */ if ( st->hHQ_core != 0 ) { - count_free( st->hHQ_core ); + free( st->hHQ_core ); st->hHQ_core = NULL; } /* allocate DFT stereo mono DMX data structure */ if ( hCPE->nchan_out == 1 && hCPE->hStereoDftDmx == NULL ) { - if ( ( hCPE->hStereoDftDmx = (STEREO_DFT_DMX_DATA_HANDLE) count_malloc( sizeof( STEREO_DFT_DMX_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoDftDmx = (STEREO_DFT_DMX_DATA_HANDLE) malloc( sizeof( STEREO_DFT_DMX_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo DFT mono output\n" ) ); } @@ -559,7 +561,7 @@ ivas_error stereo_memory_dec( /* allocate TCA data structure */ if ( hCPE->nchan_out != 1 && hCPE->hStereoTCA == NULL ) { - if ( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) count_malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); } @@ -578,14 +580,14 @@ ivas_error stereo_memory_dec( /* allocate BWEs for primary channel */ if ( st->hBWE_TD == NULL ) { - if ( ( st->hBWE_TD = (TD_BWE_DEC_HANDLE) count_malloc( sizeof( TD_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_TD = (TD_BWE_DEC_HANDLE) malloc( sizeof( TD_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); } td_bwe_dec_init( st->hBWE_TD, -1, st->output_Fs ); - if ( ( st->hBWE_FD = (FD_BWE_DEC_HANDLE) count_malloc( sizeof( FD_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_FD = (FD_BWE_DEC_HANDLE) malloc( sizeof( FD_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); } @@ -608,7 +610,7 @@ ivas_error stereo_memory_dec( /* allocate stereo CNG structure */ if ( hCPE->hStereoCng == NULL ) { - if ( ( hCPE->hStereoCng = (STEREO_CNG_DEC_HANDLE) count_malloc( sizeof( STEREO_CNG_DEC ) ) ) == NULL ) + if ( ( hCPE->hStereoCng = (STEREO_CNG_DEC_HANDLE) malloc( sizeof( STEREO_CNG_DEC ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo CNG\n" ) ); } @@ -644,26 +646,26 @@ ivas_error stereo_memory_dec( if ( hCPE->hStereoTD != NULL ) { - count_free( hCPE->hStereoTD ); + free( hCPE->hStereoTD ); hCPE->hStereoTD = NULL; } if ( hCPE->hStereoDftDmx != NULL ) { - count_free( hCPE->hStereoDftDmx ); + free( hCPE->hStereoDftDmx ); hCPE->hStereoDftDmx = NULL; } if ( hCPE->hStereoICBWE != NULL ) { - count_free( hCPE->hStereoICBWE ); + free( hCPE->hStereoICBWE ); hCPE->hStereoICBWE = NULL; } /* de-allocate stereo CNG structure */ if ( hCPE->hStereoCng != NULL ) { - count_free( hCPE->hStereoCng ); + free( hCPE->hStereoCng ); hCPE->hStereoCng = NULL; } @@ -675,10 +677,6 @@ ivas_error stereo_memory_dec( /* deallocate core-decoder substructures */ deallocate_CoreCoder( st ); -#ifndef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - /* deallocate FD_CNG substructure */ - deleteFdCngDec( &st->hFdCngDec ); -#endif st->first_CNG = 0; } @@ -702,7 +700,6 @@ ivas_error stereo_memory_dec( } } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT /* allocate Fd-Cng structure for second channel */ if ( ( error = createFdCngDec( &st->hFdCngDec ) ) != IVAS_ERR_OK ) { @@ -711,7 +708,6 @@ ivas_error stereo_memory_dec( /* Init FD-CNG */ initFdCngDec( st ); -#endif if ( hCPE->last_element_mode == IVAS_CPE_DFT ) { @@ -726,7 +722,14 @@ ivas_error stereo_memory_dec( if ( hCPE->last_element_mode == IVAS_CPE_DFT ) { - cpy_tcx_ltp_data( &tcxLtpTmp, hCPE->hCoreCoder[1]->hTcxLtpDec, output_Fs ); + if ( hCPE->nchan_out == 1 ) + { + cpy_tcx_ltp_data( hCPE->hCoreCoder[0]->hTcxLtpDec, hCPE->hCoreCoder[1]->hTcxLtpDec, output_Fs ); + } + else + { + cpy_tcx_ltp_data( &tcxLtpTmp, hCPE->hCoreCoder[1]->hTcxLtpDec, output_Fs ); + } } if ( hCPE->last_element_mode == IVAS_CPE_TD ) @@ -739,7 +742,7 @@ ivas_error stereo_memory_dec( st->hTcxDec->prev_good_synth = st->hTcxDec->old_synthFB + NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ); /* allocate and initialize MDCT stereo structure */ - if ( ( hCPE->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); } @@ -772,21 +775,21 @@ ivas_error stereo_memory_dec( /* deallocate ICBWE structure */ if ( hCPE->hStereoICBWE != NULL ) { - count_free( hCPE->hStereoICBWE ); + free( hCPE->hStereoICBWE ); hCPE->hStereoICBWE = NULL; } /* allocate BWEs for secondary channel */ if ( st->hBWE_TD == NULL ) { - if ( ( st->hBWE_TD = (TD_BWE_DEC_HANDLE) count_malloc( sizeof( TD_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_TD = (TD_BWE_DEC_HANDLE) malloc( sizeof( TD_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); } td_bwe_dec_init( st->hBWE_TD, -1, st->output_Fs ); - if ( ( st->hBWE_FD = (FD_BWE_DEC_HANDLE) count_malloc( sizeof( FD_BWE_DEC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_FD = (FD_BWE_DEC_HANDLE) malloc( sizeof( FD_BWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); } @@ -801,13 +804,13 @@ ivas_error stereo_memory_dec( { if ( st->hBWE_TD != NULL ) { - count_free( st->hBWE_TD ); + free( st->hBWE_TD ); st->hBWE_TD = NULL; } if ( st->hBWE_FD != NULL ) { - count_free( st->hBWE_FD ); + free( st->hBWE_FD ); st->hBWE_FD = NULL; } } @@ -815,7 +818,7 @@ ivas_error stereo_memory_dec( /* allocate ICBWE structure */ if ( hCPE->hStereoICBWE == NULL ) { - if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) count_malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); } @@ -832,14 +835,14 @@ ivas_error stereo_memory_dec( if ( ivas_format == STEREO_FORMAT && hCPE->element_mode == IVAS_CPE_MDCT ) { - if ( hCPE->element_brate <= MAX_MDCT_ITD_BRATE && ivas_total_brate > IVAS_SID_4k4 ) + if ( hCPE->element_brate <= MAX_MDCT_ITD_BRATE && ivas_total_brate > IVAS_SID_5k2 ) { if ( hCPE->hStereoMdct->use_itd == 0 ) { if ( hCPE->hStereoTCA == NULL ) { /* allocate TCA data structure */ - if ( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) count_malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); } @@ -852,13 +855,13 @@ ivas_error stereo_memory_dec( else { /* de-allocate TCA data structure */ - if ( hCPE->hStereoMdct->use_itd == 1 && ivas_total_brate > IVAS_SID_4k4 && hCPE->hStereoTCA != NULL ) + if ( hCPE->hStereoMdct->use_itd == 1 && ivas_total_brate > IVAS_SID_5k2 && hCPE->hStereoTCA != NULL ) { - count_free( hCPE->hStereoTCA ); + free( hCPE->hStereoTCA ); hCPE->hStereoTCA = NULL; hCPE->hStereoMdct->use_itd = 0; } - else if ( hCPE->hStereoMdct->use_itd == 1 && ivas_total_brate <= IVAS_SID_4k4 ) + else if ( hCPE->hStereoMdct->use_itd == 1 && ivas_total_brate <= IVAS_SID_5k2 ) { hCPE->hStereoMdct->itd = 0.0f; } @@ -879,7 +882,7 @@ ivas_error stereo_memory_dec( { if ( hCPE->hStereoDftDmx == NULL ) { - if ( ( hCPE->hStereoDftDmx = (STEREO_DFT_DMX_DATA_HANDLE) count_malloc( sizeof( STEREO_DFT_DMX_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoDftDmx = (STEREO_DFT_DMX_DATA_HANDLE) malloc( sizeof( STEREO_DFT_DMX_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo DFT mono output\n" ) ); } @@ -888,27 +891,115 @@ ivas_error stereo_memory_dec( if ( hCPE->prev_synth_chs[1] != NULL ) { - count_free( hCPE->prev_synth_chs[1] ); + free( hCPE->prev_synth_chs[1] ); hCPE->prev_synth_chs[1] = NULL; } + + if ( hCPE->hStereoTCA != NULL ) + { + free( hCPE->hStereoTCA ); + hCPE->hStereoTCA = NULL; + } } else /* nchan_out == 2 */ { if ( hCPE->hStereoDftDmx != NULL ) { - count_free( hCPE->hStereoDftDmx ); + free( hCPE->hStereoDftDmx ); hCPE->hStereoDftDmx = NULL; } if ( hCPE->prev_synth_chs[1] == NULL ) { st = hCPE->hCoreCoder[1]; - if ( ( hCPE->prev_synth_chs[1] = (float *) count_malloc( sizeof( float ) * NS2SA( st->output_Fs, FRAME_SIZE_NS ) ) ) == NULL ) + if ( ( hCPE->prev_synth_chs[1] = (float *) malloc( sizeof( float ) * NS2SA( st->output_Fs, FRAME_SIZE_NS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } set_zero( hCPE->prev_synth_chs[1], NS2SA( st->output_Fs, FRAME_SIZE_NS ) ); } + + if ( hCPE->hStereoICBWE == NULL && hCPE->element_mode == IVAS_CPE_DFT ) + { + if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); + } + + stereo_icBWE_init_dec( hCPE->hStereoICBWE ); + } + + if ( hCPE->hStereoTCA == NULL && ( hCPE->element_mode == IVAS_CPE_DFT || hCPE->element_mode == IVAS_CPE_TD ) ) + { + if ( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); + } + + stereo_tca_init_dec( hCPE->hStereoTCA ); + } + + if ( hCPE->element_mode == IVAS_CPE_MDCT ) + { + if ( hCPE->hStereoTCA != NULL ) + { + /* note: in MASA, hCPE->hStereoMdct->itd = 0 */ + free( hCPE->hStereoTCA ); + hCPE->hStereoTCA = NULL; + } + + if ( hCPE->hStereoICBWE != NULL ) + { + free( hCPE->hStereoICBWE ); + hCPE->hStereoICBWE = NULL; + } + } + } + } + + /*--------------------------------------------------------------* + * Bitrate switching in MASA format + *---------------------------------------------------------------*/ + + if ( ivas_format == MC_FORMAT && hCPE->element_mode == IVAS_CPE_MDCT ) + { + if ( mc_mode == MC_MODE_MCT ) + { + /* deallocate the FdCNG handle */ + for ( i = 0; i < CPE_CHANNELS; ++i ) + { + deleteFdCngDec( &hCPE->hCoreCoder[i]->hFdCngDec ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE + /* deallocate CLDFB synthesis for LFE channel */ + if ( hCPE->hCoreCoder[i]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + { + deleteCldfb( &hCPE->hCoreCoder[i]->cldfbSyn ); + } +#endif + } + } + else + { + /* allocate the FdCNG handle (for noise estimation for TCX PLC fadeout)*/ + for ( i = 0; i < CPE_CHANNELS; ++i ) + { + if ( hCPE->hCoreCoder[i]->cldfbSyn == NULL ) /* could be NULL when we had the MCT LFE channel */ + { + if ( ( error = openCldfb( &hCPE->hCoreCoder[i]->cldfbSyn, CLDFB_SYNTHESIS, hCPE->hCoreCoder[i]->output_Fs, CLDFB_PROTOTYPE_1_25MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( hCPE->hCoreCoder[i]->hFdCngDec == NULL ) + { + if ( ( error = createFdCngDec( &hCPE->hCoreCoder[i]->hFdCngDec ) ) != IVAS_ERR_OK ) + { + return error; + } + initFdCngDec( hCPE->hCoreCoder[i] ); + } + } } } @@ -943,6 +1034,7 @@ void synchro_synthesis( int16_t dft_mono_brate_switch; int16_t delay_diff; float tmpF; + int16_t nChannels; sts = hCPE->hCoreCoder; output_Fs = sts[0]->output_Fs; @@ -969,7 +1061,7 @@ void synchro_synthesis( if ( use_cldfb_for_last_dft ) { - if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->last_element_mode == IVAS_CPE_TD && ( ivas_total_brate > IVAS_SID_4k4 || hCPE->nchan_out == 2 ) ) + if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->last_element_mode == IVAS_CPE_TD && ( ivas_total_brate > IVAS_SID_5k2 || hCPE->nchan_out == 2 ) ) { stereo_tca_scale_R_channel( hCPE, output[0], output_frame ); } @@ -1012,6 +1104,12 @@ void synchro_synthesis( } } + if ( hCPE->nchan_out == 1 && hCPE->last_element_mode == IVAS_CPE_MDCT ) + { + v_add( sts[0]->prev_synth_buffer, sts[1]->prev_synth_buffer, sts[0]->prev_synth_buffer, delay_comp_DFT ); + v_multc( sts[0]->prev_synth_buffer, INV_SQRT_2, sts[0]->prev_synth_buffer, delay_comp_DFT ); + } + if ( use_cldfb_for_last_dft ) { /* delay CLDFB-based mono output (<= 24.4 kbps) to be aligned with DFT-based mono output (32 kbps), needed to avoid discontinuities with TCX-LTP. */ @@ -1019,7 +1117,10 @@ void synchro_synthesis( delay_signal( output[0], output_frame, hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf, delay_diff ); } - ivas_post_proc( NULL, hCPE, 0, output[0], output, output_frame, sba_dirac_stereo_flag ); + if ( hCPE->element_mode != IVAS_CPE_MDCT ) + { + ivas_post_proc( NULL, hCPE, 0, output[0], output, output_frame, sba_dirac_stereo_flag ); + } /* zero padding in order to synchronize the upmixed DFT stereo synthesis with the TD/MDCT stereo synthesis */ for ( n = 0; n < hCPE->nchan_out; n++ ) @@ -1086,7 +1187,8 @@ void synchro_synthesis( /*----------------------------------------------------------------* * TD/MDCT stereo synchro *----------------------------------------------------------------*/ - + if ( sba_dirac_stereo_flag ) + return; if ( hCPE->element_mode == IVAS_CPE_TD || hCPE->element_mode == IVAS_CPE_MDCT ) { /* handling of DFT->TD switching */ @@ -1107,6 +1209,14 @@ void synchro_synthesis( } } + /* if previous frame had only one channel copy buffers to other channel */ + if ( hCPE->nchan_out == 1 && hCPE->element_mode == IVAS_CPE_MDCT && hCPE->last_element_mode == IVAS_CPE_DFT ) + { + mvr2r( sts[0]->prev_synth_buffer, sts[1]->prev_synth_buffer, delay_comp_TD ); + mvr2r( tmp_out[0], tmp_out[1], delay_cldfb ); + mvr2r( p_output_mem[0], p_output_mem[1], delay_diff ); + } + /*----------------------------------------------------------------* * update DFT synthesis overlap memory @output_Fs; needed for TD->DFT stereo switching *----------------------------------------------------------------*/ @@ -1190,7 +1300,8 @@ void synchro_synthesis( } } - for ( n = 0; n < hCPE->nchan_out; n++ ) + nChannels = ( hCPE->element_mode == IVAS_CPE_MDCT ) ? 2 : hCPE->nchan_out; + for ( n = 0; n < nChannels; n++ ) { if ( hCPE->element_mode == IVAS_CPE_MDCT ) { @@ -1223,7 +1334,7 @@ void synchro_synthesis( } /* cross-fading between DFT OLA memory and TD output */ - for ( n = 0; n < hCPE->nchan_out; n++ ) + for ( n = 0; n < nChannels; n++ ) { if ( hCPE->element_mode == IVAS_CPE_MDCT ) { @@ -1307,7 +1418,7 @@ void stereo_switching_dec( mvr2r( hCPE->input_mem[n], hCPE->output_mem[n], dft32ms_ovl ); } - if ( ivas_total_brate > IVAS_SID_4k4 || n == 0 || hCPE->last_element_mode != IVAS_CPE_TD || hCPE->nchan_out == 1 ) + if ( ivas_total_brate > IVAS_SID_5k2 || n == 0 || hCPE->last_element_mode != IVAS_CPE_TD || hCPE->nchan_out == 1 ) { for ( i = 0; i < dft32ms_ovl; i++ ) { @@ -1381,7 +1492,7 @@ void stereo_switching_dec( /* no secondary channel in the previous frame -> memory resets */ if ( hCPE->element_mode > IVAS_CPE_DFT && hCPE->last_element_mode == IVAS_CPE_DFT ) { - if ( hCPE->last_element_brate <= IVAS_SID_4k4 && hCPE->nchan_out == 2 ) + if ( hCPE->last_element_brate <= IVAS_SID_5k2 && hCPE->nchan_out == 2 ) { /* reset CLDFB memories */ cldfb_reset_memory( sts[0]->cldfbAna ); @@ -1392,7 +1503,6 @@ void stereo_switching_dec( sts[0]->tilt_code = 0.0f; sts[0]->gc_threshold = 0.0f; - /*init_gp_clip( sts[1]->clip_var );*/ set_f( sts[0]->mem_syn1, 0, M ); set_f( sts[0]->mem_syn2, 0, M ); @@ -1422,7 +1532,6 @@ void stereo_switching_dec( sts[1]->tilt_code = 0.0f; sts[1]->gc_threshold = 0.0f; - /*init_gp_clip( sts[1]->clip_var );*/ set_f( sts[1]->mem_syn1, 0, M ); set_f( sts[1]->mem_syn2, 0, M ); @@ -1435,23 +1544,15 @@ void stereo_switching_dec( mvr2r( sts[0]->old_exc, sts[1]->old_exc, L_EXC_MEM_DEC ); mvr2r( sts[0]->lsf_old, sts[1]->lsf_old, M ); mvr2r( sts[0]->lsp_old, sts[1]->lsp_old, M ); - if ( hCPE->element_mode == IVAS_CPE_MDCT ) { sts[1]->last_core = sts[0]->last_core; sts[1]->last_coder_type = sts[0]->last_coder_type; - sts[1]->hTcxCfg->last_aldo = sts[0]->hTcxCfg->last_aldo; - sts[1]->hTcxCfg->tcx_curr_overlap_mode = sts[0]->hTcxCfg->tcx_curr_overlap_mode; mvr2r( sts[0]->hHQ_core->old_out, sts[1]->hHQ_core->old_out, L_FRAME48k ); mvr2r( sts[0]->delay_buf_out, sts[1]->delay_buf_out, HQ_DELTA_MAX * HQ_DELAY_COMP ); mvr2r( sts[0]->hTcxDec->old_syn_Overl, sts[1]->hTcxDec->old_syn_Overl, 256 ); /* Todo: apply panning to buffers instead of simply using dmx in left and right channel */ - - sts[1]->fscale = sts[0]->fscale; - sts[1]->hTcxCfg->tcx_mdct_window_length = sts[0]->hTcxCfg->tcx_mdct_window_length; - sts[1]->pit_res_max = sts[0]->pit_res_max; - sts[1]->pit_res_max_past = sts[0]->pit_res_max_past; } } else if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode == IVAS_CPE_MDCT ) @@ -1460,6 +1561,19 @@ void stereo_switching_dec( set_f( sts[1]->old_exc, 0.0f, L_EXC_MEM_DEC ); } + /* TD/DFT -> MDCT stereo switching (there is no TCX in the TD stereo secondary channel, or DFT stereo) */ + if ( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->last_element_mode != IVAS_CPE_MDCT ) + { + sts[1]->hTcxCfg->last_aldo = sts[0]->hTcxCfg->last_aldo; + sts[1]->hTcxCfg->tcx_curr_overlap_mode = sts[0]->hTcxCfg->tcx_curr_overlap_mode; + sts[1]->fscale = sts[0]->fscale; + sts[1]->hTcxCfg->tcx_mdct_window_length = sts[0]->hTcxCfg->tcx_mdct_window_length; + sts[1]->pit_res_max = sts[0]->pit_res_max; + sts[1]->pit_res_max_past = sts[0]->pit_res_max_past; + sts[1]->hTcxDec->L_frameTCX = sts[0]->hTcxDec->L_frameTCX; + sts[1]->hTcxDec->conceal_eof_gain = sts[0]->hTcxDec->conceal_eof_gain; + } + return; } diff --git a/lib_dec/ivas_stereo_td_dec.c b/lib_dec/ivas_stereo_td_dec.c index fbfcc5e825c18ef09477d69267960ffce2076bdb..605d5ad388ca0f2bf6853c8deb59ac9cd881762d 100644 --- a/lib_dec/ivas_stereo_td_dec.c +++ b/lib_dec/ivas_stereo_td_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * stereo_td_init_dec() @@ -99,10 +99,10 @@ void tdm_configure_dec( sts = hCPE->hCoreCoder; /*----------------------------------------------------------------* - * Decode CoreCoder signalling + * Decode CoreCoder signaling *----------------------------------------------------------------*/ - /* temporarily decode PCh signalling */ + /* temporarily decode PCh signaling */ bits_offset = sts[0]->next_bit_pos; core = get_indice_st( sts[0], hCPE->element_brate, bits_offset, 1 ); bits_offset += 1; diff --git a/lib_dec/ivas_svd_dec.c b/lib_dec/ivas_svd_dec.c index ff9852d1df647b90b7177bdd954556aacc715c35..785a9067804c9b252fb08d1922d4354d675ab801 100644 --- a/lib_dec/ivas_svd_dec.c +++ b/lib_dec/ivas_svd_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -196,7 +196,7 @@ int16_t svd( float secDiag[MAX_OUTPUT_CHANNELS]; float eps_x = 0.0f, temp; - wmops_sub_start( "svd" ); + push_wmops( "svd" ); set_zero( secDiag, MAX_OUTPUT_CHANNELS ); @@ -252,7 +252,7 @@ int16_t svd( } } while ( condition == 1 ); - wmops_sub_end(); + pop_wmops(); return ( errorMessage ); } diff --git a/lib_dec/ivas_tcx_core_dec.c b/lib_dec/ivas_tcx_core_dec.c index 21a525391d1499ebca1aa424dcba44e3c5dee9cb..b5dcfd2bbede473d6a2ee5b8e5bbf6742162a994 100644 --- a/lib_dec/ivas_tcx_core_dec.c +++ b/lib_dec/ivas_tcx_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "prot.h" #include "rom_com.h" #include "stat_dec.h" -#include "wmops.h" +#include "wmc_auto.h" #include "basop_proto_func.h" #include "stat_com.h" #include "ivas_prot.h" @@ -51,7 +51,8 @@ * Local prototypes *-------------------------------------------------------------*/ -static void dec_prm_tcx( Decoder_State *st, int16_t param[], int16_t param_lpc[], int16_t *total_nbbits, int16_t *bitsRead ); +static void dec_prm_tcx( Decoder_State *st, int16_t param[], int16_t param_lpc[], int16_t *total_nbbits, const int16_t last_element_mode, int16_t *bitsRead ); +static void stereo_tcx_dec_mode_switch_reconf( Decoder_State *st, const int16_t MCT_flag, const int16_t last_element_mode ); /*-------------------------------------------------------------* @@ -61,12 +62,11 @@ static void dec_prm_tcx( Decoder_State *st, int16_t param[], int16_t param_lpc[] *-------------------------------------------------------------*/ void stereo_tcx_init_dec( - Decoder_State *st, /* i/o: decoder state structure */ - const int16_t is_mct, /* i : MCT mode flag */ - const int16_t last_element_mode /* i : element mode of previous frame */ + Decoder_State *st, /* i/o: decoder state structure */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ + const int16_t last_element_mode /* i : element mode of previous frame */ ) { - int16_t frame_size_index; TCX_LTP_DEC_HANDLE hTcxLtpDec = st->hTcxLtpDec; TCX_DEC_HANDLE hTcxDec = st->hTcxDec; @@ -95,7 +95,26 @@ void stereo_tcx_init_dec( st->hTcxCfg->ctx_hm = getCtxHm( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->rf_flag ); st->hTcxCfg->resq = getResq( st->bits_frame_nominal * FRAMES_PER_SEC ); hTcxDec->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->bits_frame_nominal * FRAMES_PER_SEC, st->rf_flag, st->element_mode ); - st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_flag, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_flag +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + !MCT_flag && +#endif + st->element_mode != EVS_MONO ) + { + st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( st->bits_frame_nominal * FRAMES_PER_SEC, st->igf, st->element_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + } if ( hTcxLtpDec != NULL ) { hTcxLtpDec->tcxltp = getTcxLtp( st->sr_core ); @@ -103,7 +122,7 @@ void stereo_tcx_init_dec( if ( st->element_mode == IVAS_SCE ) { - st->tcxonly = getTcxonly( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, is_mct ); + st->tcxonly = getTcxonly( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, MCT_flag ); /* LPC quantization */ if ( st->sr_core <= INT_FS_16k && st->tcxonly == 0 ) @@ -125,36 +144,13 @@ void stereo_tcx_init_dec( } } - if ( ( st->bits_frame_nominal != st->last_bits_frame_nominal ) || ( st->bwidth != st->last_bwidth ) || ( st->last_core != TCX_20_CORE && st->last_core != TCX_10_CORE && !( st->prev_bfi == 1 && st->last_core == ACELP_CORE && st->last_con_tcx == 1 ) ) || ( st->idchan == 1 && st->element_mode == IVAS_CPE_MDCT && last_element_mode != IVAS_CPE_MDCT ) ) + if ( ( st->bits_frame_nominal != st->last_bits_frame_nominal ) || + ( st->bwidth != st->last_bwidth ) || + ( st->last_core != TCX_20_CORE && st->last_core != TCX_10_CORE && !( st->prev_bfi == 1 && st->last_core == ACELP_CORE && st->last_con_tcx == 1 ) ) || + ( st->idchan == 1 && st->element_mode == IVAS_CPE_MDCT && last_element_mode != IVAS_CPE_MDCT ) ) { /*re-initialization*/ - st->rate_switching_init = 1; - - /* Identify frame type - TCX Reconfiguration */ - for ( frame_size_index = 0; frame_size_index < FRAME_SIZE_NB; frame_size_index++ ) - { - if ( frame_size_index < FRAME_SIZE_NB - 1 ) - { - if ( ( FrameSizeConfig[frame_size_index].frame_bits <= st->bits_frame_nominal ) && ( FrameSizeConfig[frame_size_index + 1].frame_bits > st->bits_frame_nominal ) ) - { - break; - } - } - else - { - if ( FrameSizeConfig[frame_size_index].frame_bits <= st->bits_frame_nominal ) - { - break; - } - } - } - - /* Reconfigure Core */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - mode_switch_decoder_LPD( st, st->bwidth, st->bits_frame_nominal * FRAMES_PER_SEC, st->last_bits_frame_nominal * FRAMES_PER_SEC, frame_size_index, is_mct, last_element_mode ); -#else - mode_switch_decoder_LPD( st, st->bwidth, st->bits_frame_nominal * FRAMES_PER_SEC, st->last_bits_frame_nominal * FRAMES_PER_SEC, frame_size_index, is_mct ); -#endif + stereo_tcx_dec_mode_switch_reconf( st, MCT_flag, last_element_mode ); } return; @@ -178,7 +174,12 @@ void stereo_tcx_core_dec( const int16_t last_element_mode, /* i : last element mode */ const int16_t flag_sec_CNA, /* i : CNA flag for secondary channel */ STEREO_CNG_DEC_HANDLE hStereoCng, /* i : Stereo CNG handle */ - const int16_t nchan_out /* i : number of output channels */ + const int16_t nchan_out, /* i : number of output channels */ + const IVAS_FORMAT ivas_format /* i : IVAS format */ +#ifndef DISCRETE_ISM_DTX_CNG + , + const ISM_MODE ism_mode /* i : ISM mode (only needed if format is ISM)*/ +#endif ) { int16_t i, k; @@ -214,7 +215,7 @@ void stereo_tcx_core_dec( TCX_LTP_DEC_HANDLE hTcxLtpDec = st->hTcxLtpDec; TCX_DEC_HANDLE hTcxDec = st->hTcxDec; - wmops_sub_start( "stereo_tcx_core_dec" ); + push_wmops( "stereo_tcx_core_dec" ); /*Sanity check*/ assert( !( st->total_brate == FRAME_NO_DATA || st->total_brate == SID_2k40 ) ); /*Active frame*/ @@ -288,7 +289,7 @@ void stereo_tcx_core_dec( tcx_current_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; #endif - dec_prm_tcx( st, param, param_lpc, &total_nbbits, &bitsRead ); + dec_prm_tcx( st, param, param_lpc, &total_nbbits, last_element_mode, &bitsRead ); #ifdef FIX_IVAS_337 /*IVAS-337 consider BER */ if ( !st->rate_switching_init && st->BER_detect ) @@ -457,11 +458,7 @@ void stereo_tcx_core_dec( } /* PLC: [TCX: TD PLC] */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT con_tcx( st, &synthFB[0], -1.f, NULL, 0, NULL ); -#else - con_tcx( st, &synthFB[0], -1.f, NULL, 0 ); -#endif lerp( synthFB, synth, st->L_frame, hTcxDec->L_frameTCX ); st->con_tcx = 1; set_f( &st->mem_pitch_gain[2], st->lp_gainp, st->nb_subfr ); @@ -589,11 +586,7 @@ void stereo_tcx_core_dec( TonalMDCTConceal_SaveTimeSignal( st->hTonalMDCTConc, synthFB, hTcxDec->L_frameTCX ); } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT decoder_tcx_post( st, synth, synthFB, Aq, bfi, 0 ); -#else - decoder_tcx_post( st, synth, synthFB, Aq, bfi ); -#endif if ( st->core == TCX_20_CORE ) { @@ -750,11 +743,20 @@ void stereo_tcx_core_dec( if ( st->element_mode != IVAS_CPE_TD ) { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - ApplyFdCng( signal_out, NULL, NULL, NULL, st, st->bfi, 0 ); +#ifndef DISCRETE_ISM_DTX_CNG + if ( ivas_format == ISM_FORMAT && ism_mode == ISM_MODE_PARAM ) #else - ApplyFdCng( signal_out, NULL, NULL, st, st->bfi, 0 ); + if ( ivas_format == ISM_FORMAT ) #endif + { + float buffer[L_FRAME16k]; + lerp( signal_outFB, buffer, st->L_frame, hTcxDec->L_frameTCX ); + ApplyFdCng( buffer, NULL, NULL, NULL, st, st->bfi, 0 ); + } + else + { + ApplyFdCng( signal_out, NULL, NULL, NULL, st, st->bfi, 0 ); + } } /* Generate additional comfort noise to mask potential coding artefacts */ @@ -779,11 +781,7 @@ void stereo_tcx_core_dec( if ( st->element_mode == IVAS_CPE_TD && st->idchan == 0 ) { -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT ApplyFdCng( signal_out, NULL, NULL, NULL, st, st->bfi, 0 ); -#else - ApplyFdCng( signal_out, NULL, NULL, st, st->bfi, 0 ); -#endif } } @@ -812,23 +810,24 @@ void stereo_tcx_core_dec( #endif - wmops_sub_end(); + pop_wmops(); return; } /*-----------------------------------------------------------------* - * Function dec_prm_tcx() * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * decode TCX parameters + * Function dec_prm_tcx() + * + * Decode TCX parameters *-----------------------------------------------------------------*/ static void dec_prm_tcx( - Decoder_State *st, /* i/o: decoder memory state */ - int16_t param[], /* o : decoded parameters */ - int16_t param_lpc[], /* o : LPC parameters */ - int16_t *total_nbbits, /* i/o: number of bits / decoded bits */ - int16_t *bitsRead /* o : number of read bits */ + Decoder_State *st, /* i/o: decoder memory state */ + int16_t param[], /* o : decoded parameters */ + int16_t param_lpc[], /* o : LPC parameters */ + int16_t *total_nbbits, /* i/o: number of bits / decoded bits */ + const int16_t last_element_mode, /* i : last element mode */ + int16_t *bitsRead /* o : number of read bits */ ) { int16_t start_bit_pos, bits_common; @@ -867,27 +866,12 @@ static void dec_prm_tcx( *--------------------------------------------------------------------------------*/ /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT getTCXMode( st, st, 0 /* <- MCT_flag */ ); -#else - getTCXMode( st, st ); -#endif /* last_core for error concealment */ if ( !st->use_partial_copy && st->element_mode != IVAS_CPE_MDCT ) { -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - if ( st->core == TCX_20_CORE ) - { - st->last_core_from_bs = get_next_indice( st, 1 ); - } - else - { - st->last_core_from_bs = st->last_core; - } -#else st->last_core_from_bs = get_next_indice( st, 1 ); /* Store decoder memory of last_core */ -#endif if ( st->last_core == ACELP_CORE && st->last_core_from_bs != ACELP_CORE ) { /* A mismatch between the memory and the last_core @@ -896,6 +880,12 @@ static void dec_prm_tcx( st->prev_bfi = 1; } + /* possible need for reconfiguration can only be decided correctly once last_core_from_bs has been decoded */ + if ( ( st->last_core != st->last_core_from_bs ) && ( st->last_core_from_bs != TCX_20_CORE && st->last_core_from_bs != TCX_10_CORE && !( st->prev_bfi == 1 && st->last_core_from_bs == ACELP_CORE && st->last_con_tcx == 1 ) ) ) + { + stereo_tcx_dec_mode_switch_reconf( st, 0, last_element_mode ); + } + st->last_core = st->last_core_from_bs; /*for TCX 10 force last_core to be TCX since ACELP as previous core is forbidden*/ @@ -909,11 +899,7 @@ static void dec_prm_tcx( { if ( st->element_mode != IVAS_CPE_MDCT ) { -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 getTCXWindowing( st->core, st->last_core, st->element_mode, st->hTcxCfg, st ); -#else - getTCXWindowing( st->core, st->last_core, st->hTcxCfg, st ); -#endif } st->flagGuidedAcelp = 0; @@ -962,3 +948,44 @@ static void dec_prm_tcx( return; } + +/*-----------------------------------------------------------------* + * Function stereo_tcx_dec_mode_switch_reconf() + * + * Reconfigure stereo TCX parameters + *-----------------------------------------------------------------*/ + +static void stereo_tcx_dec_mode_switch_reconf( + Decoder_State *st, /* i/o: decoder state structure */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ + const int16_t last_element_mode /* i : element mode of previous frame */ +) +{ + int16_t frame_size_index; + + st->rate_switching_init = 1; + + /* Identify frame type - TCX Reconfiguration */ + for ( frame_size_index = 0; frame_size_index < FRAME_SIZE_NB; frame_size_index++ ) + { + if ( frame_size_index < FRAME_SIZE_NB - 1 ) + { + if ( ( FrameSizeConfig[frame_size_index].frame_bits <= st->bits_frame_nominal ) && ( FrameSizeConfig[frame_size_index + 1].frame_bits > st->bits_frame_nominal ) ) + { + break; + } + } + else + { + if ( FrameSizeConfig[frame_size_index].frame_bits <= st->bits_frame_nominal ) + { + break; + } + } + } + + /* Reconfigure Core */ + mode_switch_decoder_LPD( st, st->bwidth, st->bits_frame_nominal * FRAMES_PER_SEC, st->last_bits_frame_nominal * FRAMES_PER_SEC, frame_size_index, MCT_flag, last_element_mode ); + + return; +} diff --git a/lib_dec/ivas_stereo_td_low_rate_dec.c b/lib_dec/ivas_td_low_rate_dec.c similarity index 96% rename from lib_dec/ivas_stereo_td_low_rate_dec.c rename to lib_dec/ivas_td_low_rate_dec.c index 8a0757cd5e8a6dc7f8f2d06a5269e44262767e72..8ab266345a45fd3a95ff2820122502f6c87ddaac 100644 --- a/lib_dec/ivas_stereo_td_low_rate_dec.c +++ b/lib_dec/ivas_td_low_rate_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "ivas_cnst.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * tdm_low_rate_dec() @@ -67,7 +67,6 @@ void tdm_low_rate_dec( int16_t Diff_len, nb_subfr; int16_t attack_flag; int16_t last_bin; - int16_t m_coder_type; float exc_wo_nf[L_FRAME]; hGSCDec = st->hGSCDec; @@ -76,26 +75,19 @@ void tdm_low_rate_dec( * Initialization *---------------------------------------------------------------*/ - m_coder_type = st->coder_type; - - Diff_len = 0; - - pit_band_idx = 10 + BAND1k2; nb_subfr = 2; - hGSCDec->Last_GSC_pit_band_idx = pit_band_idx; - + st->GSC_IVAS_mode = 0; st->GSC_noisy_speech = 1; hGSCDec->noise_lev = 14; - /*---------------------------------------------------------------* - * DCT transform - *---------------------------------------------------------------*/ + pit_band_idx = 10 + BAND1k2; + hGSCDec->Last_GSC_pit_band_idx = pit_band_idx; st->tilt_code = 0.0f; set_f( exc, 0, L_FRAME ); set_f( dct_epit, 0, L_FRAME ); - set_f( pitch_buf, 64, 4 ); + set_f( pitch_buf, L_SUBFR, NB_SUBFR ); st->bpf_off = 1; st->bfi_pitch = (int16_t) ( mean( pitch_buf, 4 ) + 0.5f ); @@ -127,7 +119,7 @@ void tdm_low_rate_dec( tmp_nb_bits_tot--; } - gsc_dec( st, dct_epit, pit_band_idx, Diff_len, tmp_nb_bits_tot, nb_subfr, m_coder_type, &last_bin, lsf_new, exc_wo_nf, tmp_noise ); + gsc_dec( st, dct_epit, pit_band_idx, Diff_len, tmp_nb_bits_tot, nb_subfr, st->coder_type, &last_bin, lsf_new, exc_wo_nf, tmp_noise ); /*--------------------------------------------------------------------------------------* * iDCT transform diff --git a/lib_dec/ivas_vbap.c b/lib_dec/ivas_vbap.c index a2f89e08091046e7f6d75c0950d35d63d271c8f1..cda52c1aec8e7c74c9b05d1016cc429e99fb6151 100644 --- a/lib_dec/ivas_vbap.c +++ b/lib_dec/ivas_vbap.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,14 +40,12 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * Local constants *-----------------------------------------------------------------------*/ -#define VBAP_SUB_FUNCTION_MEMORY_INIT_FAIL ( -1 ) - /* 128 is maximum num_speaker_nodes number. This relates to memory optimization and maximum of triplets: - triplet indices are unsigned_char (see below structs) --> max triplets is 256 - num_speaker_nodes_internal = num_speaker_nodes + 2 (potential virtual node channels, bottom and top) @@ -97,6 +95,26 @@ typedef struct connection_option float arc_weighted; } ConnectionOption; +enum SpeakerNodeGroup +{ + SPEAKER_NODE_BOTTOM_HALF, + SPEAKER_NODE_HORIZONTAL, + SPEAKER_NODE_TOP_HALF, + SPEAKER_NODE_BACK, + SPEAKER_NODE_ALL +}; + +/* Defines a single speaker node */ +typedef struct vbap_speaker_node_structure +{ + float azi_deg; + float ele_deg; + float unit_vec[3]; + enum SpeakerNodeGroup group; + +} VBAP_SPEAKER_NODE; + + /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ @@ -109,13 +127,13 @@ static int16_t determine_virtual_surface_triplets( const int16_t num_speaker_nod static void determine_initial_search_indices( const int16_t num_triplets, const float triplet_azidegs[VBAP_MAX_NUM_TRIPLETS], int16_t initial_search_indices[VBAP_NUM_SEARCH_SECTORS] ); -static void determine_connections( const int16_t num_speaker_nodes, const VBAP_SPEAKER_NODE *speaker_node_data, int16_t connections[][2], const int16_t max_num_connections, int16_t *group1_count, int16_t *group2_start, int16_t *group2_count ); +static ivas_error determine_connections( const int16_t num_speaker_nodes, const VBAP_SPEAKER_NODE *speaker_node_data, int16_t connections[][2], const int16_t max_num_connections, int16_t *group1_count, int16_t *group2_start, int16_t *group2_count ); static void formulate_horizontal_connections( const VBAP_SPEAKER_NODE *speaker_node_data, const int16_t num_speaker_nodes, int16_t connections[][2], int16_t *connection_write_index ); -static void get_half_sphere_connection_options( const VBAP_SPEAKER_NODE *speaker_node_data, const enum SpeakerNodeGroup group, const int16_t num_speaker_nodes, const int16_t num_non_crossing_planes, const float *non_crossing_plane_elevation_deg, ConnectionOption **connection_options_pr, int16_t *num_connection_options ); +static ivas_error get_half_sphere_connection_options( const VBAP_SPEAKER_NODE *speaker_node_data, const enum SpeakerNodeGroup group, const int16_t num_speaker_nodes, const int16_t num_non_crossing_planes, const float *non_crossing_plane_elevation_deg, ConnectionOption **connection_options_pr, int16_t *num_connection_options ); -static void formulate_half_sphere_connections( const VBAP_SPEAKER_NODE *speaker_node_data, const int16_t num_speaker_nodes, const enum SpeakerNodeGroup group, int16_t connections[][2], int16_t *connection_write_index, const int16_t max_num_connections, const int16_t num_non_crossing_planes, const float *non_crossing_plane_elevation_deg ); +static ivas_error formulate_half_sphere_connections( const VBAP_SPEAKER_NODE *speaker_node_data, const int16_t num_speaker_nodes, const enum SpeakerNodeGroup group, int16_t connections[][2], int16_t *connection_write_index, const int16_t max_num_connections, const int16_t num_non_crossing_planes, const float *non_crossing_plane_elevation_deg ); static int16_t determine_non_crossing_planes( const int16_t num_speaker_nodes, const VBAP_SPEAKER_NODE *node_data, float *non_crossing_plane_elevation_deg ); @@ -155,17 +173,19 @@ ivas_error vbap_init_data( float speaker_node_ele_deg_internal[VBAP_MAX_NUM_SPEAKER_NODES]; VBAP_SPEAKER_NODE speaker_node_data[VBAP_MAX_NUM_SPEAKER_NODES]; VBAP_DATA *vbap; + ivas_error error; - wmops_sub_start( "vbap_init" ); + push_wmops( "vbap_init" ); /* Basic init checks */ if ( num_speaker_nodes > VBAP_MAX_NUM_SPEAKER_NODES || num_speaker_nodes < 3 ) { hVBAPdata = NULL; - wmops_sub_end(); + pop_wmops(); /* TODO: are these two paths correct behaviour or should and error be returned ? */ return IVAS_ERR_OK; } + if ( !speaker_node_azi_deg || !speaker_node_ele_deg ) { hVBAPdata = NULL; @@ -173,7 +193,7 @@ ivas_error vbap_init_data( } /* Allocate VBAP structure */ - if ( ( vbap = (VBAP_HANDLE) count_malloc( sizeof( VBAP_DATA ) ) ) == NULL ) + if ( ( vbap = (VBAP_HANDLE) malloc( sizeof( VBAP_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); } @@ -188,7 +208,6 @@ ivas_error vbap_init_data( vbap->num_speaker_nodes = num_speaker_nodes; vbap->num_speaker_nodes_internal = num_speaker_nodes; - /* Check if the speaker node setup needs a virtual top or bottom node (function also increments vbap->num_speaker_nodes_internal when necessary) */ virtual_bottom_type = check_need_of_virtual_speaker_node( vbap, speaker_node_azi_deg, speaker_node_ele_deg, SPEAKER_NODE_BOTTOM_HALF ); @@ -202,7 +221,11 @@ ivas_error vbap_init_data( if ( is_success && virtual_bottom_type != NO_VIRTUAL_SPEAKER_NODE ) { - vbap->bottom_virtual_speaker_node_division_gains = (float *) count_calloc( num_speaker_nodes, sizeof( float ) ); + if ( ( vbap->bottom_virtual_speaker_node_division_gains = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); + } + set_zero( vbap->bottom_virtual_speaker_node_division_gains, num_speaker_nodes ); is_success &= vbap->bottom_virtual_speaker_node_division_gains != NULL; speaker_node_azi_deg_internal[vbap->bottom_virtual_speaker_node_index] = 0.0f; speaker_node_ele_deg_internal[vbap->bottom_virtual_speaker_node_index] = -90.0f; @@ -210,7 +233,11 @@ ivas_error vbap_init_data( if ( is_success && virtual_top_type != NO_VIRTUAL_SPEAKER_NODE ) { - vbap->top_virtual_speaker_node_division_gains = (float *) count_calloc( num_speaker_nodes, sizeof( float ) ); + if ( ( vbap->top_virtual_speaker_node_division_gains = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); + } + set_zero( vbap->top_virtual_speaker_node_division_gains, num_speaker_nodes ); is_success &= vbap->top_virtual_speaker_node_division_gains != NULL; speaker_node_azi_deg_internal[vbap->top_virtual_speaker_node_index] = 0.0f; speaker_node_ele_deg_internal[vbap->top_virtual_speaker_node_index] = 90.0f; @@ -218,7 +245,11 @@ ivas_error vbap_init_data( if ( is_success && virtual_back_type != NO_VIRTUAL_SPEAKER_NODE ) { - vbap->back_virtual_speaker_node_division_gains = (float *) count_calloc( num_speaker_nodes, sizeof( float ) ); + if ( ( vbap->back_virtual_speaker_node_division_gains = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); + } + set_zero( vbap->back_virtual_speaker_node_division_gains, num_speaker_nodes ); is_success &= vbap->back_virtual_speaker_node_division_gains != NULL; speaker_node_azi_deg_internal[vbap->back_virtual_speaker_node_index] = 180.0f; speaker_node_ele_deg_internal[vbap->back_virtual_speaker_node_index] = 0.0f; @@ -229,7 +260,10 @@ ivas_error vbap_init_data( /* Allocate and determine node-node connections */ max_num_connections = ( vbap->num_speaker_nodes_internal - 2 ) * 3; /* Theoretical maximum */ - determine_connections( vbap->num_speaker_nodes_internal, speaker_node_data, connections, max_num_connections, &connection_group1_count, &connection_group2_start, &connection_group2_count ); + if ( ( error = determine_connections( vbap->num_speaker_nodes_internal, speaker_node_data, connections, max_num_connections, &connection_group1_count, &connection_group2_start, &connection_group2_count ) ) != IVAS_ERR_OK ) + { + return error; + } /* Allocate and determine virtual surface speaker node triplets */ if ( is_success ) @@ -265,12 +299,20 @@ ivas_error vbap_init_data( break; } } - vbap->search_struct[0].triplets = (VBAP_VS_TRIPLET *) count_malloc( ( ( speaker_nodes_group1_internal - 2 ) * 2 - ( max( 0, ( speaker_nodes_horiz_internal - 2 ) ) ) ) * sizeof( VBAP_VS_TRIPLET ) ); + + if ( ( vbap->search_struct[0].triplets = (VBAP_VS_TRIPLET *) malloc( ( ( speaker_nodes_group1_internal - 2 ) * 2 - ( max( 0, ( speaker_nodes_horiz_internal - 2 ) ) ) ) * sizeof( VBAP_VS_TRIPLET ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); + } is_success &= vbap->search_struct[0].triplets != NULL; + if ( speaker_nodes_group2_internal > 0 ) { vbap->num_search_structs = 2; - vbap->search_struct[1].triplets = (VBAP_VS_TRIPLET *) count_malloc( ( ( speaker_nodes_group2_internal - 2 ) * 2 - ( max( 0, ( speaker_nodes_horiz_internal - 2 ) ) ) ) * sizeof( VBAP_VS_TRIPLET ) ); + if ( ( vbap->search_struct[1].triplets = (VBAP_VS_TRIPLET *) malloc( ( ( speaker_nodes_group2_internal - 2 ) * 2 - ( max( 0, ( speaker_nodes_horiz_internal - 2 ) ) ) ) * sizeof( VBAP_VS_TRIPLET ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); + } is_success &= vbap->search_struct[1].triplets != NULL; } else @@ -305,7 +347,7 @@ ivas_error vbap_init_data( determine_virtual_speaker_node_division_gains( vbap->back_virtual_speaker_node_index, vbap->back_virtual_speaker_node_division_gains, connections, virtual_back_type, max_num_connections, num_speaker_nodes ); } - wmops_sub_end(); + pop_wmops(); if ( is_success ) { @@ -337,26 +379,26 @@ void vbap_free_data( if ( ( *hVBAPdata )->bottom_virtual_speaker_node_division_gains != NULL ) { - count_free( ( *hVBAPdata )->bottom_virtual_speaker_node_division_gains ); + free( ( *hVBAPdata )->bottom_virtual_speaker_node_division_gains ); } if ( ( *hVBAPdata )->top_virtual_speaker_node_division_gains != NULL ) { - count_free( ( *hVBAPdata )->top_virtual_speaker_node_division_gains ); + free( ( *hVBAPdata )->top_virtual_speaker_node_division_gains ); } if ( ( *hVBAPdata )->back_virtual_speaker_node_division_gains != NULL ) { - count_free( ( *hVBAPdata )->back_virtual_speaker_node_division_gains ); + free( ( *hVBAPdata )->back_virtual_speaker_node_division_gains ); } if ( ( *hVBAPdata )->search_struct[0].triplets != NULL ) { - count_free( ( *hVBAPdata )->search_struct[0].triplets ); + free( ( *hVBAPdata )->search_struct[0].triplets ); } if ( ( *hVBAPdata )->num_search_structs == 2 && ( *hVBAPdata )->search_struct[1].triplets != NULL ) { - count_free( ( *hVBAPdata )->search_struct[1].triplets ); + free( ( *hVBAPdata )->search_struct[1].triplets ); } - count_free( *hVBAPdata ); + free( *hVBAPdata ); *hVBAPdata = NULL; return; @@ -402,7 +444,7 @@ void vbap_determine_gains( assert( gains != NULL && "VBAP gain determination requires reserved memory for gain output." ); #endif - wmops_sub_start( "vbap_gains" ); + push_wmops( "vbap_gains" ); num_speaker_nodes = hVBAPdata->num_speaker_nodes; bottom_virtual_speaker_node_index = hVBAPdata->bottom_virtual_speaker_node_index; top_virtual_speaker_node_index = hVBAPdata->top_virtual_speaker_node_index; @@ -438,7 +480,7 @@ void vbap_determine_gains( gain_ene += gain_triplet[ch] * gain_triplet[ch]; } - norm_value = 1.0f / sqrtf( gain_ene ); + norm_value = inv_sqrt( gain_ene ); for ( ch = 0; ch < 3; ch++ ) { @@ -486,7 +528,7 @@ void vbap_determine_gains( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -664,8 +706,7 @@ static void determine_virtual_speaker_node_division_gains( are distributed to all neighboring real speaker nodes. An amplitude-division instead of energy division is utilized just in case to avoid excessive emphasis on the coherent distributed sound. */ - int16_t c; - int16_t ch; + int16_t c, ch; float sum_val; if ( type == VIRTUAL_SPEAKER_NODE_DISTRIBUTE_ENERGY ) @@ -717,7 +758,7 @@ static void determine_virtual_speaker_node_division_gains( /*! r: virtual speaker node type */ static enum VirtualSpeakerNodeType check_need_of_virtual_speaker_node( VBAP_HANDLE hVBAPdata, /* i/o: VBAP structure */ - const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths */ + const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths */ const float *speaker_node_ele_deg, /* i : vector of speaker node elevations */ enum SpeakerNodeGroup group /* i : group of speaker nodes where this belongs */ ) @@ -947,9 +988,9 @@ static void matrix_inverse_3x3( *-------------------------------------------------------------------------*/ static int16_t check_and_store_triplet( - int16_t chA, /* i : first channel index that forms the loudspeaker triplet */ - int16_t chB, /* i : second channel index that forms the loudspeaker triplet */ - int16_t chC, /* i : third channel index that forms the loudspeaker triplet */ + const int16_t chA, /* i : first channel index that forms the loudspeaker triplet */ + const int16_t chB, /* i : second channel index that forms the loudspeaker triplet */ + const int16_t chC, /* i : third channel index that forms the loudspeaker triplet */ const int16_t num_speaker_nodes, /* i : number of speaker nodes */ const VBAP_SPEAKER_NODE *speaker_node_data, /* i : speaker node data structure */ VBAP_VS_TRIPLET *triplets, /* o : vector of virtual surface triplets */ @@ -1002,7 +1043,7 @@ static int16_t check_and_store_triplet( /* Get center azimuth for fast search use */ triplet_azidegs[*triplet_index] = atan2f( speaker_node_data[chA].unit_vec[1] + speaker_node_data[chB].unit_vec[1] + speaker_node_data[chC].unit_vec[1], speaker_node_data[chA].unit_vec[0] + speaker_node_data[chB].unit_vec[0] + speaker_node_data[chC].unit_vec[0] ) * - 180.0f / EVS_PI; + _180_OVER_PI; /* Store increasing order indices for the later sorting step. */ triplet_order[*triplet_index] = *triplet_index; @@ -1181,7 +1222,7 @@ static void determine_initial_search_indices( * Determine all valid connections between all speaker nodes *-------------------------------------------------------------------------*/ -static void determine_connections( +static ivas_error determine_connections( const int16_t num_speaker_nodes, /* i : number of speaker nodes */ const VBAP_SPEAKER_NODE *speaker_node_data, /* i : speaker node data */ int16_t connections[][2], /* o : vector of connections */ @@ -1195,6 +1236,7 @@ static void determine_connections( int16_t c; int16_t connection_write_index = 0; float non_crossing_plane_elevation_deg[VBAP_MAX_PLANES]; + ivas_error error; set_f( non_crossing_plane_elevation_deg, 0.0f, VBAP_MAX_PLANES ); @@ -1210,20 +1252,31 @@ static void determine_connections( /* Process in different mode based on the grouping. It is enough to check for first node. */ if ( speaker_node_data[0].group == SPEAKER_NODE_ALL ) { - formulate_half_sphere_connections( speaker_node_data, num_speaker_nodes, SPEAKER_NODE_ALL, connections, &connection_write_index, max_num_connections, num_non_crossing_planes, non_crossing_plane_elevation_deg ); + if ( ( error = formulate_half_sphere_connections( speaker_node_data, num_speaker_nodes, SPEAKER_NODE_ALL, connections, &connection_write_index, max_num_connections, num_non_crossing_planes, non_crossing_plane_elevation_deg ) ) != IVAS_ERR_OK ) + { + return error; + } } else { /* The node-node connections are determined in three stages: bottom, horizontal, and top. */ - formulate_half_sphere_connections( speaker_node_data, num_speaker_nodes, SPEAKER_NODE_BOTTOM_HALF, connections, &connection_write_index, max_num_connections, num_non_crossing_planes, non_crossing_plane_elevation_deg ); + if ( ( error = formulate_half_sphere_connections( speaker_node_data, num_speaker_nodes, SPEAKER_NODE_BOTTOM_HALF, connections, &connection_write_index, max_num_connections, num_non_crossing_planes, non_crossing_plane_elevation_deg ) ) != IVAS_ERR_OK ) + { + return error; + } *group2_start = connection_write_index; + formulate_horizontal_connections( speaker_node_data, num_speaker_nodes, connections, &connection_write_index ); *group1_count = connection_write_index; - formulate_half_sphere_connections( speaker_node_data, num_speaker_nodes, SPEAKER_NODE_TOP_HALF, connections, &connection_write_index, max_num_connections, num_non_crossing_planes, non_crossing_plane_elevation_deg ); + + if ( ( error = formulate_half_sphere_connections( speaker_node_data, num_speaker_nodes, SPEAKER_NODE_TOP_HALF, connections, &connection_write_index, max_num_connections, num_non_crossing_planes, non_crossing_plane_elevation_deg ) ) != IVAS_ERR_OK ) + { + return error; + } *group2_count = connection_write_index - *group2_start; } - return; + return IVAS_ERR_OK; } @@ -1426,7 +1479,7 @@ static int16_t check_plane_crossing( * Get list of all potential connections at the half-sphere *-------------------------------------------------------------------------*/ -static void get_half_sphere_connection_options( +static ivas_error get_half_sphere_connection_options( const VBAP_SPEAKER_NODE *speaker_node_data, /* i : speaker node data */ const enum SpeakerNodeGroup group, /* i : speaker node group */ const int16_t num_speaker_nodes, /* i : number of speaker nodes */ @@ -1452,7 +1505,11 @@ static void get_half_sphere_connection_options( } /* Init memory for connection options */ - c_options = (ConnectionOption *) count_malloc( sizeof( ConnectionOption ) * max_num_connection_options ); + if ( ( c_options = (ConnectionOption *) malloc( sizeof( ConnectionOption ) * max_num_connection_options ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); + } + for ( c = 0; c < max_num_connection_options; c++ ) { c_options[c].chA = -1; @@ -1507,7 +1564,11 @@ static void get_half_sphere_connection_options( /* Init memory for reordered connection options and order by arc_weighted, * which informs of the preference order of the connections in case they cross */ - c_options_reorder = (ConnectionOption *) count_malloc( sizeof( ConnectionOption ) * ( *num_connection_options ) ); + if ( ( c_options_reorder = (ConnectionOption *) malloc( sizeof( ConnectionOption ) * ( *num_connection_options ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VBAP data\n" ) ); + } + for ( c = 0; c < *num_connection_options; c++ ) { float min_arc_weighted; @@ -1532,18 +1593,19 @@ static void get_half_sphere_connection_options( /* Set reordered connections as output and free temporary data */ *connection_options_pr = c_options_reorder; - count_free( c_options ); + free( c_options ); - return; + return IVAS_ERR_OK; } + /*-------------------------------------------------------------------------* * formulate_half_sphere_connections() * * Formulate half-sphere connections *-------------------------------------------------------------------------*/ -static void formulate_half_sphere_connections( +static ivas_error formulate_half_sphere_connections( const VBAP_SPEAKER_NODE *speaker_node_data, /* i : speaker node data */ const int16_t num_speaker_nodes, /* i : number of speaker nodes */ const enum SpeakerNodeGroup group, /* i : speaker node group */ @@ -1570,19 +1632,23 @@ static void formulate_half_sphere_connections( ConnectionOption *connection_options; int16_t num_connection_options; int16_t half_sphere_first_connection; + ivas_error error; half_sphere_first_connection = *connection_write_index; /* Obtain all connection options (i.e., channel pairs) at the half sphere. The function orders them * in terms of which connection to keep if two connections would cross each other. */ - get_half_sphere_connection_options( - speaker_node_data, - group, - num_speaker_nodes, - num_non_crossing_planes, - non_crossing_plane_elevation_deg, - &connection_options, - &num_connection_options ); + if ( ( error = get_half_sphere_connection_options( + speaker_node_data, + group, + num_speaker_nodes, + num_non_crossing_planes, + non_crossing_plane_elevation_deg, + &connection_options, + &num_connection_options ) ) != IVAS_ERR_OK ) + { + return error; + } set_f( connection_arc, 0.0f, max_num_connections ); for ( c = 0; c < max_num_connections; c++ ) @@ -1678,8 +1744,10 @@ static void formulate_half_sphere_connections( } c_opt++; } - count_free( connection_options ); - return; + + free( connection_options ); + + return IVAS_ERR_OK; } diff --git a/lib_dec/jbm_jb4_circularbuffer.c b/lib_dec/jbm_jb4_circularbuffer.c index a9da400a3604ba00cee41e5d4986740a6268ff06..e68b3e170e2e71260d37eb05aeebec5e37984789 100644 --- a/lib_dec/jbm_jb4_circularbuffer.c +++ b/lib_dec/jbm_jb4_circularbuffer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /* local includes */ #include "jbm_jb4_circularbuffer.h" @@ -70,9 +70,14 @@ struct JB4_CIRCULARBUFFER /* Creates a circular buffer (FIFO) */ -int16_t JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ) +ivas_error JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ) { - JB4_CIRCULARBUFFER_HANDLE h = count_malloc( sizeof( struct JB4_CIRCULARBUFFER ) ); + JB4_CIRCULARBUFFER_HANDLE h; + + if ( ( h = malloc( sizeof( struct JB4_CIRCULARBUFFER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } h->data = NULL; h->capacity = 0; @@ -81,7 +86,7 @@ int16_t JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ) *ph = h; - return 0; + return IVAS_ERR_OK; } @@ -103,9 +108,9 @@ void JB4_CIRCULARBUFFER_Destroy( if ( h->data ) { - count_free( h->data ); + free( h->data ); } - count_free( h ); + free( h ); *ph = NULL; return; @@ -119,13 +124,17 @@ int16_t JB4_CIRCULARBUFFER_Init( { /* keep one element free to be able to decide between full/empty buffer */ ++capacity; - h->data = count_malloc( capacity * sizeof( JB4_CIRCULARBUFFER_ELEMENT ) ); + + if ( ( h->data = malloc( capacity * sizeof( JB4_CIRCULARBUFFER_ELEMENT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } h->capacity = capacity; h->writePos = 0; h->readPos = 0; - return 0; + return IVAS_ERR_OK; } diff --git a/lib_dec/jbm_jb4_circularbuffer.h b/lib_dec/jbm_jb4_circularbuffer.h index 2e5a035dab0fa0fad72c5293edecc168ee370ab4..e14144b329e0984730809384e565db6c9b42b6ae 100644 --- a/lib_dec/jbm_jb4_circularbuffer.h +++ b/lib_dec/jbm_jb4_circularbuffer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -47,7 +47,7 @@ typedef struct JB4_CIRCULARBUFFER *JB4_CIRCULARBUFFER_HANDLE; typedef int32_t JB4_CIRCULARBUFFER_ELEMENT; -int16_t JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ); +ivas_error JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ); void JB4_CIRCULARBUFFER_Destroy( JB4_CIRCULARBUFFER_HANDLE *ph ); diff --git a/lib_dec/jbm_jb4_inputbuffer.c b/lib_dec/jbm_jb4_inputbuffer.c index 8eaf547838282229205a249c29fe2b7dd48176cb..925e35dfff2c23e7b28ad59f400d836f6cda0939 100644 --- a/lib_dec/jbm_jb4_inputbuffer.c +++ b/lib_dec/jbm_jb4_inputbuffer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,11 +33,9 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ /** \file jbm_jb4_inputbuffer.c RTP input buffer with fixed capacity. */ -/* system includes */ #include #include #include "options.h" @@ -46,8 +44,10 @@ #ifdef DEBUGGING #include "debug.h" #endif -/* local includes */ #include "jbm_jb4_inputbuffer.h" +#include "wmc_auto.h" + +#define WMC_TOOL_SKIP /** input buffer with fixed capacity */ @@ -67,10 +67,15 @@ struct JB4_INPUTBUFFER /* Creates a input buffer */ -int16_t JB4_INPUTBUFFER_Create( +ivas_error JB4_INPUTBUFFER_Create( JB4_INPUTBUFFER_HANDLE *ph ) { - JB4_INPUTBUFFER_HANDLE h = count_malloc( sizeof( struct JB4_INPUTBUFFER ) ); + JB4_INPUTBUFFER_HANDLE h; + + if ( ( h = malloc( sizeof( struct JB4_INPUTBUFFER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } h->data = NULL; h->capacity = 0; @@ -80,7 +85,7 @@ int16_t JB4_INPUTBUFFER_Create( *ph = h; - return 0; + return IVAS_ERR_OK; } @@ -99,9 +104,13 @@ void JB4_INPUTBUFFER_Destroy( { return; } + if ( h->data ) - count_free( h->data ); - count_free( h ); + { + free( h->data ); + } + + free( h ); *ph = NULL; return; @@ -109,7 +118,7 @@ void JB4_INPUTBUFFER_Destroy( /* Initializes a input buffer with a fixed maximum allowed number of elements */ -int16_t JB4_INPUTBUFFER_Init( +ivas_error JB4_INPUTBUFFER_Init( JB4_INPUTBUFFER_HANDLE h, uint16_t capacity, int16_t ( *compareFunction )( const JB4_INPUTBUFFER_ELEMENT first, const JB4_INPUTBUFFER_ELEMENT second, bool *replaceWithNewElementIfEqual ) ) @@ -117,13 +126,17 @@ int16_t JB4_INPUTBUFFER_Init( /* keep one element free to be able to decide between full/empty buffer */ ++capacity; - h->data = count_malloc( capacity * sizeof( JB4_INPUTBUFFER_ELEMENT ) ); + if ( ( h->data = malloc( capacity * sizeof( JB4_INPUTBUFFER_ELEMENT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } + h->capacity = capacity; h->writePos = 0; h->readPos = 0; h->compareFunction = compareFunction; - return 0; + return IVAS_ERR_OK; } @@ -359,3 +372,5 @@ uint16_t JB4_INPUTBUFFER_Size( return ret; } + +#undef WMC_TOOL_SKIP diff --git a/lib_dec/jbm_jb4_inputbuffer.h b/lib_dec/jbm_jb4_inputbuffer.h index 7ab80864702dcdd96da2c567b1c25b160f2a936f..6087ecb20717b76c316e2349ca79a0e95131629e 100644 --- a/lib_dec/jbm_jb4_inputbuffer.h +++ b/lib_dec/jbm_jb4_inputbuffer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -48,14 +48,11 @@ typedef struct JB4_INPUTBUFFER *JB4_INPUTBUFFER_HANDLE; typedef void *JB4_INPUTBUFFER_ELEMENT; -int16_t JB4_INPUTBUFFER_Create( JB4_INPUTBUFFER_HANDLE *ph ); +ivas_error JB4_INPUTBUFFER_Create( JB4_INPUTBUFFER_HANDLE *ph ); void JB4_INPUTBUFFER_Destroy( JB4_INPUTBUFFER_HANDLE *ph ); -int16_t JB4_INPUTBUFFER_Init( - JB4_INPUTBUFFER_HANDLE h, - uint16_t capacity, - int16_t ( *compareFunction )( const JB4_INPUTBUFFER_ELEMENT newElement, const JB4_INPUTBUFFER_ELEMENT arrayElement, bool *replaceWithNewElementIfEqual ) ); +ivas_error JB4_INPUTBUFFER_Init( JB4_INPUTBUFFER_HANDLE h, uint16_t capacity, int16_t ( *compareFunction )( const JB4_INPUTBUFFER_ELEMENT newElement, const JB4_INPUTBUFFER_ELEMENT arrayElement, bool *replaceWithNewElementIfEqual ) ); int16_t JB4_INPUTBUFFER_Enque( JB4_INPUTBUFFER_HANDLE h, JB4_INPUTBUFFER_ELEMENT element, JB4_INPUTBUFFER_ELEMENT *replacedElement ); diff --git a/lib_dec/jbm_jb4_jmf.c b/lib_dec/jbm_jb4_jmf.c index 7b0dd2f188ce44df863d1b1b252c9b4752d31cdf..85e9980e6ef8b11a2306f70f228227185034cfd0 100644 --- a/lib_dec/jbm_jb4_jmf.c +++ b/lib_dec/jbm_jb4_jmf.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /* local includes */ #include "jbm_jb4_jmf.h" @@ -84,19 +84,35 @@ struct JB4_JMF /** helper function to add an entry at back of the buffer */ -static void JB4_JMF_pushBack( JB4_JMF_HANDLE h, int32_t delay, int32_t offset, uint32_t time ); +static void JB4_JMF_pushBack( JB4_JMF_HANDLE h, const int32_t delay, const int32_t offset, const uint32_t time ); + /** helper function to remove an entry from the front of the buffer */ static void JB4_JMF_popFront( JB4_JMF_HANDLE h ); -int16_t JB4_JMF_Create( +ivas_error JB4_JMF_Create( JB4_JMF_HANDLE *ph ) { - JB4_JMF_HANDLE h = count_malloc( sizeof( struct JB4_JMF ) ); + JB4_JMF_HANDLE h; + ivas_error error; + + if ( ( h = malloc( sizeof( struct JB4_JMF ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } - JB4_CIRCULARBUFFER_Create( &h->fifo ); - JB4_CIRCULARBUFFER_Create( &h->offsetFifo ); - JB4_CIRCULARBUFFER_Create( &h->timeStampFifo ); + if ( ( error = JB4_CIRCULARBUFFER_Create( &h->fifo ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( JB4_CIRCULARBUFFER_Create( &h->offsetFifo ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( JB4_CIRCULARBUFFER_Create( &h->timeStampFifo ) ) != IVAS_ERR_OK ) + { + return error; + } h->timeScale = 1000; h->consideredFraction = 1000; @@ -108,7 +124,7 @@ int16_t JB4_JMF_Create( *ph = h; - return 0; + return IVAS_ERR_OK; } @@ -131,7 +147,7 @@ void JB4_JMF_Destroy( JB4_CIRCULARBUFFER_Destroy( &h->offsetFifo ); JB4_CIRCULARBUFFER_Destroy( &h->timeStampFifo ); - count_free( h ); + free( h ); *ph = NULL; return; @@ -141,10 +157,10 @@ void JB4_JMF_Destroy( /* function to set the window size of the fifo and the fraction which will be considered */ int16_t JB4_JMF_Init( JB4_JMF_HANDLE h, - int16_t timeScale, - uint16_t windowSize, - uint16_t windowDuration, - uint16_t consideredFraction ) + const int16_t timeScale, + const uint16_t windowSize, + const uint16_t windowDuration, + const uint16_t consideredFraction ) { /* check parameters */ @@ -175,8 +191,8 @@ int16_t JB4_JMF_Init( /* function to calculate delay for the current packet */ int16_t JB4_JMF_PushPacket( JB4_JMF_HANDLE h, - uint32_t sysTime, - uint32_t rtpTimeStamp ) + const uint32_t sysTime, + const uint32_t rtpTimeStamp ) { int32_t rtpTimeDiff, sysTimeDiff; int32_t offset, delay; @@ -267,9 +283,9 @@ int16_t JB4_JMF_MinOffset( /* helper function to add entry at back of the buffer */ static void JB4_JMF_pushBack( JB4_JMF_HANDLE h, - int32_t delay, - int32_t offset, - uint32_t time ) + const int32_t delay, + const int32_t offset, + const uint32_t time ) { int32_t minTime, maxTime; uint32_t duration; diff --git a/lib_dec/jbm_jb4_jmf.h b/lib_dec/jbm_jb4_jmf.h index b945c318846af76f8b32076eeb93d24a9840d2ac..5efff7cd5ee36c4a91bf2f4cf0dc3b400161f590 100644 --- a/lib_dec/jbm_jb4_jmf.h +++ b/lib_dec/jbm_jb4_jmf.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,13 +45,13 @@ /** handle for jitter measure fifo - a fifo used for windowed measure of network status */ typedef struct JB4_JMF *JB4_JMF_HANDLE; -int16_t JB4_JMF_Create( JB4_JMF_HANDLE *ph ); +ivas_error JB4_JMF_Create( JB4_JMF_HANDLE *ph ); void JB4_JMF_Destroy( JB4_JMF_HANDLE *ph ); -int16_t JB4_JMF_Init( JB4_JMF_HANDLE h, int16_t timeScale, uint16_t windowSize, uint16_t windowDuration, uint16_t consideredFraction ); +int16_t JB4_JMF_Init( JB4_JMF_HANDLE h, const int16_t timeScale, const uint16_t windowSize, const uint16_t windowDuration, const uint16_t consideredFraction ); -int16_t JB4_JMF_PushPacket( JB4_JMF_HANDLE h, uint32_t sysTime, uint32_t rtpTimeStamp ); +int16_t JB4_JMF_PushPacket( JB4_JMF_HANDLE h, const uint32_t sysTime, const uint32_t rtpTimeStamp ); int16_t JB4_JMF_Jitter( const JB4_JMF_HANDLE h, uint32_t *jitter ); diff --git a/lib_dec/jbm_jb4sb.c b/lib_dec/jbm_jb4sb.c index 28dfd43e61538b692837738829867074463ad503..755187b640347bd9d61a94b0fdb75342e636c13b 100644 --- a/lib_dec/jbm_jb4sb.c +++ b/lib_dec/jbm_jb4sb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ /*==================================================================================== EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ /*! \file jbm_jb4sb.c EVS Jitter Buffer Management Interface */ @@ -46,7 +45,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /* local headers */ #include "jbm_jb4_circularbuffer.h" #include "jbm_jb4_inputbuffer.h" @@ -54,6 +53,7 @@ #include "jbm_jb4sb.h" #include "prot.h" +#define WMC_TOOL_SKIP #define JB4_MIN( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) ) #define JB4_MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) ) @@ -61,7 +61,7 @@ #define MAXOFFSET 10 /*! Calculates the difference between two RTP timestamps - the diff is positive, if B 'later', negative otherwise */ -static int32_t JB4_rtpTimeStampDiff( uint32_t tsA, uint32_t tsB ); +static int32_t JB4_rtpTimeStampDiff( const uint32_t tsA, const uint32_t tsB ); /* function to calculate different options for the target playout delay */ static void JB4_targetPlayoutDelay( const JB4_HANDLE h, uint32_t *targetMin, uint32_t *targetMax, uint32_t *targetDtx, uint32_t *targetStartUp ); /*! function to do playout adaptation before playing the next data unit */ @@ -88,18 +88,18 @@ static int16_t JB4_inspectBufferForDropping( const JB4_HANDLE h, bool *dropEarly /* function to look into the buffer and check if it makes sense to drop a data unit during DTX */ static int16_t JB4_checkDtxDropping( const JB4_HANDLE h ); /*! function to estimate the short term jitter */ -static void JB4_estimateShortTermJitter( JB4_HANDLE h, uint32_t rcvTime, uint32_t rtpTimeStamp ); +static void JB4_estimateShortTermJitter( JB4_HANDLE h, const uint32_t rcvTime, const uint32_t rtpTimeStamp ); /*! function to pop a data unit from the buffer */ -static void JB4_popFromBuffer( JB4_HANDLE h, uint32_t sysTime, JB4_DATAUNIT_HANDLE *pDataUnit ); +static void JB4_popFromBuffer( JB4_HANDLE h, const uint32_t sysTime, JB4_DATAUNIT_HANDLE *pDataUnit ); /*! function to drop a data unit from the buffer - updates nShrinked */ static void JB4_dropFromBuffer( JB4_HANDLE h ); /*! function to calculate the playout delay based on the current jitter */ /*! @param[in] playTime the system time when the data unit will be played * @param[in] timeStamp the time stamp of the data unit to played * @param[out] delay the calculated playout delay */ -static int16_t JB4_playoutDelay( const JB4_HANDLE h, uint32_t playTime, uint32_t rtpTimeStamp, uint32_t *delay ); +static int16_t JB4_playoutDelay( const JB4_HANDLE h, const uint32_t playTime, const uint32_t rtpTimeStamp, uint32_t *delay ); /*! function to update lastPlayoutDelay and lastTargetTime after popFromBuffer() */ -static void JB4_updateLastTimingMembers( JB4_HANDLE h, uint32_t playTime, uint32_t rtpTimeStamp ); +static void JB4_updateLastTimingMembers( JB4_HANDLE h, const uint32_t playTime, const uint32_t rtpTimeStamp ); /*! function to compare the RTP time stamps of two data units: newElement==arrayElement ? 0 : (newElement>arrayElement ? +1 : -1) */ static int16_t JB4_inputBufferCompareFunction( const JB4_INPUTBUFFER_ELEMENT newElement, const JB4_INPUTBUFFER_ELEMENT arrayElement, bool *replaceWithNewElementIfEqual ); @@ -207,8 +207,9 @@ ivas_error JB4_Create( { int16_t iter; JB4_HANDLE h; + ivas_error error; - if ( ( h = count_malloc( sizeof( struct JB4 ) ) ) == NULL ) + if ( ( h = malloc( sizeof( struct JB4 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JB4 structure\n" ) ); } @@ -228,12 +229,23 @@ ivas_error JB4_Create( /* internal configuration values - do not change!!! */ h->timeScale = 0; h->frameDuration = 0; + /* jitter buffer configuration values: done in JB4_Init() */ /* short term jitter evaluation */ - JB4_JMF_Create( &h->stJmf ); - JB4_CIRCULARBUFFER_Create( &h->stJitterFifo ); - JB4_CIRCULARBUFFER_Create( &h->stTimeStampFifo ); + if ( ( error = JB4_JMF_Create( &h->stJmf ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = JB4_CIRCULARBUFFER_Create( &h->stJitterFifo ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = JB4_CIRCULARBUFFER_Create( &h->stTimeStampFifo ) ) != IVAS_ERR_OK ) + { + return error; + } h->stJitter = 0; + /* jitter buffer data */ h->firstDataUnitPopped = false; h->prevPopSysTime = 0; @@ -266,11 +278,18 @@ ivas_error JB4_Create( move32(); /* members to store the data units */ - JB4_INPUTBUFFER_Create( &h->inputBuffer ); + if ( ( error = JB4_INPUTBUFFER_Create( &h->inputBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + /* allocate memory for data units */ for ( iter = 0; iter < MAX_JBM_SLOTS; ++iter ) { - h->memorySlots[iter].data = count_malloc( MAX_AU_SIZE ); + if ( ( h->memorySlots[iter].data = malloc( MAX_AU_SIZE ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JB4 structure\n" ) ); + } h->freeMemorySlots[iter] = &h->memorySlots[iter]; } h->nFreeMemorySlots = MAX_JBM_SLOTS; @@ -304,22 +323,23 @@ void JB4_Destroy( for ( i = 0; i < MAX_JBM_SLOTS; ++i ) { - count_free( h->memorySlots[i].data ); + free( h->memorySlots[i].data ); } - count_free( h ); + free( h ); *ph = NULL; return; } -int16_t JB4_Init( +ivas_error JB4_Init( JB4_HANDLE h, - int16_t safetyMargin ) + const int16_t safetyMargin ) { uint16_t ltJmfSize, stFifoSize, stJmfSize, stJmfAllowedLateLoss; uint16_t inputBufferCapacity; + ivas_error error; /* internal timescale is 1000, frame duration is 20ms */ h->timeScale = 1000; /* ms */ @@ -340,9 +360,13 @@ int16_t JB4_Init( JB4_JMF_Init( h->stJmf, h->timeScale, stJmfSize, h->timeScale /* 1s */, (uint16_t) ( 1000 - stJmfAllowedLateLoss ) ); inputBufferCapacity = MAX_JBM_SLOTS - 2; - JB4_INPUTBUFFER_Init( h->inputBuffer, inputBufferCapacity, JB4_inputBufferCompareFunction ); - return 0; + if ( ( error = JB4_INPUTBUFFER_Init( h->inputBuffer, inputBufferCapacity, JB4_inputBufferCompareFunction ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; } @@ -383,7 +407,7 @@ void JB4_FreeDataUnit( int16_t JB4_PushDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit, - uint32_t rcvTime ) + const uint32_t rcvTime ) { JB4_DATAUNIT_HANDLE droppedDataUnit = NULL; @@ -551,8 +575,8 @@ int16_t JB4_FECoffset( int16_t JB4_PopDataUnit( JB4_HANDLE h, - uint32_t sysTime, - uint32_t extBufferedTime, + const uint32_t sysTime, + const uint32_t extBufferedTime, JB4_DATAUNIT_HANDLE *pDataUnit, uint32_t *scale, uint32_t *maxScaling ) @@ -574,8 +598,8 @@ int16_t JB4_PopDataUnit( /* Calculates the difference between two RTP timestamps - the diff is positive, if B 'later', negative otherwise */ static int32_t JB4_rtpTimeStampDiff( - uint32_t tsA, - uint32_t tsB ) + const uint32_t tsA, + const uint32_t tsB ) { int32_t ret; /* do not dare to inline this function, casting to int32_t is important here! */ @@ -1058,8 +1082,8 @@ static int16_t JB4_checkDtxDropping( /* function to estimate the short term jitter */ static void JB4_estimateShortTermJitter( JB4_HANDLE h, - uint32_t rcvTime, - uint32_t rtpTimeStamp ) + const uint32_t rcvTime, + const uint32_t rtpTimeStamp ) { uint32_t jitter, duration, maxDuration; int32_t minTime, maxTime; @@ -1121,7 +1145,7 @@ static void JB4_estimateShortTermJitter( /* function to pop a data unit from the buffer */ static void JB4_popFromBuffer( JB4_HANDLE h, - uint32_t sysTime, + const uint32_t sysTime, JB4_DATAUNIT_HANDLE *pDataUnit ) { JB4_DATAUNIT_HANDLE nextDataUnit; @@ -1430,8 +1454,8 @@ static void JB4_dropFromBuffer( /* function to calculate the playout delay based on the current jitter */ static int16_t JB4_playoutDelay( const JB4_HANDLE h, - uint32_t playTime, - uint32_t rtpTimeStamp, + const uint32_t playTime, + const uint32_t rtpTimeStamp, uint32_t *delay ) { int32_t minOffTicks; @@ -1450,8 +1474,8 @@ static int16_t JB4_playoutDelay( /* function to update lastPlayoutDelay and lastTargetTime after popFromBuffer() */ static void JB4_updateLastTimingMembers( JB4_HANDLE h, - uint32_t playTime, - uint32_t rtpTimeStamp ) + const uint32_t playTime, + const uint32_t rtpTimeStamp ) { int32_t minOffTicks; @@ -1508,3 +1532,5 @@ static int16_t JB4_inputBufferCompareFunction( return result; } + +#undef WMC_TOOL_SKIP diff --git a/lib_dec/jbm_jb4sb.h b/lib_dec/jbm_jb4sb.h index bc70413689b087cba0bf8053743804407fa31fcf..54b873b006b1c9532794cae661a7f3c2aea031ad 100644 --- a/lib_dec/jbm_jb4sb.h +++ b/lib_dec/jbm_jb4sb.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -63,9 +63,6 @@ struct JB4_DATAUNIT uint32_t rcvTime; /** true, if the data unit contains only silence */ bool silenceIndicator; - Word16 isAMRWB_IOmode; - /** for EVS payload */ - Word16 frameTypeIndex; /** Q bit for AMR-WB IO */ Word16 qBit; @@ -88,15 +85,15 @@ ivas_error JB4_Create( JB4_HANDLE *ph ); void JB4_Destroy( JB4_HANDLE *ph ); -int16_t JB4_Init( JB4_HANDLE h, int16_t safetyMargin ); +ivas_error JB4_Init( JB4_HANDLE h, const int16_t safetyMargin ); JB4_DATAUNIT_HANDLE JB4_AllocDataUnit( JB4_HANDLE h ); void JB4_FreeDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit ); -int16_t JB4_PushDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit, uint32_t rcvTime ); +int16_t JB4_PushDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit, const uint32_t rcvTime ); -int16_t JB4_PopDataUnit( JB4_HANDLE h, uint32_t sysTime, uint32_t extBufferedTime, JB4_DATAUNIT_HANDLE *pDataUnit, uint32_t *scale, uint32_t *maxScaling ); +int16_t JB4_PopDataUnit( JB4_HANDLE h, const uint32_t sysTime, const uint32_t extBufferedTime, JB4_DATAUNIT_HANDLE *pDataUnit, uint32_t *scale, uint32_t *maxScaling ); int16_t JB4_getFECoffset( JB4_HANDLE h ); diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c index 3968e38974dba01378f418e4d059f28b74e07a00..c816a9d9c8b4fadbea3da7e1ccb7061dbc4cd677 100644 --- a/lib_dec/jbm_pcmdsp_apa.c +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -47,7 +47,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /* local headers */ #include "jbm_pcmdsp_apa.h" #include "jbm_pcmdsp_similarityestimation.h" @@ -66,11 +66,12 @@ struct apa_state_t { /* output buffer */ - int16_t buf_out[APA_BUF]; + int16_t *buf_out; + uint16_t buf_out_capacity; uint16_t l_buf_out; /* Hann window */ - float win[APA_BUF]; + float win[APA_BUF_PER_CHANNEL]; uint16_t l_halfwin; /* sampling rate [Hz] */ @@ -99,8 +100,8 @@ struct apa_state_t /* search length [samples] */ uint16_t l_search; - uint16_t wss; /* waveform subsampling */ - uint16_t css; /* correlation subsampling */ + uint16_t wss; /* waveform subsampling per channel */ + uint16_t css; /* correlation subsampling per channel */ float targetQuality; uint16_t qualityred; /* quality reduction threshold */ @@ -138,8 +139,9 @@ static bool extend_frm( apa_state_t *ps, const int16_t frm_in[], int16_t frm_out *---------------------------------------------------------------------*/ /* Allocates memory for state struct and initializes elements. */ -uint8_t apa_init( - apa_state_t **pps ) +ivas_error apa_init( + apa_state_t **pps, + const int32_t num_channels ) { apa_state_t *ps = NULL; @@ -150,15 +152,22 @@ uint8_t apa_init( } /* allocate state struct */ - ps = (apa_state_t *) count_malloc( sizeof( apa_state_t ) ); - if ( !ps ) + if ( ( ps = (apa_state_t *) malloc( sizeof( apa_state_t ) ) ) == NULL ) { - return 2; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } + + ps->num_channels = (uint16_t) num_channels; + ps->buf_out_capacity = (uint16_t) ( APA_BUF_PER_CHANNEL * num_channels ); + if ( ( ps->buf_out = malloc( sizeof( float ) * ps->buf_out_capacity ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); } + apa_reset( ps ); *pps = ps; - return 0; + return IVAS_ERR_OK; } @@ -186,7 +195,6 @@ void apa_reset( ps->last_pitch = 0; ps->bad_frame_count = 0; ps->good_frame_count = 0; - ps->num_channels = 0; return; } @@ -195,8 +203,7 @@ void apa_reset( /* Sets the audio configuration. */ bool apa_set_rate( apa_state_t *ps, - const int32_t output_Fs, - const int16_t num_channels ) + const int32_t output_Fs ) { /* make sure pointer is valid */ if ( ps == NULL ) @@ -216,8 +223,10 @@ bool apa_set_rate( /* copy rate to state struct */ ps->rate = (uint16_t) output_Fs; - /* set number of channels */ - ps->num_channels = num_channels; + if ( ps->num_channels > APA_MAX_NUM_CHANNELS ) + { + return 1; + } /* * several other parameters depend on the sampling rate @@ -235,8 +244,7 @@ bool apa_set_rate( ps->l_seg = ( ps->rate / 100 ) * ps->num_channels; /* init Hann window */ - /* Note: l_win < APA_BUF is required, which is assured */ - /* because APA_MAX_RATE/100 = l_win = 441 < 2048 = APA_BUF */ + /* Note: l_win < APA_BUF_PER_CHANNEL is required */ /* Length of Hann window should be independent of * number of channels - same window applied to all channels */ ps->l_halfwin = ps->rate / 100; @@ -401,8 +409,11 @@ bool apa_exit( return 0; } + /* deallocate state struct members */ + free( ( *pps )->buf_out ); + /* deallocate state struct */ - count_free( *pps ); + free( *pps ); /* set pointer to NULL */ *pps = NULL; @@ -452,7 +463,7 @@ uint8_t apa_exec( ) { uint16_t i; - int16_t frm_in[APA_BUF]; + int16_t frm_in[APA_BUF]; /* TODO(mcjbm): this buffer could be smaller - always allocates space for 16 channels */ uint16_t l_frm_out; int16_t l_rem; int32_t dl_scaled, dl_copied, l_frm_out_target; @@ -462,6 +473,9 @@ uint8_t apa_exec( statsResetThreshold = 1637; statsResetShift = 2; + /* Convert max_scaling from "per channel" to total */ + maxScaling *= ps->num_channels; + /* make sure no invalid output is used */ *l_out = 0; l_frm_out = 0; @@ -565,7 +579,7 @@ uint8_t apa_exec( /* copy output to internal buffer */ /* avoid buffer overflow: */ /* discard old samples; always keep at least most recent l_frm samples */ - if ( ( ps->l_buf_out + l_frm_out ) > APA_BUF ) + if ( ( ps->l_buf_out + l_frm_out ) > ps->buf_out_capacity ) { int16_t *buf_out_ptr1 = ps->buf_out; int16_t *buf_out_ptr2; @@ -583,7 +597,7 @@ uint8_t apa_exec( ps->l_buf_out = l_rem; } /* append new output samples */ - if ( ( ps->l_buf_out + l_frm_out ) > APA_BUF ) + if ( ( ps->l_buf_out + l_frm_out ) > ps->buf_out_capacity ) { return 5; } @@ -818,7 +832,7 @@ static bool logarithmic_search( do { coeff_max = -FLT_MAX; /* will always be overwritten with result of first correlation */ - for ( i = s_start; i < s_start + inlen; i += css ) + for ( i = s_start; i < s_start + inlen; i += css * ps->num_channels ) { if ( ( wss == 1 ) && ( ps->num_channels == 1 ) ) { @@ -929,7 +943,7 @@ static bool find_synch( /* pass last pitch to search function as prediction value */ *synch_pos = ps->last_pitch; - logarithmic_search( ps, in, s_start, s_len, offset, fixed_pos, corr_len, ps->wss, ps->css * ps->num_channels, synch_pos ); + logarithmic_search( ps, in, s_start, s_len, offset, fixed_pos, corr_len, ps->wss, ps->css, synch_pos ); /* assert synch_pos is cleanly divisible by number of channels */ assert( *synch_pos % ps->num_channels == 0 ); diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h index 5cf4e7d8b6d4dc97f4694bdae5ac18241fa5411c..543042f53b4301789af0eabe9fddee082254c8fa 100644 --- a/lib_dec/jbm_pcmdsp_apa.h +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -50,7 +50,9 @@ */ /* size of IO buffers (a_in[], a_out[]) for apa_exec() */ -#define APA_BUF 4096 * 3 +#define APA_BUF_PER_CHANNEL ( 960 * 3 ) +#define APA_MAX_NUM_CHANNELS 16 +#define APA_BUF ( APA_BUF_PER_CHANNEL * APA_MAX_NUM_CHANNELS ) /* min/max sampling rate [Hz] */ #define APA_MIN_RATE 1000 @@ -89,7 +91,8 @@ typedef struct apa_state_t *PCMDSP_APA_HANDLE; /*! Allocates memory for state struct and initializes elements. * @return 0 on success, 1 on failure */ -uint8_t apa_init( apa_state_t **s ); +ivas_error apa_init( apa_state_t **s, + const int32_t num_channels ); /*! Sets state variables to initial value. */ void apa_reset( apa_state_t *s ); @@ -103,7 +106,7 @@ void apa_reset( apa_state_t *s ); * @param[in] output_Fs sample rate [Hz] * @param[in] num_channels number of channels * @return 0 on success, 1 on failure */ -bool apa_set_rate( apa_state_t *ps, const int32_t output_Fs, const int16_t num_channels ); +bool apa_set_rate( apa_state_t *ps, const int32_t output_Fs ); /*! Set scaling. * The scale is given in % and will be valid until changed again. diff --git a/lib_dec/jbm_pcmdsp_fifo.c b/lib_dec/jbm_pcmdsp_fifo.c index 86990618fd0d5122cbdaef3d0e7fafd673213191..81e833e5e56fc3860b7045c6b97405e52b71ae15 100644 --- a/lib_dec/jbm_pcmdsp_fifo.c +++ b/lib_dec/jbm_pcmdsp_fifo.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,15 +43,20 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "jbm_pcmdsp_fifo.h" /* Creates a FIFO. */ -int16_t pcmdsp_fifo_create( +ivas_error pcmdsp_fifo_create( PCMDSP_FIFO_HANDLE *ph ) { - PCMDSP_FIFO_HANDLE h = count_malloc( sizeof( struct PCMDSP_FIFO ) ); + PCMDSP_FIFO_HANDLE h; + + if ( ( h = malloc( sizeof( struct PCMDSP_FIFO ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } h->size = 0; h->capacity = 0; @@ -63,7 +68,7 @@ int16_t pcmdsp_fifo_create( *ph = h; - return 0; + return IVAS_ERR_OK; } @@ -85,33 +90,37 @@ void pcmdsp_fifo_destroy( if ( h->dataBegin ) { - count_free( h->dataBegin ); + free( h->dataBegin ); } - count_free( h ); + free( h ); *ph = NULL; return; } /* Initializes the FIFO with a fixed maximum allowed number audio samples. */ -int16_t pcmdsp_fifo_init( +ivas_error pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, - uint16_t nSamples, + uint16_t nSamplesPerChannel, uint16_t nChannels, uint16_t nBytesPerSample ) { - uint16_t nDataBytes; + uint32_t nDataBytes; /* Must be 32-bit, otherwise overflows for multichannel */ - h->capacity = nSamples; + h->capacity = nSamplesPerChannel; h->nBytesPerSampleSet = nChannels * nBytesPerSample; - nDataBytes = nSamples * h->nBytesPerSampleSet; - h->dataBegin = count_malloc( nDataBytes ); + nDataBytes = nSamplesPerChannel * h->nBytesPerSampleSet; + if ( ( h->dataBegin = malloc( nDataBytes ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) ); + } + h->dataEnd = h->dataBegin + nDataBytes; h->dataWriteIterator = h->dataBegin; h->dataReadIterator = h->dataBegin; - return 0; + return IVAS_ERR_OK; } @@ -201,7 +210,7 @@ int16_t pcmdsp_fifo_read( /* Returns the number of samples per channel that can be read (number of currently stored samples). */ -uint16_t pcmdsp_fifo_nReadableSamples( +uint16_t pcmdsp_fifo_nReadableSamplesPerChannel( const PCMDSP_FIFO_HANDLE h ) { return h->size; diff --git a/lib_dec/jbm_pcmdsp_fifo.h b/lib_dec/jbm_pcmdsp_fifo.h index bdd186702e1be2b78e5bcf4816ecc643628fc012..13ffd146f871fb1b4d7c227b965a1931ba2f1e11 100644 --- a/lib_dec/jbm_pcmdsp_fifo.h +++ b/lib_dec/jbm_pcmdsp_fifo.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -66,16 +66,16 @@ struct PCMDSP_FIFO typedef struct PCMDSP_FIFO *PCMDSP_FIFO_HANDLE; -int16_t pcmdsp_fifo_create( PCMDSP_FIFO_HANDLE *ph ); +ivas_error pcmdsp_fifo_create( PCMDSP_FIFO_HANDLE *ph ); void pcmdsp_fifo_destroy( PCMDSP_FIFO_HANDLE *ph ); -int16_t pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, uint16_t nSamples, uint16_t nChannels, uint16_t nBytesPerSample ); +ivas_error pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel, uint16_t nChannels, uint16_t nBytesPerSample ); int16_t pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const uint8_t *samples, uint16_t nSamplesPerChannel ); int16_t pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, uint16_t nSamplesPerChannel, uint8_t *samples ); -uint16_t pcmdsp_fifo_nReadableSamples( const PCMDSP_FIFO_HANDLE h ); +uint16_t pcmdsp_fifo_nReadableSamplesPerChannel( const PCMDSP_FIFO_HANDLE h ); #endif /* JBM_PCMDSP_FIFO_H */ diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.c b/lib_dec/jbm_pcmdsp_similarityestimation.c index 3016fab5e1dac6f1652469379679250bc44c09e7..f575acc7ad337f77ac81495ec36340ce1ce2ef49 100644 --- a/lib_dec/jbm_pcmdsp_similarityestimation.c +++ b/lib_dec/jbm_pcmdsp_similarityestimation.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /* local headers */ #include "jbm_pcmdsp_similarityestimation.h" diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.h b/lib_dec/jbm_pcmdsp_similarityestimation.h index 36f64d7297b5ea6f469844bd355bac5b4320b311..4dc92f27b7cff9320280124d17733c6d6f7feabc 100644 --- a/lib_dec/jbm_pcmdsp_similarityestimation.h +++ b/lib_dec/jbm_pcmdsp_similarityestimation.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_dec/jbm_pcmdsp_window.c b/lib_dec/jbm_pcmdsp_window.c index 94182e5ad67ff603ba4157178d44a6bda9429277..f9f71ac802093d4a0b8dbfcab05d43895dae989d 100644 --- a/lib_dec/jbm_pcmdsp_window.c +++ b/lib_dec/jbm_pcmdsp_window.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #endif #include "jbm_pcmdsp_window.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * hannWindow() diff --git a/lib_dec/jbm_pcmdsp_window.h b/lib_dec/jbm_pcmdsp_window.h index cf697b6b9c6f6886f7518c2039c883c3bc3b4dea..67759e97384d759c2666f260eb2fd0754afe1326 100644 --- a/lib_dec/jbm_pcmdsp_window.h +++ b/lib_dec/jbm_pcmdsp_window.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_dec/lead_deindexing.c b/lib_dec/lead_deindexing.c index 246e0df391e41d8c7649683295a8d22f0e9a5c37..830daa81207796655b42c6f8125b61e450f42d39 100644 --- a/lib_dec/lead_deindexing.c +++ b/lib_dec/lead_deindexing.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_dec.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 26a0bb0c925cc9112b2d34e06426407d67d84e5f..a1410c482e1031ad3e6ed4c3480ea175ba449102 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,6 +32,7 @@ #include "lib_dec.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "prot.h" #include "jbm_jb4sb.h" #include "jbm_pcmdsp_apa.h" @@ -42,9 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#ifdef WMOPS -#include "wmops.h" -#endif +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local structs @@ -52,11 +51,14 @@ struct IVAS_DEC_VOIP { - uint16_t nSamplesFrame; + uint16_t nSamplesFrame; /* Total number of samples in a frame (includes number of channels) */ JB4_HANDLE hJBM; PCMDSP_APA_HANDLE hTimeScaler; PCMDSP_FIFO_HANDLE hFifoAfterTimeScaler; uint16_t lastDecodedWasActive; + int16_t *apaExecBuffer; /* Buffer for APA scaling */ + JB4_DATAUNIT_HANDLE hCurrentDataUnit; /* Points to the currently processed data unit */ + uint16_t *bs_conversion_buf; /* Buffer for bitstream conversion from packed to serial */ #ifdef SUPPORT_JBM_TRACEFILE IVAS_JBM_TRACE_DATA JbmTraceData; #endif @@ -110,13 +112,18 @@ ivas_error IVAS_DEC_Open( float no_diegetic_pan ) { IVAS_DEC_HANDLE hIvasDec; + Decoder_Struct *st_ivas; if ( phIvasDec == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - if ( ( *phIvasDec = (IVAS_DEC_HANDLE) count_malloc( sizeof( struct IVAS_DEC ) ) ) == NULL ) + /*-----------------------------------------------------------------* + * Allocate and initialize IVAS application decoder handle + *-----------------------------------------------------------------*/ + + if ( ( *phIvasDec = (IVAS_DEC_HANDLE) malloc( sizeof( struct IVAS_DEC ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS decoder handle" ); } @@ -128,56 +135,69 @@ ivas_error IVAS_DEC_Open( hIvasDec->mode = mode; - if ( ( hIvasDec->st_ivas = (Decoder_Struct *) count_malloc( sizeof( Decoder_Struct ) ) ) == NULL ) + hIvasDec->bitstreamformat = G192; + hIvasDec->Opt_VOIP = 0; + hIvasDec->amrwb_rfc4867_flag = -1; + hIvasDec->prev_ft_speech = 1; /* RXDTX handler previous frametype flag for G.192 format AMRWB SID_FIRST detection */ + hIvasDec->CNG = 0; /* RXDTX handler CNG = 1, no CNG = 0*/ + + /*-----------------------------------------------------------------* + * Initialize IVAS-codec decoder state + *-----------------------------------------------------------------*/ + + if ( ( hIvasDec->st_ivas = (Decoder_Struct *) malloc( sizeof( Decoder_Struct ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS decoder structure" ); } - if ( ( hIvasDec->st_ivas->hDecoderConfig = (DECODER_CONFIG_HANDLE) count_malloc( sizeof( DECODER_CONFIG ) ) ) == NULL ) + if ( ( hIvasDec->st_ivas->hDecoderConfig = (DECODER_CONFIG_HANDLE) malloc( sizeof( DECODER_CONFIG ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Decoder config structure" ); } + /*-----------------------------------------------------------------* + * Initialize IVAS-codec decoder state + *-----------------------------------------------------------------*/ + + st_ivas = hIvasDec->st_ivas; + + /* initialize Decoder Config. handle */ init_decoder_config( hIvasDec->st_ivas->hDecoderConfig, orientation_tracking, no_diegetic_pan ); - hIvasDec->bitstreamformat = G192; - hIvasDec->Opt_VOIP = 0; - hIvasDec->amrwb_rfc4867_flag = -1; - hIvasDec->prev_ft_speech = 1; /* RXDTX handeler previous frametype flag for G.192 format AMRWB SID_FIRST detection */ - hIvasDec->CNG = 0; /* RXDTX handler CNG = 1, no CNG = 0*/ + /* initialize pointers to handles to NULL */ + ivas_initialize_handles_dec( st_ivas ); + /* set high-level parameters */ if ( mode == IVAS_DEC_MODE_EVS ) { - /* EVS - do alloc etc. */ - hIvasDec->st_ivas->codec_mode = 0; /* unknown before first frame */ - hIvasDec->st_ivas->element_mode_init = EVS_MONO; - hIvasDec->st_ivas->ivas_format = MONO_FORMAT; - hIvasDec->st_ivas->transport_config = AUDIO_CONFIG_INVALID; - hIvasDec->st_ivas->intern_config = AUDIO_CONFIG_INVALID; - hIvasDec->st_ivas->writeFECoffset = 0; + st_ivas->codec_mode = 0; /* unknown before first frame */ + st_ivas->element_mode_init = EVS_MONO; + st_ivas->ivas_format = MONO_FORMAT; + st_ivas->transport_config = AUDIO_CONFIG_INVALID; + st_ivas->intern_config = AUDIO_CONFIG_INVALID; + st_ivas->writeFECoffset = 0; return IVAS_ERR_OK; } else if ( mode == IVAS_DEC_MODE_IVAS ) { - hIvasDec->st_ivas->codec_mode = 0; /* unknown before first frame */ - hIvasDec->st_ivas->element_mode_init = -1; - hIvasDec->st_ivas->ivas_format = UNDEFINED_FORMAT; - hIvasDec->st_ivas->transport_config = AUDIO_CONFIG_INVALID; - hIvasDec->st_ivas->intern_config = AUDIO_CONFIG_INVALID; - hIvasDec->st_ivas->renderer_type = RENDERER_DISABLE; - hIvasDec->st_ivas->ini_frame = 0; - hIvasDec->st_ivas->ini_active_frame = 0; - hIvasDec->st_ivas->writeFECoffset = 0; - hIvasDec->st_ivas->sba_order = 0; - hIvasDec->st_ivas->sba_planar = 0; - - /*initialize pointers*/ - ivas_initialize_handles_dec( hIvasDec->st_ivas ); - - hIvasDec->st_ivas->ism_mode = ISM_MODE_NONE; - hIvasDec->st_ivas->sba_mode = SBA_MODE_NONE; - hIvasDec->st_ivas->mc_mode = MC_MODE_NONE; + st_ivas->codec_mode = 0; /* unknown before first frame */ + st_ivas->element_mode_init = -1; + st_ivas->ivas_format = UNDEFINED_FORMAT; + st_ivas->transport_config = AUDIO_CONFIG_INVALID; + st_ivas->intern_config = AUDIO_CONFIG_INVALID; + st_ivas->renderer_type = RENDERER_DISABLE; + st_ivas->ini_frame = 0; + st_ivas->ini_active_frame = 0; + st_ivas->writeFECoffset = 0; + + st_ivas->ism_mode = ISM_MODE_NONE; + st_ivas->sba_mode = SBA_MODE_NONE; + st_ivas->mc_mode = MC_MODE_NONE; + + st_ivas->sba_order = 0; + st_ivas->sba_planar = 0; + st_ivas->sba_analysis_order = 0; return IVAS_ERR_OK; } @@ -203,9 +223,7 @@ static void init_decoder_config( hDecoderConfig->Opt_LsCustom = 0; hDecoderConfig->Opt_HRTF_binary = 0; hDecoderConfig->Opt_Headrotation = 0; -#ifdef DEBUGGING - hDecoderConfig->forceSubframeBinauralization = 0; -#endif + hDecoderConfig->Opt_RendConfigCustom = 0; hDecoderConfig->orientation_tracking = orientation_tracking; hDecoderConfig->no_diegetic_pan = no_diegetic_pan; @@ -232,38 +250,16 @@ void IVAS_DEC_Close( if ( ( *phIvasDec )->hVoIP ) { IVAS_DEC_Close_VoIP( ( *phIvasDec )->hVoIP ); - count_free( ( *phIvasDec )->hVoIP ); + ( *phIvasDec )->hVoIP = NULL; } - if ( ( *phIvasDec )->isInitialized ) + if ( ( *phIvasDec )->st_ivas ) { - if ( ( *phIvasDec )->st_ivas ) - { - ivas_destroy_dec( ( *phIvasDec )->st_ivas ); - } - } - else - { - if ( ( *phIvasDec )->st_ivas->hDecoderConfig != NULL ) - { - count_free( ( *phIvasDec )->st_ivas->hDecoderConfig ); - ( *phIvasDec )->st_ivas->hDecoderConfig = NULL; - } - - if ( ( *phIvasDec )->st_ivas->hHeadTrackData != NULL ) - { - count_free( ( *phIvasDec )->st_ivas->hHeadTrackData ); - ( *phIvasDec )->st_ivas->hHeadTrackData = NULL; - } - - ivas_HRTF_binary_close( &( *phIvasDec )->st_ivas->hHrtfTD ); - - count_free( ( *phIvasDec )->st_ivas ); + ivas_destroy_dec( ( *phIvasDec )->st_ivas ); + ( *phIvasDec )->st_ivas = NULL; } - ( *phIvasDec )->st_ivas = NULL; - - count_free( *phIvasDec ); + free( *phIvasDec ); *phIvasDec = NULL; phIvasDec = NULL; @@ -391,11 +387,8 @@ ivas_error IVAS_DEC_Configure( const IVAS_DEC_AUDIO_CONFIG outputFormat, /* i : output format */ const int16_t customLsOutputEnabled, /* i : enable custom loudspeaker setup handle */ const int16_t hrtfReaderEnabled, /* i : enable HRTF binary file input */ - const int16_t enableHeadRotation /* i : enable head rotation for binaural output */ -#ifdef DEBUGGING - , - const int16_t forceSubframeBinauralization /* i : enable subframe binauralization */ -#endif + const int16_t enableHeadRotation, /* i : enable head rotation for binaural output */ + const int16_t renderConfigEnabled /* i : enable Renderer config. file for binaural output */ ) { Decoder_Struct *st_ivas; @@ -441,12 +434,10 @@ ivas_error IVAS_DEC_Configure( hDecoderConfig->nchan_out = audioCfg2channels( hDecoderConfig->output_config ); } -#ifdef DEBUGGING - hDecoderConfig->forceSubframeBinauralization = forceSubframeBinauralization; -#endif hDecoderConfig->Opt_LsCustom = customLsOutputEnabled; hDecoderConfig->Opt_Headrotation = enableHeadRotation; hDecoderConfig->Opt_HRTF_binary = hrtfReaderEnabled; + hDecoderConfig->Opt_RendConfigCustom = renderConfigEnabled; /* Set decoder parameters to initial values */ if ( ( error = ivas_init_decoder_front( st_ivas ) ) != IVAS_ERR_OK ) @@ -490,44 +481,52 @@ ivas_error IVAS_DEC_EnableVoIP( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - if ( !hIvasDec->isInitialized ) - { - if ( ( error = ivas_init_decoder( hIvasDec->st_ivas ) ) != IVAS_ERR_OK ) - { - return error; - } - - hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00; - hIvasDec->isInitialized = true; - } hDecoderConfig = hIvasDec->st_ivas->hDecoderConfig; hIvasDec->Opt_VOIP = 1; - hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]->codec_mode = 0; - hDecoderConfig->nchan_out = 1; /* VoIP only supported in mono */ + + hDecoderConfig->nchan_out = audioCfg2channels( hDecoderConfig->output_config ); + assert( hDecoderConfig->nchan_out > 0 && "EXT output not yet supported in VoIP mode" ); + if ( ( error = input_format_API_to_internal( inputFormat, &hIvasDec->bitstreamformat, &hIvasDec->sdp_hf_only, true ) ) != IVAS_ERR_OK ) { return error; } - hIvasDec->hVoIP = count_malloc( sizeof( IVAS_DEC_VOIP ) ); + hIvasDec->hVoIP = malloc( sizeof( IVAS_DEC_VOIP ) ); + if ( hIvasDec->hVoIP == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); + } + hIvasDec->hVoIP->lastDecodedWasActive = 0; - hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs / FRAMES_PER_SEC ); + hIvasDec->hVoIP->hCurrentDataUnit = NULL; + hIvasDec->hVoIP->nSamplesFrame = (uint16_t) ( hDecoderConfig->output_Fs * hDecoderConfig->nchan_out / FRAMES_PER_SEC ); + + hIvasDec->hVoIP->apaExecBuffer = malloc( sizeof( int16_t ) * APA_BUF_PER_CHANNEL * hDecoderConfig->nchan_out ); + if ( hIvasDec->hVoIP->apaExecBuffer == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); + } - /* Copy updated configuration to core coder */ +#define WMC_TOOL_SKIP + /* Bitstream conversion is not counted towards complexity and memory usage */ + hIvasDec->hVoIP->bs_conversion_buf = malloc( sizeof( uint16_t ) * ( MAX_BITS_PER_FRAME + 4 * 8 ) ); +#undef WMC_TOOL_SKIP - if ( hIvasDec->hVoIP == NULL ) + if ( hIvasDec->hVoIP->bs_conversion_buf == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate VoIP handle" ); } + /* initialize JBM */ if ( ( error = JB4_Create( &hIvasDec->hVoIP->hJBM ) != IVAS_ERR_OK ) != IVAS_ERR_OK ) { return error; } - if ( JB4_Init( hIvasDec->hVoIP->hJBM, jbmSafetyMargin ) != 0 ) + if ( ( error = JB4_Init( hIvasDec->hVoIP->hJBM, jbmSafetyMargin ) ) != IVAS_ERR_OK ) { - return IVAS_ERR_FAILED_ALLOC; + return error; } if ( hDecoderConfig->output_Fs == 8000 ) @@ -555,12 +554,12 @@ ivas_error IVAS_DEC_EnableVoIP( return IVAS_ERR_INIT_ERROR; } - if ( apa_init( &hIvasDec->hVoIP->hTimeScaler ) != 0 || - apa_set_rate( hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->output_Fs, hDecoderConfig->nchan_out ) != 0 || + if ( apa_init( &hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->nchan_out ) != IVAS_ERR_OK || + apa_set_rate( hIvasDec->hVoIP->hTimeScaler, hDecoderConfig->output_Fs ) != 0 || apa_set_complexity_options( hIvasDec->hVoIP->hTimeScaler, wss, css ) != 0 || apa_set_quality( hIvasDec->hVoIP->hTimeScaler, 1, 4, 4 ) != 0 || - pcmdsp_fifo_create( &hIvasDec->hVoIP->hFifoAfterTimeScaler ) != 0 || - pcmdsp_fifo_init( hIvasDec->hVoIP->hFifoAfterTimeScaler, (uint16_t) ( hDecoderConfig->output_Fs * 4 / FRAMES_PER_SEC ) /* 4 frames */, hDecoderConfig->nchan_out, sizeof( int16_t ) ) != 0 ) + pcmdsp_fifo_create( &hIvasDec->hVoIP->hFifoAfterTimeScaler ) != IVAS_ERR_OK || + pcmdsp_fifo_init( hIvasDec->hVoIP->hFifoAfterTimeScaler, (uint16_t) ( hDecoderConfig->output_Fs * 4 / FRAMES_PER_SEC ) /* 4 frames */, hDecoderConfig->nchan_out, sizeof( int16_t ) ) != IVAS_ERR_OK ) { return IVAS_ERR_INIT_ERROR; } @@ -579,7 +578,7 @@ ivas_error IVAS_DEC_FeedFrame_Serial( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ uint16_t *serial, /* i : buffer containing serial input bitstream. Each bit should be stored as a single uint16_t value */ const uint16_t num_bits, /* i : number of bits in input bitstream */ - const int16_t bfi /* i : bad frame indicator flag */ + int16_t bfi /* i : bad frame indicator flag */ ) { ivas_error error; @@ -597,19 +596,61 @@ ivas_error IVAS_DEC_FeedFrame_Serial( return error; } - hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00; + if ( hIvasDec->hVoIP != NULL && hIvasDec->hVoIP->hCurrentDataUnit != NULL ) + { + DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; + st->ini_frame = 0; + st->prev_use_partial_copy = 0; + hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = hIvasDec->hVoIP->hCurrentDataUnit->dataSize * FRAMES_PER_SEC; + } + else + { + hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = ACELP_8k00; + } } hIvasDec->isInitialized = true; } - if ( !bfi ) + if ( !bfi ) /* TODO(mcjbm): Is this ok for bfi == 2 (partial frame)? Is there enough info to fully configure decoder? */ { hIvasDec->hasBeenFedFirstGoodFrame = true; } + /* Update redundant frame information in EVS (pre- read indices) */ + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && hIvasDec->hVoIP != NULL && hIvasDec->hVoIP->hCurrentDataUnit != NULL ) + { + DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; + st->bit_stream = serial; + + if ( hIvasDec->hVoIP->hCurrentDataUnit->partial_frame || st->prev_use_partial_copy ) + { + st->next_coder_type = hIvasDec->hVoIP->hCurrentDataUnit->nextCoderType; + } + else + { + st->next_coder_type = INACTIVE; + } + + if ( hIvasDec->hVoIP->hCurrentDataUnit->partial_frame == 1 && bfi != 1 ) + { + bfi = 2; + } + } + error = read_indices( hIvasDec->st_ivas, serial, num_bits, &hIvasDec->prev_ft_speech, &hIvasDec->CNG, bfi ); + /* Update redundant frame information in EVS (post- read indices) */ + if ( hIvasDec->mode == IVAS_DEC_MODE_EVS && + hIvasDec->hVoIP != NULL && + hIvasDec->hVoIP->hCurrentDataUnit != NULL && + hIvasDec->hVoIP->hCurrentDataUnit->partial_frame != 0 ) + { + DEC_CORE_HANDLE st = hIvasDec->st_ivas->hSCE[0]->hCoreCoder[0]; + st->codec_mode = MODE2; + st->use_partial_copy = 1; + } + return error; } @@ -623,7 +664,7 @@ ivas_error IVAS_DEC_FeedFrame_Serial( ivas_error IVAS_DEC_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ int16_t *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */ - int16_t *nOutSamples /* o : number of samples written to output buffer */ + int16_t *nOutSamples /* o : number of samples per channel written to output buffer */ ) { Decoder_Struct *st_ivas; @@ -784,15 +825,25 @@ ivas_error IVAS_DEC_GetObjectMetadata( { metadata->azimuth = 0.f; metadata->elevation = 0.f; +#ifdef FIX_379_EXT_METADATA + metadata->radius = 1.f; + metadata->spread = 0.f; + metadata->gainFactor = 1.f; + metadata->yaw = 0.f; + metadata->pitch = 0.f; +#else metadata->radius = 0.f; metadata->spread = 0.f; metadata->gainFactor = 1.f; +#endif } else { metadata->azimuth = hIsmMeta->azimuth; metadata->elevation = hIsmMeta->elevation; - metadata->radius = 0.f; + metadata->radius = hIsmMeta->radius; + metadata->yaw = hIsmMeta->yaw; + metadata->pitch = hIsmMeta->pitch; metadata->spread = 0.f; metadata->gainFactor = 1.f; } @@ -808,8 +859,12 @@ ivas_error IVAS_DEC_GetObjectMetadata( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_GetMasaMetadata( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef FIX_350_MASA_DELAY_COMP + MASA_DECODER_EXT_OUT_META_HANDLE *hMasaExtOutMeta /* o : pointer to handle, which will be set to point to metadata from the most recently decoded frame */ +#else IVAS_MASA_QMETADATA_HANDLE *hMasaMetadata /* o : pointer to handle, which will be set to point to metadata from the most recently decoded frame */ +#endif ) { if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) @@ -822,7 +877,11 @@ ivas_error IVAS_DEC_GetMasaMetadata( return IVAS_ERR_WRONG_MODE; } +#ifdef FIX_350_MASA_DELAY_COMP + *hMasaExtOutMeta = hIvasDec->st_ivas->hMasa->data.extOutMeta; +#else *hMasaMetadata = hIvasDec->st_ivas->hQMetaData; +#endif return IVAS_ERR_OK; } @@ -834,14 +893,15 @@ ivas_error IVAS_DEC_GetMasaMetadata( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_FeedHeadTrackData( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - IVAS_QUATERNION *orientation /* i : head-tracking data */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_QUATERNION *orientation, /* i : head-tracking data, listener orientation */ + IVAS_POSITION *Pos /* i : listener position */ ) { HEAD_TRACK_DATA_HANDLE hHeadTrackData; int16_t i; - if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || orientation == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; } @@ -856,10 +916,16 @@ ivas_error IVAS_DEC_FeedHeadTrackData( /* Move head-tracking data to the decoder handle */ for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) { - hHeadTrackData->Quaternions[i].w = orientation[i].w; - hHeadTrackData->Quaternions[i].x = orientation[i].x; - hHeadTrackData->Quaternions[i].y = orientation[i].y; - hHeadTrackData->Quaternions[i].z = orientation[i].z; + /* check for Euler angle signaling */ + if ( orientation[i].w == -3.0f ) + { + Euler2Quat( deg2rad( orientation[i].x ), deg2rad( orientation[i].y ), deg2rad( orientation[i].z ), &orientation[i] ); + } + + ivas_orient_trk_Process( hHeadTrackData->OrientationTracker, orientation[i], FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hHeadTrackData->Quaternions[i] ); + hHeadTrackData->Pos[i].x = Pos[i].x; + hHeadTrackData->Pos[i].y = Pos[i].y; + hHeadTrackData->Pos[i].z = Pos[i].z; } hIvasDec->st_ivas->hHeadTrackData->num_quaternions = 0; @@ -867,6 +933,58 @@ ivas_error IVAS_DEC_FeedHeadTrackData( return IVAS_ERR_OK; } +/*---------------------------------------------------------------------* + * IVAS_DEC_FeedRefRotData( ) + * + * Feed the decoder with the reference rotation + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_FeedRefRotData( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_QUATERNION rotation /* i : reference rotation data */ +) +{ + ivas_orient_trk_state_t *pOtr; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHeadTrackData == NULL || hIvasDec->st_ivas->hHeadTrackData->OrientationTracker == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + pOtr = hIvasDec->st_ivas->hHeadTrackData->OrientationTracker; + + pOtr->refRot.w = rotation.w; + pOtr->refRot.x = rotation.x; + pOtr->refRot.z = rotation.z; + pOtr->refRot.y = rotation.y; + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_FeedRefVectorData( ) + * + * Feed the decoder with a reference vector spanning from listenerPos + * to refPos. Only available in OTR_TRACKING_REF_POS and + * OTR_TRACKING_REF_POS_LEV modes. + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_FeedRefVectorData( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_VECTOR3 listenerPos, /* i : Listener position */ + const IVAS_VECTOR3 refPos /* i : Reference position */ +) +{ + ivas_orient_trk_state_t *pOtr; + + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHeadTrackData == NULL || hIvasDec->st_ivas->hHeadTrackData->OrientationTracker == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + pOtr = hIvasDec->st_ivas->hHeadTrackData->OrientationTracker; + return ivas_orient_trk_SetReferenceVector( pOtr, listenerPos, refPos ); +} /*---------------------------------------------------------------------* * IVAS_DEC_FeedCustomLsData( ) @@ -944,6 +1062,69 @@ ivas_error IVAS_DEC_GetHrtfHandle( } +/*---------------------------------------------------------------------* + * IVAS_DEC_GetHrtfCRendHandle( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetHrtfCRendHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */ +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hSetOfHRTF == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + *hSetOfHRTF = hIvasDec->st_ivas->hSetOfHRTF; + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetHrtfFastConvHandle( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetHrtfFastConvHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/oL IVAS decoder handle */ + IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfFastConv == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + *hHrtfFastConv = hIvasDec->st_ivas->hHrtfFastConv; + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetHrtfParamBinHandle( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetHrtfParamBinHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */ +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfParambin == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + *hHrtfParambin = hIvasDec->st_ivas->hHrtfParambin; + + return IVAS_ERR_OK; +} + /*---------------------------------------------------------------------* * IVAS_DEC_GetRenderConfig( ) * @@ -964,7 +1145,18 @@ ivas_error IVAS_DEC_GetRenderConfig( hRCin = hIvasDec->st_ivas->hRenderConfig; #ifdef DEBUGGING - hRCout->renderer_type_override = hRCin->renderer_type_override; + switch ( hRCin->renderer_type_override ) + { + case RENDER_TYPE_OVERRIDE_CREND: + hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_CREND; + break; + case RENDER_TYPE_OVERRIDE_FASTCONV: + hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_FASTCONV; + break; + default: + hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; + break; + } #endif hRCout->room_acoustics.override = hRCin->roomAcoustics.override; hRCout->room_acoustics.use_brir = hRCin->roomAcoustics.use_brir; @@ -976,6 +1168,7 @@ ivas_error IVAS_DEC_GetRenderConfig( mvr2r( hRCin->roomAcoustics.pFc_input, hRCout->room_acoustics.pFc_input, CLDFB_NO_CHANNELS_MAX ); mvr2r( hRCin->roomAcoustics.pAcoustic_rt60, hRCout->room_acoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); mvr2r( hRCin->roomAcoustics.pAcoustic_dsr, hRCout->room_acoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); + mvr2r( hRCin->directivity, hRCout->directivity, 3 ); return IVAS_ERR_OK; } @@ -1020,6 +1213,7 @@ ivas_error IVAS_DEC_FeedRenderConfig( mvr2r( renderConfig.room_acoustics.pFc_input, hRenderConfig->roomAcoustics.pFc_input, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.room_acoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.room_acoustics.pAcoustic_dsr, hRenderConfig->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); + mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 ); return IVAS_ERR_OK; } @@ -1045,10 +1239,18 @@ ivas_error IVAS_DEC_GetDelay( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } + if ( !hIvasDec->hasDecodedFirstGoodFrame ) + { + /* Delay depends on IVAS format, which is unknown until first frame has been decoded */ + return IVAS_ERR_WAITING_FOR_BITSTREAM; + } + st_ivas = hIvasDec->st_ivas; hDecoderConfig = st_ivas->hDecoderConfig; - *nSamples = NS2SA( hDecoderConfig->output_Fs, (int32_t) ( get_delay( DEC, hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->cldfbAnaDec[0], st_ivas->renderer_type, st_ivas->binaural_latency_ns ) + 0.5f ) ); + nSamples[1] = NS2SA( hDecoderConfig->output_Fs, get_delay( DEC, hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->cldfbAnaDec[0] ) ); + nSamples[2] = (int16_t) roundf( (float) st_ivas->binaural_latency_ns * hDecoderConfig->output_Fs / 1000000000.f ); + nSamples[0] = nSamples[1] + nSamples[2]; *timeScale = hDecoderConfig->output_Fs; @@ -1124,7 +1326,7 @@ static bool isSidFrame( { return true; /* EVS SID */ } - else if ( size == IVAS_SID_4k4 / FRAMES_PER_SEC ) + else if ( size == IVAS_SID_5k2 / FRAMES_PER_SEC ) { return true; /* IVAS SID */ } @@ -1132,11 +1334,39 @@ static bool isSidFrame( return false; } +static void bsCompactToSerial( const uint8_t *compact, uint16_t *serial, uint16_t num_bits ) +{ +/* Bitstream conversion is not counted towards complexity and memory usage */ +#define WMC_TOOL_SKIP + uint32_t i; + uint8_t byte = 0; + const uint8_t mask = 0x80; + + for ( i = 0; i < num_bits; ++i ) + { + if ( i % 8 == 0 ) + { + byte = compact[i / 8]; + } + + serial[i] = ( byte & mask ) >> 7; + + byte <<= 1; + } + + /* Add 4 padding bytes required by core coder */ + for ( i = 0; i < 4 * 8; ++i ) + { + serial[num_bits + i] = 0; + } +#undef WMC_TOOL_SKIP +} + /*---------------------------------------------------------------------* * IVAS_DEC_VoIP_FeedFrame( ) * - * + * Feed RTP packet into internal jitter buffer *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_VoIP_FeedFrame( @@ -1146,8 +1376,6 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( const uint16_t rtpSequenceNumber, /* i : RTP sequence number (16 bits) */ const uint32_t rtpTimeStamp, /* i : RTP timestamp (32 bits) */ const uint32_t rcvTime_ms, /* i : receive time of the RTP packet in milliseconds */ - const bool isAMRWB_IOmode, /* i : AMRWB flag */ - const uint16_t frameTypeIndex, /* i : core mode for frame */ const bool qBit /* i : Q bit for AMR-WB IO */ ) { @@ -1179,8 +1407,6 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( dataUnit->timeStamp = rtpTimeStamp; dataUnit->partial_frame = 0; dataUnit->partialCopyOffset = partialCopyOffset; - dataUnit->isAMRWB_IOmode = isAMRWB_IOmode; - dataUnit->frameTypeIndex = frameTypeIndex; dataUnit->qBit = qBit; /* add the frame to the JBM */ @@ -1204,8 +1430,6 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( dataUnit->timeStamp = rtpTimeStamp - partialCopyOffset * dataUnit->duration; dataUnit->partial_frame = 1; dataUnit->partialCopyOffset = partialCopyOffset; - dataUnit->isAMRWB_IOmode = isAMRWB_IOmode; - dataUnit->frameTypeIndex = frameTypeIndex; dataUnit->qBit = qBit; /* add the frame to the JBM */ @@ -1228,22 +1452,23 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( ivas_error IVAS_DEC_VoIP_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - int16_t *nOutSamples, /* o : number of samples written to output buffer */ + uint16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ int16_t *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */ - const uint32_t pcmBufSize, /* i : size of the PCM output buffer */ const uint32_t systemTimestamp_ms /* i : current system timestamp */ +#ifdef SUPPORT_JBM_TRACEFILE + , + JbmTraceFileWriterFn jbmWriterFn, + void *jbmWriter +#endif ) { Decoder_Struct *st_ivas; DECODER_CONFIG_HANDLE hDecoderConfig; - Decoder_State *st; IVAS_DEC_VOIP *hVoIP; uint32_t extBufferedTime_ms, scale, maxScaling; uint16_t nTimeScalerOutSamples; JB4_DATAUNIT_HANDLE dataUnit; - uint16_t bit_stream[MAX_BITS_PER_FRAME + 4 * 8]; int16_t nOutSamplesElse; - uint16_t soundCardFrameSize; uint16_t extBufferedSamples; int16_t timeScalingDone; int16_t result; @@ -1253,20 +1478,19 @@ ivas_error IVAS_DEC_VoIP_GetSamples( st_ivas = hIvasDec->st_ivas; hDecoderConfig = st_ivas->hDecoderConfig; - st = st_ivas->hSCE[0]->hCoreCoder[0]; hVoIP = hIvasDec->hVoIP; - soundCardFrameSize = hVoIP->nSamplesFrame; timeScalingDone = 0; - assert( hVoIP->nSamplesFrame <= pcmBufSize ); - assert( hVoIP->nSamplesFrame <= APA_BUF ); - - st_ivas->hSCE[0]->hCoreCoder[0]->bit_stream = bit_stream; + /* TODO(mcjbm): ringbuffer capacity should be configurable by user */ + if ( nSamplesPerChannel > hVoIP->hFifoAfterTimeScaler->capacity || nSamplesPerChannel == 0 ) + { + return IVAS_ERR_WRONG_PARAMS; + } /* make sure that the FIFO after decoder/scaler contains at least one sound card frame (i.e. 20ms) */ - while ( pcmdsp_fifo_nReadableSamples( hVoIP->hFifoAfterTimeScaler ) < soundCardFrameSize ) + while ( pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ) < nSamplesPerChannel ) { - extBufferedSamples = pcmdsp_fifo_nReadableSamples( hVoIP->hFifoAfterTimeScaler ); + extBufferedSamples = pcmdsp_fifo_nReadableSamplesPerChannel( hVoIP->hFifoAfterTimeScaler ); extBufferedTime_ms = extBufferedSamples * 1000 / hDecoderConfig->output_Fs; dataUnit = NULL; /* pop one access unit from the jitter buffer */ @@ -1293,52 +1517,27 @@ ivas_error IVAS_DEC_VoIP_GetSamples( /* copy bitstream into decoder state */ if ( dataUnit ) { - if ( st->codec_mode != 0 ) - { - read_indices_from_djb( st, dataUnit->data, &hIvasDec->CNG, dataUnit->dataSize, - dataUnit->isAMRWB_IOmode, dataUnit->frameTypeIndex, dataUnit->qBit, hIvasDec->bitstreamformat, hIvasDec->amrwb_rfc4867_flag, - ( dataUnit->partial_frame == TRUE ) ? 1 : 0, dataUnit->nextCoderType ); - - if ( dataUnit->partial_frame != 0 ) - { - st->codec_mode = MODE2; - st->use_partial_copy = 1; - } - } - else /* initialize decoder with first received frame */ - { - /* initialize, since this is needed within read_indices_from_djb, to correctly set st->last_codec_mode */ - st->ini_frame = 0; - st->prev_use_partial_copy = 0; - st_ivas->hDecoderConfig->ivas_total_brate = dataUnit->dataSize * FRAMES_PER_SEC; + hIvasDec->hVoIP->hCurrentDataUnit = dataUnit; - read_indices_from_djb( st, dataUnit->data, &hIvasDec->CNG, dataUnit->dataSize, - dataUnit->isAMRWB_IOmode, dataUnit->frameTypeIndex, dataUnit->qBit, hIvasDec->bitstreamformat, hIvasDec->amrwb_rfc4867_flag, - 0, 0 ); - } + bsCompactToSerial( dataUnit->data, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize ); + IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, dataUnit->dataSize, 0 ); } - else if ( st->codec_mode != 0 ) + else if ( hIvasDec->hasDecodedFirstGoodFrame ) { - read_indices_from_djb( st, NULL, &hIvasDec->CNG, 0, - 0, 0, 0, hIvasDec->bitstreamformat, 0, - 0, 0 ); + /* Decoder has been initialized with first good frame - do PLC */ + IVAS_DEC_FeedFrame_Serial( hIvasDec, hIvasDec->hVoIP->bs_conversion_buf, 0, 1 ); } /* decode */ - if ( st->codec_mode == 0 ) + if ( !hIvasDec->hasBeenFedFirstGoodFrame ) { - /* codec mode to use not known yet */ - set_s( pcmBuf, 0, hVoIP->nSamplesFrame ); + /* codec mode to use not known yet - simply output silence */ + set_s( hVoIP->apaExecBuffer, 0, hVoIP->nSamplesFrame ); /* TODO(mcjbm): Could be optimized: just write directly to output buffer */ } else { - if ( hIvasDec->mode == IVAS_DEC_MODE_EVS ) - { - /* Update total bitrate after reading indices */ - hIvasDec->st_ivas->hDecoderConfig->ivas_total_brate = st->total_brate; - } - if ( ( error = IVAS_DEC_GetSamples( hIvasDec, pcmBuf, &nOutSamplesElse ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, hVoIP->apaExecBuffer, &nOutSamplesElse ) ) != IVAS_ERR_OK ) { return error; } @@ -1373,29 +1572,36 @@ ivas_error IVAS_DEC_VoIP_GetSamples( { return IVAS_ERR_UNKNOWN; } - result = apa_exec( hVoIP->hTimeScaler, pcmBuf, (uint16_t) ( hVoIP->nSamplesFrame * hDecoderConfig->nchan_out ), (uint16_t) maxScaling, pcmBuf, &nTimeScalerOutSamples ); + result = apa_exec( hVoIP->hTimeScaler, hVoIP->apaExecBuffer, hVoIP->nSamplesFrame, (uint16_t) maxScaling, hVoIP->apaExecBuffer, &nTimeScalerOutSamples ); if ( result != 0 ) { return IVAS_ERR_UNKNOWN; } - assert( nTimeScalerOutSamples <= pcmBufSize ); assert( nTimeScalerOutSamples <= APA_BUF ); /* append scaled samples to FIFO */ - if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) pcmBuf, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) + if ( pcmdsp_fifo_write( hVoIP->hFifoAfterTimeScaler, (uint8_t *) hVoIP->apaExecBuffer, (uint16_t) ( nTimeScalerOutSamples / hDecoderConfig->nchan_out ) ) != 0 ) { return IVAS_ERR_UNKNOWN; } #ifdef SUPPORT_JBM_TRACEFILE - /* store JBM trace data entry */ - store_JbmData( hVoIP, dataUnit, systemTimestamp_ms, extBufferedSamples, hDecoderConfig->output_Fs ); + /* jbmWriterFn and jbmWriter may be NULL if tracefile writing was not requested on CLI */ + if ( jbmWriterFn != NULL && jbmWriter != NULL ) + { + /* write JBM trace data entry */ + store_JbmData( hVoIP, dataUnit, systemTimestamp_ms, extBufferedSamples, hDecoderConfig->output_Fs ); + if ( ( jbmWriterFn( &hVoIP->JbmTraceData, jbmWriter ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing JBM Trace data to file\n" ); + return IVAS_ERR_UNKNOWN; + } + } #endif } - /* fetch one frame for the sound card from FIFO */ - *nOutSamples = (int16_t) soundCardFrameSize; - if ( pcmdsp_fifo_read( hVoIP->hFifoAfterTimeScaler, *nOutSamples, (uint8_t *) pcmBuf ) != 0 ) + /* fetch a user-specified number of samples from FIFO */ + if ( pcmdsp_fifo_read( hVoIP->hFifoAfterTimeScaler, nSamplesPerChannel, (uint8_t *) pcmBuf ) != 0 ) { return IVAS_ERR_UNKNOWN; } @@ -1457,6 +1663,21 @@ static void IVAS_DEC_Close_VoIP( pcmdsp_fifo_destroy( &hVoIP->hFifoAfterTimeScaler ); + if ( hVoIP->apaExecBuffer != NULL ) + { + free( hVoIP->apaExecBuffer ); + } + + if ( hVoIP->bs_conversion_buf != NULL ) + { +#define WMC_TOOL_SKIP + /* Bitstream conversion is not counted towards complexity and memory usage */ + free( hVoIP->bs_conversion_buf ); +#undef WMC_TOOL_SKIP + } + + free( hVoIP ); + return; } @@ -1484,31 +1705,18 @@ static void store_JbmData( JbmTraceData = &hVoIP->JbmTraceData; - /* the first sample of the decoded/concealed frame will be played after the samples in the ring buffer */ - JbmTraceData->playTime = systemTimestamp_ms + extBufferedSamples * 1000.0 / output_Fs; - - /* rtpSeqNo;rtpTs;rcvTime;playTime;active\n */ - if ( dataUnit ) + JbmTraceData->systemTimestamp_ms = systemTimestamp_ms; + JbmTraceData->extBufferedSamples = extBufferedSamples; + JbmTraceData->lastDecodedWasActive = hVoIP->lastDecodedWasActive; + JbmTraceData->output_Fs = output_Fs; + JbmTraceData->dataUnit_flag = dataUnit != NULL; + if ( dataUnit != NULL ) { JbmTraceData->sequenceNumber = dataUnit->sequenceNumber; - JbmTraceData->partialCopyOffset = dataUnit->partialCopyOffset; JbmTraceData->timeStamp = dataUnit->timeStamp; JbmTraceData->rcvTime = dataUnit->rcvTime; - JbmTraceData->lastDecodedWasActive = hVoIP->lastDecodedWasActive; - - JbmTraceData->dataUnit_flag = 1; - if ( dataUnit->partial_frame == 1 ) - { - JbmTraceData->partial_frame_flag = 1; - } - else - { - JbmTraceData->partial_frame_flag = 0; - } - } - else - { - JbmTraceData->dataUnit_flag = 0; + JbmTraceData->partial_frame = dataUnit->partial_frame; + JbmTraceData->partialCopyOffset = dataUnit->partialCopyOffset; } return; @@ -1578,10 +1786,19 @@ const char *IVAS_DEC_GetErrorMessage( return "invalid format of input bitstream"; case IVAS_ERR_INVALID_INDEX: return "invalid index"; + case IVAS_ERR_INTERNAL: + case IVAS_ERR_INTERNAL_FATAL: + return "internal error"; + case IVAS_ERR_RECONFIGURE_NOT_SUPPORTED: + return "reconfigure not supported"; + case IVAS_ERR_UNEXPECTED_NULL_POINTER: + return "unexpected NULL pointer"; #ifdef DEBUGGING case IVAS_ERR_INVALID_FORCE_MODE: return "invalid force mode"; #endif + case IVAS_ERR_FAILED_FILE_READ: + return "could not read from file"; case IVAS_ERR_NOT_IMPLEMENTED: return "not implemented"; case IVAS_ERR_UNKNOWN: @@ -1748,7 +1965,7 @@ static ivas_error printConfigInfo_dec( } else if ( st_ivas->ivas_format == SBA_FORMAT ) { - fprintf( stdout, "Input configuration: SBA - %d transport channel(s) %s\n", st_ivas->nchan_transport, st_ivas->sba_planar ? "(Planar)" : "" ); + fprintf( stdout, "Input configuration: Scene Based Audio, Ambisonic order %i%s, %d transport channel(s)\n", st_ivas->sba_order, st_ivas->sba_planar ? " (Planar)" : "", st_ivas->nchan_transport ); } else if ( st_ivas->ivas_format == MASA_FORMAT ) { @@ -1767,16 +1984,44 @@ static ivas_error printConfigInfo_dec( get_channel_config( st_ivas->hDecoderConfig->output_config, &config_str[0] ); fprintf( stdout, "Output configuration: %s\n", config_str ); + if ( st_ivas->hDecoderConfig->Opt_HRTF_binary ) + { + fprintf( stdout, "HRIR/BRIR file: ON\n" ); + } + + if ( st_ivas->hDecoderConfig->Opt_RendConfigCustom ) + { + fprintf( stdout, "Renderer config. file: ON\n" ); + } + if ( st_ivas->hDecoderConfig->Opt_Headrotation ) { fprintf( stdout, "Head rotation: ON\n" ); } + + if ( st_ivas->hDecoderConfig->orientation_tracking != IVAS_ORIENT_TRK_NONE ) + { + switch ( st_ivas->hDecoderConfig->orientation_tracking ) + { + case IVAS_ORIENT_TRK_AVG: + fprintf( stdout, "Orientation tracking: AVG\n" ); + break; + case IVAS_ORIENT_TRK_REF: + fprintf( stdout, "Orientation tracking: REF\n" ); + break; + case IVAS_ORIENT_TRK_REF_VEC: + fprintf( stdout, "Orientation tracking: REF_VEC\n" ); + break; + case IVAS_ORIENT_TRK_REF_VEC_LEV: + fprintf( stdout, "Orientation tracking: REF_VEC_LEV\n" ); + break; + } + } } return IVAS_ERR_OK; } - /*---------------------------------------------------------------------* * IVAS_DEC_PrintConfig( ) * @@ -1795,6 +2040,7 @@ void IVAS_DEC_PrintConfig( #ifdef DEBUGGING +#define WMC_TOOL_SKIP void IVAS_DEC_PrintConfigWithBitstream( IVAS_DEC_HANDLE hIvasDec, const bool quietModeEnabled, @@ -1806,7 +2052,7 @@ void IVAS_DEC_PrintConfigWithBitstream( /* Create a copy of decoder struct that will be modified by preview_indices(), * leaving the original decoder struct unchanged. The additional memory used here * should not be counted towards memory footprint of the decoder. */ - st_ivas = dynamic_malloc( sizeof( Decoder_Struct ) ); + st_ivas = malloc( sizeof( Decoder_Struct ) ); memcpy( st_ivas, hIvasDec->st_ivas, sizeof( Decoder_Struct ) ); preview_indices( st_ivas, bit_stream, num_bits ); @@ -1814,12 +2060,46 @@ void IVAS_DEC_PrintConfigWithBitstream( /* Print config from modified decoder struct */ printConfigInfo_dec( st_ivas, hIvasDec->bitstreamformat, hIvasDec->Opt_VOIP, quietModeEnabled ); - dynamic_free( st_ivas ); + free( st_ivas ); return; } + +void IVAS_DEC_PrintConfigWithVoipBitstream( + IVAS_DEC_HANDLE hIvasDec, + const bool quietModeEnabled, + uint8_t *au, + const uint16_t auSizeBits ) +{ + Decoder_Struct *st_ivas; + uint16_t bit_stream[MAX_BITS_PER_FRAME + 4 * 8]; + + /* Create a copy of decoder struct that will be modified by preview_indices(), + * leaving the original decoder struct unchanged. The additional memory used here + * should not be counted towards memory footprint of the decoder. */ + st_ivas = malloc( sizeof( Decoder_Struct ) ); + memcpy( st_ivas, hIvasDec->st_ivas, sizeof( Decoder_Struct ) ); + + bsCompactToSerial( au, bit_stream, auSizeBits ); + preview_indices( st_ivas, bit_stream, auSizeBits ); + + /* Print config from modified decoder struct */ + printConfigInfo_dec( st_ivas, hIvasDec->bitstreamformat, hIvasDec->Opt_VOIP, quietModeEnabled ); + + free( st_ivas ); + + return; +} +#undef WMC_TOOL_SKIP #endif + +/*---------------------------------------------------------------------* + * IVAS_DEC_PrintDisclaimer( ) + * + * Print IVAS disclaimer to console + *---------------------------------------------------------------------*/ + void IVAS_DEC_PrintDisclaimer( void ) { print_disclaimer( stderr ); @@ -2020,6 +2300,42 @@ ivas_error IVAS_DEC_SetForcedRendMode( return IVAS_ERR_OK; } + +#ifdef DEBUG_SBA_AUDIO_DUMP +/*---------------------------------------------------------------------* + * IVAS_DEC_GetSbaDebugParams( ) + * + * Returns SBA debug parameters + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetSbaDebugParams( + const IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + int16_t *numOutputChannels, + int16_t *numTransportChannels, + int16_t *pca_ingest_channels ) +{ + if ( hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( hIvasDec->st_ivas->ivas_format != SBA_FORMAT || hIvasDec->st_ivas->hSpar == NULL ) + { + *numOutputChannels = 1; + *numTransportChannels = 1; + *pca_ingest_channels = 1; + } + else + { + *numOutputChannels = hIvasDec->st_ivas->hSpar->numOutChannels; + *numTransportChannels = hIvasDec->st_ivas->nchan_transport; + *pca_ingest_channels = hIvasDec->st_ivas->hSpar->pca_ingest_channels; + } + + return IVAS_ERR_OK; +} +#endif /* DEBUG_SBA_AUDIO_DUMP */ + #endif /* DEBUGGING */ static ivas_error input_format_API_to_internal( diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index b4221c142cbc2d02ec776a6ff6a76566c1e56152..e1e5bfe9f47fbcb676cf2c8c79ece0d5c2a39398 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,9 +34,7 @@ #define LIB_DEC_H #include "common_api_types.h" -#include "ivas_error.h" #include -#include /*---------------------------------------------------------------------* @@ -103,6 +101,11 @@ typedef enum _IVAS_DEC_BS_FORMAT typedef struct IVAS_DEC *IVAS_DEC_HANDLE; +#ifdef SUPPORT_JBM_TRACEFILE +/* Callback function for JBM tracefile writing */ +typedef ivas_error ( *JbmTraceFileWriterFn )( const void *data, void *writer ); +#endif + /* clang-format off */ /*---------------------------------------------------------------------* @@ -126,11 +129,8 @@ ivas_error IVAS_DEC_Configure( const IVAS_DEC_AUDIO_CONFIG outputFormat, /* i : output format */ const int16_t customLsOutputEnabled, /* i : enable custom loudspeaker setup handle */ const int16_t hrtfReaderEnabled, /* i : enable HRTF binary file input */ - const int16_t enableHeadRotation /* i : enable head rotation for binaural output */ -#ifdef DEBUGGING - , - const int16_t forceSubframeBinauralization /* i : enable subframe binauralization */ -#endif + const int16_t enableHeadRotation, /* i : enable head rotation for binaural output */ + const int16_t renderConfigEnabled /* i : enable Renderer config. file for binaural output */ ); void IVAS_DEC_Close( @@ -145,14 +145,14 @@ ivas_error IVAS_DEC_FeedFrame_Serial( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ uint16_t *serial, /* i : buffer containing serial input bitstream. Each bit should be stored as a single uint16_t value */ const uint16_t num_bits, /* i : number of bits in input bitstream */ - const int16_t bfi /* i : bad frame indicator flag */ + int16_t bfi /* i : bad frame indicator flag */ ); /*! r: decoder error code */ ivas_error IVAS_DEC_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ int16_t *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */ - int16_t *nOutSamples /* o : number of samples written to output buffer */ + int16_t *nOutSamples /* o : number of samples per channel written to output buffer */ ); /*! r: error code */ @@ -165,14 +165,31 @@ ivas_error IVAS_DEC_GetObjectMetadata( /*! r: error code */ ivas_error IVAS_DEC_GetMasaMetadata( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - IVAS_MASA_QMETADATA_HANDLE *hMasaMetadata /* o : pointer to handle, which will be set to point to metadata from the most recently decoded frame */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ +#ifdef FIX_350_MASA_DELAY_COMP + MASA_DECODER_EXT_OUT_META_HANDLE *hMasaExtOutMeta /* o : pointer to handle, which will be set to point to metadata from the most recently decoded frame */ +#else + IVAS_MASA_QMETADATA_HANDLE *hMasaMetadata /* o : pointer to handle, which will be set to point to metadata from the most recently decoded frame */ +#endif ); /*! r: error code */ ivas_error IVAS_DEC_FeedHeadTrackData( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - IVAS_QUATERNION *orientation /* i : head-tracking data */ + IVAS_QUATERNION *orientation, /* i : head-tracking data */ + IVAS_POSITION *Pos /* i : listener position */ +); + +/*! r: error code */ +ivas_error IVAS_DEC_FeedRefRotData( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_QUATERNION rotation /* i : reference rotation data */ +); +/*! r: error code */ +ivas_error IVAS_DEC_FeedRefVectorData( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const IVAS_VECTOR3 listenerPos, /* i : Listener position */ + const IVAS_VECTOR3 refPos /* i : Reference position */ ); /*! r: error code */ @@ -183,18 +200,19 @@ ivas_error IVAS_DEC_VoIP_FeedFrame( const uint16_t rtpSequenceNumber, /* i : RTP sequence number (16 bits) */ const uint32_t rtpTimeStamp, /* i : RTP timestamp (32 bits) */ const uint32_t rcvTime_ms, /* i : receive time of the RTP packet in milliseconds */ - const bool isAMRWB_IOmode, /* i : AMRWB flag */ - const uint16_t frameTypeIndex, /* i : core mode for frame */ const bool qBit /* i : Q bit for AMR-WB IO */ ); /*! r: error code */ ivas_error IVAS_DEC_VoIP_GetSamples( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - int16_t *nOutSamples, /* o : number of samples written to output buffer */ + uint16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ int16_t *pcmBuf, /* i/o: buffer for decoded PCM output. The memory must already be allocated and be able to hold the expected number of output samples, based on frame size and number of output channels */ - const uint32_t pcmBufSize, /* i : size of the PCM output buffer */ const uint32_t systemTimestamp_ms /* i : current system timestamp */ +#ifdef SUPPORT_JBM_TRACEFILE + , JbmTraceFileWriterFn jbmWriterFn, + void* jbmWriter +#endif ); /* Setter functions - apply changes to decoder configuration */ @@ -206,17 +224,6 @@ ivas_error IVAS_DEC_EnableVoIP( const IVAS_DEC_INPUT_FORMAT inputFormat /* i : format of the input bitstream */ ); -/*! r: error code */ -ivas_error IVAS_DEC_SetHeadrotation( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const float w, /* i : w-coordinate of head rotation quaternion */ - const float x, /* i : x-coordinate of head rotation quaternion */ - const float y, /* i : y-coordinate of head rotation quaternion */ - const float z, /* i : z-coordinate of head rotation quaternion */ - const uint16_t i /* i : subframe index within current frame */ -); - - #ifdef DEBUGGING bool IVAS_DEC_GetBerDetectFlag( IVAS_DEC_HANDLE hIvasDec /* i : IVAS decoder handle */ @@ -235,6 +242,15 @@ ivas_error IVAS_DEC_SetForcedRendMode( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ const IVAS_DEC_FORCED_REND_MODE forcedRendMode /* i : forced renderer mode */ ); + +#ifdef DEBUG_SBA_AUDIO_DUMP +ivas_error IVAS_DEC_GetSbaDebugParams( + const IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + int16_t *numOutputChannels, + int16_t *numTransportChannels, + int16_t *pca_ingest_channels +); +#endif #endif /* Getter functions - retrieve information from a decoder through a handle */ @@ -269,6 +285,22 @@ ivas_error IVAS_DEC_GetHrtfHandle( IVAS_DEC_HRTF_HANDLE *hHrtfTD /* o : HRTF handle */ ); +/*! r: error code */ +ivas_error IVAS_DEC_GetHrtfCRendHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */ +); + +ivas_error IVAS_DEC_GetHrtfFastConvHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/oL IVAS decoder handle */ + IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ +); + +ivas_error IVAS_DEC_GetHrtfParamBinHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */ +); + /*! r: error code*/ ivas_error IVAS_DEC_GetRenderConfig( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ @@ -325,7 +357,6 @@ const char *IVAS_DEC_GetErrorMessage( ivas_error error /* i : decoder error code enum */ ); - void IVAS_DEC_PrintConfig( const IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ const bool quietModeEnabled, /* i : quiet mode flag: if true, reduces the amount of config info printed */ @@ -339,6 +370,13 @@ void IVAS_DEC_PrintConfigWithBitstream( uint16_t bit_stream[], /* i : bitstream buffer */ const int16_t num_bits /* i : number of bits in bitstream */ ); + +void IVAS_DEC_PrintConfigWithVoipBitstream( + IVAS_DEC_HANDLE hIvasDec, /* i : IVAS decoder handle */ + const bool quietModeEnabled, /* i : quiet mode flag: if true, reduces the amount of config info printed */ + uint8_t *au, /* i : buffer containing input access unit */ + const uint16_t auSizeBits /* i : size of the access unit in bits */ +); #endif void IVAS_DEC_PrintDisclaimer( diff --git a/lib_dec/lp_exc_d.c b/lib_dec/lp_exc_d.c index 7036638de00075fd723a58502fac1a68f6d6d1e8..c436edcf133f5f4b6232c69700c350fc30d9f1f4 100644 --- a/lib_dec/lp_exc_d.c +++ b/lib_dec/lp_exc_d.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * lp_filt_exc_dec() @@ -55,7 +55,7 @@ void lp_filt_exc_dec( const int16_t i_subfr, /* i : subframe index */ const int16_t L_subfr, /* i : subframe size */ const int16_t L_frame, /* i : frame size */ - int16_t lp_flag, /* i : operation mode signalling */ + int16_t lp_flag, /* i : operation mode signaling */ float *exc /* i/o: pointer to the excitation signal frame */ ) { diff --git a/lib_dec/lsf_dec.c b/lib_dec/lsf_dec.c index ffa5e91e2c6fdd8c0a50ad5cece67b3e848ae8e3..e29cc480a22433b3e5b480d5eeb4e661f2728734 100644 --- a/lib_dec/lsf_dec.c +++ b/lib_dec/lsf_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -47,7 +47,7 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* diff --git a/lib_dec/lsf_msvq_ma_dec.c b/lib_dec/lsf_msvq_ma_dec.c index 1fe895b70617b90d5eccf6fd6e81a5a5fff3ff26..2fa1f3573b0a432fe062ffce9c45b8358e721b77 100644 --- a/lib_dec/lsf_msvq_ma_dec.c +++ b/lib_dec/lsf_msvq_ma_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_com.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * lsf_msvq_ma_decprm() diff --git a/lib_dec/nelp_dec.c b/lib_dec/nelp_dec.c index 1814031fb2d2c4dbac88c63acc8958beba2f7f57..67d8fb5f8bda758ff4a2a213768eefb6704aae18 100644 --- a/lib_dec/nelp_dec.c +++ b/lib_dec/nelp_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * nelp_decoder() diff --git a/lib_dec/peak_vq_dec.c b/lib_dec/peak_vq_dec.c index 45897b77b30b2d0c8c8d3cd70a6b8a6b3881ac12..df238a057f24507e98dffe81769b8914e2468f41 100644 --- a/lib_dec/peak_vq_dec.c +++ b/lib_dec/peak_vq_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------* diff --git a/lib_dec/pit_dec.c b/lib_dec/pit_dec.c index 9f2ba3bcad25f0b150532749a6a4fabc65b4408e..c569e6609780edd126e0baf65619cbafb54c2ace 100644 --- a/lib_dec/pit_dec.c +++ b/lib_dec/pit_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------* * pit_decode() diff --git a/lib_dec/pitch_extr.c b/lib_dec/pitch_extr.c index d90f06af7a729af64630943e0c7baa33a4fd4bab..a0370946bde5b9b0c429e73adff6115da5ced67d 100644 --- a/lib_dec/pitch_extr.c +++ b/lib_dec/pitch_extr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "cnst.h" #include "prot.h" #include "basop_util.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* @@ -151,7 +151,7 @@ void pitch_pred_linear_fit( ml_fx[i] = (int32_t) ( ml[i] / pow( 2.f, -31 + 15 ) ); /* Q16 */ } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP FOR( i = 0; i < lcor; i++ ) { pg_fx[i] = mult( mult( pg_fx[i], pg_fx[i] ), timeWeight[i] ); /*Q12 'til pg[lcor-1], Q14 'til pg[8]*/ @@ -286,7 +286,7 @@ void pitch_pred_linear_fit( pita = L_shl( L_deposit_l( a1 ), add( add( sum0_q, 16 - 10 + 1 ), sub( tmpa, a_e ) ) ) /*Q16*/; pitb = L_shl_r( L_mult( b1 /*Q15*/, add( no_subfr_pred, nb_subfr ) /*Q0*/ ), add( add( sum0_q, 16 - 12 ), sub( tmpb, b_e ) ) ); pit = L_add( pita, pitb ); /*Q16*/ -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /* convert pitch back to float precision */ T0 = (float) ( pit * pow( 2.f, -31 + 15 ) ); diff --git a/lib_dec/post_dec.c b/lib_dec/post_dec.c index 0d7bd7e7c7b284efa521f5c42686d4917e3abd4d..5bc31d56eeb2165396b3a01d02beb9a6528b686c 100644 --- a/lib_dec/post_dec.c +++ b/lib_dec/post_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Function prototypes diff --git a/lib_dec/ppp_dec.c b/lib_dec/ppp_dec.c index 24ad0146a0f3ef1f7819d3fbccb2c77935de3657..f9e97edcaaa35fb7a10eec86aab93eb0f4b569bf 100644 --- a/lib_dec/ppp_dec.c +++ b/lib_dec/ppp_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -177,7 +177,7 @@ ivas_error ppp_quarter_decoder( tmp = (float) get_next_indice( st, 3 ); DTFS_phaseShift( CURRCW_Q_DTFS, (float) ( PI2 * ( tmp - 3 ) / CURRCW_Q_DTFS->lag ) ); - count_free( PREVDTFS ); + free( PREVDTFS ); return error; } diff --git a/lib_dec/pvq_core_dec.c b/lib_dec/pvq_core_dec.c index 0ef00c6ae342e1345c541f2c888899b63afe5ea1..115d53ac5786b18c662c94de338ae237b605b8ec 100644 --- a/lib_dec/pvq_core_dec.c +++ b/lib_dec/pvq_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "prot.h" #include "stl.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local prototypes @@ -403,7 +403,7 @@ static void densitySymbolIndexDecode( *index_phi = -1; return; } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP angle = atan2_fx( SQRT_DIM_fx[r_dim], SQRT_DIM_fx[l_dim] ); #ifndef BASOP_NOGLOB angle = shl( angle, 1 ); @@ -412,7 +412,7 @@ static void densitySymbolIndexDecode( #endif /* BASOP_NOGLOB */ angle = mult_r( angle, 20861 ); c = mult_r( res, angle ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP res_c = res - c; if ( c == 0 ) diff --git a/lib_dec/pvq_decode.c b/lib_dec/pvq_decode.c index c9a2bf41ab97c5a4ba7827c2aa0f5de1f4f3fbc5..a0da5f09ea6d015f42f9e1ef3b0fff5c04a5275a 100644 --- a/lib_dec/pvq_decode.c +++ b/lib_dec/pvq_decode.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Function pvq_decode() * diff --git a/lib_dec/range_dec.c b/lib_dec/range_dec.c index 55010e0b36088a36ca8e6263a441048a9021e8b7..25cfdb2155c48c3f5e4a5542996bcc456e590d7d 100644 --- a/lib_dec/range_dec.c +++ b/lib_dec/range_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local prototypes diff --git a/lib_dec/re8_dec.c b/lib_dec/re8_dec.c index 22a0a538a27ee7f235f89d8774131ae05611342f..d9a7c750dc8abb12c4d983cec25690b867f0d80d 100644 --- a/lib_dec/re8_dec.c +++ b/lib_dec/re8_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- diff --git a/lib_dec/rom_dec.c b/lib_dec/rom_dec.c index a79803ea5cccae9a227ee19deefd6e8a6a42aeb7..beba87c3dab82627e2d7182eac0a38746e59471f 100644 --- a/lib_dec/rom_dec.c +++ b/lib_dec/rom_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /* clang-format off */ diff --git a/lib_dec/rom_dec.h b/lib_dec/rom_dec.h index de17c9025159dabbdad0ce740eebb2ab2e1fa4d6..751a2e4da0c52c6f92ae2cea45ca9428c6a1cf19 100644 --- a/lib_dec/rom_dec.h +++ b/lib_dec/rom_dec.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_dec/rst_dec.c b/lib_dec/rst_dec.c index 6b8683767d87824a10083f2c84fcaf7852273df1..f3fbd32165e1130df70da4f48b896bf100e1f79e 100644 --- a/lib_dec/rst_dec.c +++ b/lib_dec/rst_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* * CNG_reset_dec() diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index 917331c050b9298da10cffbbef00ed75bb3da87a..1a82d45587c8cd0ff656a4342d75b2a54735e592 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -204,16 +204,15 @@ typedef struct Float32 *secondLastPcmOut; float *secondLastPowerSpectrum; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT float scaleFactorsBackground[FDNS_NPTS]; + float scf_fadeout; PsychoacousticParameters *psychParams; - /* could be stored only once, since the same for all channels (always at 16Khz fs) */ PsychoacousticParameters psychParamsTCX20; PsychoacousticParameters psychParamsTCX10; float last_block_nrg; float curr_noise_nrg; -#endif + float faded_signal_nrg; float nFramesLost; @@ -935,6 +934,7 @@ typedef struct Decoder_State int16_t ini_frame; /* initialization frames counter */ int16_t prev_coder_type; /* coding type of last frame */ int16_t low_rate_mode; /* low-rate mode flag */ + int16_t last_low_rate_mode; /* previous frame low-rate mode flag */ /*----------------------------------------------------------------------------------* * ACELP core parameters @@ -956,6 +956,9 @@ typedef struct Decoder_State float agc_mem2[2]; /* memory of AGC for saturation control */ int16_t mid_lsf_int; int16_t safety_net; + float stab_fac_smooth_lt; + float log_energy_old; + float log_energy_diff_lt; int16_t GSC_noisy_speech; /* AC mode (GSC) - flag to indicate GSC on SWB noisy speech */ int16_t GSC_IVAS_mode; /* AC mode (GSC) - GSC IVAS mode */ @@ -1336,14 +1339,17 @@ typedef struct Decoder_State *----------------------------------------------------------------------------------*/ int16_t tdm_LRTD_flag; /* LRTD stereo mode flag */ - int16_t cna_dirac_flag; /* CNA in DirAC flag*/ - int16_t cng_dirac_flag; /* CNG in DirAC flag*/ + int16_t cna_dirac_flag; /* CNA in DirAC flag */ + int16_t cng_sba_flag; /* CNG in SBA flag */ /* MCT Channel mode indication: LFE, ignore channel? */ MCT_CHAN_MODE mct_chan_mode; - - int16_t cng_spar_flag; /* CNG in SPAR flag*/ + int16_t cng_ism_flag; /* CNG in Param-ISM flag */ + int16_t read_sid_info; /* For ParamISM, use the transmitted noise */ +#ifdef DISCRETE_ISM_DTX_CNG + int16_t is_ism_format; /* Indication whether the codec operates in ISM format */ +#endif } Decoder_State, *DEC_CORE_HANDLE; diff --git a/lib_dec/stat_noise_uv_dec.c b/lib_dec/stat_noise_uv_dec.c index f9e8ec4f7878814d8e0ec84154bddc8fb03baeaf..2fa711814b4b290092e703bed04190a11bc0984f 100644 --- a/lib_dec/stat_noise_uv_dec.c +++ b/lib_dec/stat_noise_uv_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------* * stat_noise_uv_dec() diff --git a/lib_dec/swb_bwe_dec.c b/lib_dec/swb_bwe_dec.c index fca9267bd03b1ba62eba96be824b326a5ef5c446..e7eda534ae5817eaeaf22c5051753828f1ec478d 100644 --- a/lib_dec/swb_bwe_dec.c +++ b/lib_dec/swb_bwe_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "rom_com.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * para_pred_bws() diff --git a/lib_dec/swb_bwe_dec_hr.c b/lib_dec/swb_bwe_dec_hr.c index edfaaf67be4ef92c4fbdce0702a3d7b0b3658964..1c4d5c7f6ebb483b5091ce8b691e9db97ee9168b 100644 --- a/lib_dec/swb_bwe_dec_hr.c +++ b/lib_dec/swb_bwe_dec_hr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * swb_bwe_dec_hr() diff --git a/lib_dec/swb_bwe_dec_lr.c b/lib_dec/swb_bwe_dec_lr.c index d10be17f5f75ca758ea59e917785cf1219220793..4f29becf248e298f1aa223816d64366b30f82a88 100644 --- a/lib_dec/swb_bwe_dec_lr.c +++ b/lib_dec/swb_bwe_dec_lr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_dec/swb_tbe_dec.c b/lib_dec/swb_tbe_dec.c index 79b83e5c68d6336a0cefb4e82b4d904b9ad24a8d..79fe3b0e68df74513fc47ddd79198162d95365bc 100644 --- a/lib_dec/swb_tbe_dec.c +++ b/lib_dec/swb_tbe_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_dec.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /*-----------------------------------------------------------------* @@ -535,6 +535,7 @@ void swb_tbe_dec( { tilt_swb_fec = hBWE_TD->tilt_swb_fec; } + /* WB/SWB bandwidth switching */ if ( ( st->tilt_wb > 5 && st->clas_dec == UNVOICED_CLAS ) || st->tilt_wb > 10 ) { @@ -834,6 +835,7 @@ void swb_tbe_dec( { scale = (float) ( hBWE_TD->prev1_shb_ener_sf / sqrt( ( hBWE_TD->prev2_shb_ener_sf * hBWE_TD->prev3_shb_ener_sf ) + 0.0001 ) ); scale = hBWE_TD->prev_res_shb_gshape * min( scale, 1.0f ); + if ( hBWE_TD->prev2_shb_ener_sf > 2.0f * hBWE_TD->prev1_shb_ener_sf || hBWE_TD->prev3_shb_ener_sf > 2.0f * hBWE_TD->prev2_shb_ener_sf ) { shb_ener_sf = 0.5f * scale * hBWE_TD->prev1_shb_ener_sf; @@ -964,6 +966,7 @@ void swb_tbe_dec( /* convert from lsp to lsf */ lsp2lsf( lsp_temp, lsf_shb, LPC_SHB_ORDER, 1 ); } + mvr2r( lsf_diff + 1, hBWE_TD->prev_lsf_diff, LPC_SHB_ORDER - 2 ); hBWE_TD->prev_tilt_para = tilt_para; } @@ -1035,8 +1038,7 @@ void swb_tbe_dec( /* From low band excitation, generate highband excitation */ mvr2r( hBWE_TD->state_syn_shbexc, shaped_shb_excitation, L_SHB_LAHEAD ); GenShapedSHBExcitation( shaped_shb_excitation + L_SHB_LAHEAD, lpc_shb, White_exc16k, hBWE_TD->mem_csfilt, hBWE_TD->mem_genSHBexc_filt_down_shb, hBWE_TD->state_lpc_syn, st->coder_type, bwe_exc_extended, hBWE_TD->bwe_seed, vf_modified, st->extl, &( hBWE_TD->tbe_demph ), &( hBWE_TD->tbe_premph ), lpc_shb_sf, &shb_ener_sf, shb_res_gshape, shb_res_dummy, &vind, formant_fac, hBWE_TD->fb_state_lpc_syn, &( hBWE_TD->fb_tbe_demph ), st->total_brate, st->prev_bfi, st->element_mode, st->flag_ACELP16k, nlExc16k, mixExc16k, st->extl_brate, MSFlag, - NULL, &( hBWE_TD->prev_pow_exc16kWhtnd ), &( hBWE_TD->prev_mix_factor ), NULL, - NULL ); + NULL, &( hBWE_TD->prev_pow_exc16kWhtnd ), &( hBWE_TD->prev_mix_factor ), NULL, NULL ); /* fill-in missing SHB excitation */ if ( ( st->element_mode == IVAS_CPE_TD || st->element_mode == IVAS_CPE_DFT ) && st->last_core_brate <= SID_2k40 ) @@ -1973,10 +1975,11 @@ static void dequantizeSHBparams( *-------------------------------------------------------------------*/ void fb_tbe_dec( - Decoder_State *st, /* i/o: decoder state structure */ - const float fb_exc[], /* i : FB excitation from the SWB part */ - float *hb_synth, /* o : high-band synthesis */ - float *fb_synth_ref /* o : high-band synthesis 16-20 kHz */ + Decoder_State *st, /* i/o: decoder state structure */ + const float fb_exc[], /* i : FB excitation from the SWB part */ + float *hb_synth, /* o : high-band synthesis */ + float *fb_synth_ref, /* o : high-band synthesis 16-20 kHz */ + const int16_t output_frame /* i : output frame length */ ) { int16_t i; @@ -1986,22 +1989,35 @@ void fb_tbe_dec( hBWE_TD = st->hBWE_TD; - /* decode FB slope information */ - if ( st->extl == FB_TBE && !st->bfi ) + if ( output_frame == L_FRAME48k ) { - if ( st->codec_mode == MODE2 ) + /* decode FB slope information */ + if ( st->extl == FB_TBE && !st->bfi ) { - i = hBWE_TD->idxGain; + if ( st->codec_mode == MODE2 ) + { + i = hBWE_TD->idxGain; + } + else + { + i = get_next_indice( st, NUM_BITS_FB_FRAMEGAIN_TBE ); + } + ratio = (float) ( 1 << i ); } - else + else if ( st->extl == FB_TBE && st->bfi ) { - i = get_next_indice( st, 4 ); + ratio = hBWE_TD->prev_fbbwe_ratio; } - ratio = (float) ( 1 << i ); } - else if ( st->extl == FB_TBE && st->bfi ) + else { - ratio = hBWE_TD->prev_fbbwe_ratio; + /* update the position in the bitstream - needed in IVAS */ + if ( !st->bfi ) + { + st->next_bit_pos += NUM_BITS_FB_FRAMEGAIN; + } + + return; } fb_exc_energy = sum2_f( fb_exc, L_FRAME16k ); diff --git a/lib_dec/syn_outp.c b/lib_dec/syn_outp.c index cff7d72374ee94ea281256018ab3772617b3997a..c28666d1effccac38eb83f50b369cac9ca0e706f 100644 --- a/lib_dec/syn_outp.c +++ b/lib_dec/syn_outp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * syn_output() diff --git a/lib_dec/tcq_core_dec.c b/lib_dec/tcq_core_dec.c index a7050f9de0e21cddd11a4437280794a98eb46f89..8b0a6f2d40dbac5e01b5bb3dadadfdffb5b0b88a 100644 --- a/lib_dec/tcq_core_dec.c +++ b/lib_dec/tcq_core_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * tcq_core_LR_enc() @@ -148,7 +148,7 @@ void tcq_core_LR_dec( } } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP bsub_fx = L_shl( L_add( tcq_arbits, lsbtcq_bits ), 16 ); IF( bsub_fx > 0 ) { @@ -173,7 +173,7 @@ void tcq_core_LR_dec( } srt_vec_ind_fx( Rk_fx, Rk_sort_fx, k_sort, BANDS ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /*read the bits*/ nb_bytes = bit_budget >> 3; @@ -248,10 +248,10 @@ void tcq_core_LR_dec( } if ( surplus_fx != 0 ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP surplus_fx = L_add( Rk_fx[k_sort[k]], surplus_fx ); surplus_fx = L_add( delta_fx, surplus_fx ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } } else @@ -283,10 +283,10 @@ void tcq_core_LR_dec( } if ( surplus_fx != 0 ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP surplus_fx = L_add( Rk_fx[k_sort[k]], surplus_fx ); surplus_fx = L_add( delta_fx, surplus_fx ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } } else @@ -315,7 +315,7 @@ void tcq_core_LR_dec( if ( Rk_fx[k_sort[k]] > 0 && surplus_fx < 0 ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP IF( nzbands <= 1 ) { divider = 0; @@ -335,7 +335,7 @@ void tcq_core_LR_dec( delta_fx = 0; } surplus_fx = L_sub( surplus_fx, delta_fx ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } else { @@ -344,13 +344,13 @@ void tcq_core_LR_dec( } } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP if ( ( L_sub( surplus_fx, 524288 ) > 0 && sub( input_frame, L_FRAME8k ) == 0 ) || ( L_sub( surplus_fx, 786432 ) > 0 && sub( input_frame, L_FRAME16k ) == 0 ) ) { bit_surplus_fx[0] = Mult_32_16( surplus_fx, 24576 ); /* Q16 */ bit_surplus_fx[1] = Mult_32_16( surplus_fx, 8192 ); /* Q16 */ } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP else { bit_surplus_fx[0] = surplus_fx; @@ -363,9 +363,9 @@ void tcq_core_LR_dec( { if ( k == k_num[j] ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP Rk_fx[k_sort[k]] = L_add( Rk_fx[k_sort[k]], bit_surplus_fx[j] ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP if ( Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) { /* get number of pulses */ @@ -412,9 +412,9 @@ void tcq_core_LR_dec( decode_magnitude_usq_fx( pardec, band_width[k_sort[k]], pulsesnum, nz, &positions[band_start[k_sort[k]]], &inp_vector[band_start[k_sort[k]]] ); decode_signs_fx( pardec, band_width[k_sort[k]], &inp_vector[band_start[k_sort[k]]] ); -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP nzbands = sub( nzbands, 1 ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } else { diff --git a/lib_dec/tcx_utils_dec.c b/lib_dec/tcx_utils_dec.c index f817c61e03a8473759493ebd5c9a2132e3b0a8ac..5db8a20b082a433efae7170f55c868401f4c22d5 100644 --- a/lib_dec/tcx_utils_dec.c +++ b/lib_dec/tcx_utils_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- * tcx_decoder_memory_update() diff --git a/lib_dec/tns_base_dec.c b/lib_dec/tns_base_dec.c index b7d977c84fe4f117b951a36581ca27655f3ebb07..444c465042ed8232f18414ca6b69a8355b0a9b8c 100644 --- a/lib_dec/tns_base_dec.c +++ b/lib_dec/tns_base_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "rom_com.h" #include "prot.h" #include "stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* diff --git a/lib_dec/tonalMDCTconcealment.c b/lib_dec/tonalMDCTconcealment.c index b43f85b8f9d51e2979a620c735bbc33aee51d09a..81fa9fdf90606dad00025db95b6214a257b1259c 100644 --- a/lib_dec/tonalMDCTconcealment.c +++ b/lib_dec/tonalMDCTconcealment.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*******************************************************/ @@ -93,15 +93,15 @@ ivas_error TonalMDCTConceal_Init( hTonalMDCTConc->nSamplesCore = nSamplesCore; hTonalMDCTConc->nScaleFactors = nScaleFactors; -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT set_zero( hTonalMDCTConc->scaleFactorsBackground, FDNS_NPTS ); + hTonalMDCTConc->scf_fadeout = 1.0f; PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k, 64, 1, 1, &hTonalMDCTConc->psychParamsTCX20 ); PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k / 2, 64, 0, 1, &hTonalMDCTConc->psychParamsTCX10 ); hTonalMDCTConc->psychParams = NULL; hTonalMDCTConc->last_block_nrg = 0.0f; hTonalMDCTConc->curr_noise_nrg = 0.0f; -#endif + hTonalMDCTConc->faded_signal_nrg = 0.0f; /* Offset the pointer to the end of buffer, so that pTCI is not destroyed when new time samples are stored in lastPcmOut */ @@ -122,12 +122,8 @@ void TonalMDCTConceal_SaveFreqSignal( const float *mdctSpectrum, const uint16_t nNewSamples, const uint16_t nNewSamplesCore, - const float *scaleFactors -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - , - const int16_t infoIGFStartLine -#endif -) + const float *scaleFactors, + const int16_t infoIGFStartLine ) { float *temp; int16_t nOldSamples; @@ -168,7 +164,6 @@ void TonalMDCTConceal_SaveFreqSignal( if ( ( nNewSamples > 0 ) && ( nNewSamples <= 2 * L_FRAME_MAX ) ) { /* Store new data */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT int16_t i; hTonalMDCTConc->last_block_nrg = 0.0f; @@ -181,9 +176,6 @@ void TonalMDCTConceal_SaveFreqSignal( { hTonalMDCTConc->lastBlockData.spectralData[i] = mdctSpectrum[i]; } -#else - mvr2r( mdctSpectrum, hTonalMDCTConc->lastBlockData.spectralData, nNewSamples ); -#endif mvr2r( scaleFactors, hTonalMDCTConc->lastBlockData.scaleFactors, hTonalMDCTConc->nScaleFactors ); } @@ -394,15 +386,24 @@ static void CalcMDXT( const TonalMDCTConcealPtr hTonalMDCTConc, const char type, const float *timeSignal, - float *mdxtOutput, - const int16_t isLfe ) + float *mdxtOutput +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const int16_t isLfe +#endif +) { float windowedTimeSignal[L_FRAME_PLUS + 2 * L_MDCT_OVLP_MAX]; int16_t left_overlap, right_overlap; int16_t L_frame; L_frame = hTonalMDCTConc->nSamples; - WindowSignal( hTonalMDCTConc->tcx_cfg, hTonalMDCTConc->tcx_cfg->tcx_offsetFB, FULL_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, timeSignal, &L_frame, windowedTimeSignal, 1, 1, isLfe ); + WindowSignal( hTonalMDCTConc->tcx_cfg, hTonalMDCTConc->tcx_cfg->tcx_offsetFB, FULL_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, timeSignal, &L_frame, windowedTimeSignal, 1, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + isLfe +#endif + ); if ( type == 'S' ) { @@ -421,8 +422,12 @@ void TonalMDCTConceal_Detect( const TonalMDCTConcealPtr hTonalMDCTConc, const float pitchLag, int16_t *numIndices, - const PsychoacousticParameters *psychParamsCurrent, - const int16_t isLfe ) + const PsychoacousticParameters *psychParamsCurrent +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + const int16_t isLfe +#endif +) { float secondLastMDST[L_FRAME_MAX]; /* 32 bits are required */ float secondLastMDCT[L_FRAME_MAX]; /* 32 bits are required */ @@ -439,10 +444,18 @@ void TonalMDCTConceal_Detect( { if ( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive ) { - CalcMDXT( hTonalMDCTConc, 'S', hTonalMDCTConc->secondLastPcmOut, secondLastMDST, - isLfe ); - CalcMDXT( hTonalMDCTConc, 'C', hTonalMDCTConc->secondLastPcmOut, secondLastMDCT, - isLfe ); + CalcMDXT( hTonalMDCTConc, 'S', hTonalMDCTConc->secondLastPcmOut, secondLastMDST +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + isLfe +#endif + ); + CalcMDXT( hTonalMDCTConc, 'C', hTonalMDCTConc->secondLastPcmOut, secondLastMDCT +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + isLfe +#endif + ); hTonalMDCTConc->nNonZeroSamples = 0; for ( i = 0; i < hTonalMDCTConc->nSamples; i++ ) { @@ -500,17 +513,17 @@ void TonalMDCTConceal_InsertNoise( int16_t *pSeed, const float tiltCompFactor, const float crossfadeGain, -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT const float concealment_noise[L_FRAME48k], -#endif + const float cngLevelBackgroundTrace_bfi, const int16_t crossOverFreq ) { int16_t i, l; float x, y; Word16 rnd; float g, nrgNoiseInLastFrame, nrgWhiteNoise, tiltFactor, tilt; + float last_block_nrg_correct; - wmops_sub_start( "InsertNoise" ); + push_wmops( "InsertNoise" ); g = 1.0f - crossfadeGain; if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed ) @@ -522,21 +535,20 @@ void TonalMDCTConceal_InsertNoise( rnd = *pSeed; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT /* based on what is done in tcx_noise_filling() */ /* always initialize these to avoid compiler warnings */ tiltFactor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / hTonalMDCTConc->lastBlockData.nSamples ); tilt = 1.0f; nrgNoiseInLastFrame = 0.0f; nrgWhiteNoise = 0.0f; -#endif + hTonalMDCTConc->faded_signal_nrg = 0.0f; + last_block_nrg_correct = 0.0f; if ( !hTonalMDCTConc->lastBlockData.blockIsValid ) { /* may just become active if the very first frame is lost */ set_f( mdctSpectrum, 0.0f, hTonalMDCTConc->nSamples ); } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT else if ( concealment_noise != NULL ) { if ( !tonalConcealmentActive ) @@ -564,7 +576,7 @@ void TonalMDCTConceal_InsertNoise( /* actual fadeout is done in this case */ else { - g *= (float) sqrt( hTonalMDCTConc->last_block_nrg / hTonalMDCTConc->curr_noise_nrg ); + g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg ); for ( i = 0; i < crossOverFreq; i++ ) { @@ -579,6 +591,8 @@ void TonalMDCTConceal_InsertNoise( { mdctSpectrum[i] = g * y - crossfadeGain * x; } + + hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[i] * mdctSpectrum[i]; } for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ ) { @@ -599,6 +613,11 @@ void TonalMDCTConceal_InsertNoise( for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ ) { mdctSpectrum[l] = 0; + if ( l < crossOverFreq ) + { + last_block_nrg_correct += hTonalMDCTConc->lastBlockData.spectralData[l] * hTonalMDCTConc->lastBlockData.spectralData[l]; + hTonalMDCTConc->curr_noise_nrg -= concealment_noise[l] * concealment_noise[l]; + } } } @@ -651,7 +670,7 @@ void TonalMDCTConceal_InsertNoise( /* actual fadeout is done in this case */ else { - g *= (float) sqrt( hTonalMDCTConc->last_block_nrg / hTonalMDCTConc->curr_noise_nrg ); + g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg ); for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ ) { @@ -666,6 +685,7 @@ void TonalMDCTConceal_InsertNoise( { mdctSpectrum[l] = g * y - crossfadeGain * x; } + hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l]; } for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ ) { @@ -682,6 +702,7 @@ void TonalMDCTConceal_InsertNoise( { mdctSpectrum[l] = g * y - crossfadeGain * x; } + hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l]; } } @@ -698,6 +719,7 @@ void TonalMDCTConceal_InsertNoise( { mdctSpectrum[l] = g * y - crossfadeGain * x; } + hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l]; } for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ ) @@ -706,16 +728,17 @@ void TonalMDCTConceal_InsertNoise( } } } + + if ( hTonalMDCTConc->faded_signal_nrg > 0.0f && hTonalMDCTConc->curr_noise_nrg > MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG ) + { + float nrg_corr_factor; + + nrg_corr_factor = sqrtf( ( hTonalMDCTConc->last_block_nrg - last_block_nrg_correct ) / hTonalMDCTConc->faded_signal_nrg ); + v_multc( mdctSpectrum, nrg_corr_factor, mdctSpectrum, crossOverFreq ); + } } -#endif else { -#ifndef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - /* based on what is done in tcx_noise_filling() */ - tiltFactor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / hTonalMDCTConc->lastBlockData.nSamples ); - tilt = 1.0f; - nrgNoiseInLastFrame = nrgWhiteNoise = 0.0f; -#endif if ( !tonalConcealmentActive ) { for ( i = 0; i < crossOverFreq; i++ ) @@ -858,7 +881,7 @@ void TonalMDCTConceal_InsertNoise( *pSeed = rnd; - wmops_sub_end(); + pop_wmops(); return; } @@ -962,7 +985,6 @@ void TonalMDCTConceal_SaveTimeSignal( return; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT void TonalMdctConceal_create_concealment_noise( float concealment_noise[L_FRAME48k], CPE_DEC_HANDLE hCPE, @@ -971,7 +993,7 @@ void TonalMdctConceal_create_concealment_noise( const int16_t idchan, const int16_t subframe_idx, const int16_t core, - const int16_t crossfade_gain, + const float crossfade_gain, const TONALMDCTCONC_NOISE_GEN_MODE noise_gen_mode ) { STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct; @@ -986,7 +1008,7 @@ void TonalMdctConceal_create_concealment_noise( float *cngNoiseLevelPtr; float last_scf; - wmops_sub_start( "create_conc_noise" ); + push_wmops( "create_conc_noise" ); hStereoMdct = hCPE->hStereoMdct; st = hCPE->hCoreCoder[idchan]; @@ -1038,7 +1060,7 @@ void TonalMdctConceal_create_concealment_noise( concealment_noise[i] = *rnd; } - wmops_sub_end(); + pop_wmops(); return; } @@ -1049,7 +1071,6 @@ void TonalMdctConceal_create_concealment_noise( c_inv = sqrtf( 1 - hStereoMdct->lastCoh ); /* pre-compute the noise shape for later weighting of the noise spectra */ - /* TODO: optimize by intertwining with later loop */ cngNoiseLevelPtr = &hFdCngCom->cngNoiseLevel[0]; inc = ( st->core > TCX_20_CORE ) ? 2 : 1; start_idx = hFdCngCom->startBand / inc; @@ -1072,7 +1093,7 @@ void TonalMdctConceal_create_concealment_noise( } /* fill the noise vector */ - hTonalMDCTConc->curr_noise_nrg = 0.001f; + hTonalMDCTConc->curr_noise_nrg = MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG; if ( noise_gen_mode == EQUAL_CORES || ( ( noise_gen_mode == TCX20_IN_0_TCX10_IN_1 && idchan == 0 ) || ( noise_gen_mode == TCX10_IN_0_TCX20_IN_1 && idchan == 1 ) ) ) { /* current channel is TCX20 -> generate noise for "full-length" spectrum */ @@ -1100,6 +1121,14 @@ void TonalMdctConceal_create_concealment_noise( } } + if ( st->tonal_mdct_plc_active ) + { + for ( i = crossOverFreq; i < max( crossOverFreq, hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] ); ++i ) + { + concealment_noise[i] *= 0.0f; + } + } + /* restore common seed - after finishing the first channel - after a first subframe if the current channel is TCX10 */ @@ -1108,8 +1137,65 @@ void TonalMdctConceal_create_concealment_noise( *rnd_c = save_rnd_c; } - wmops_sub_end(); + st->seed_tcx_plc = *rnd; + + pop_wmops(); return; } -#endif + +void TonalMdctConceal_whiten_noise_shape( + Decoder_State *st, + const int16_t L_frame, + const TONALMDCTCONC_NOISE_SHAPE_WHITENING_MODE whitening_mode ) +{ + int16_t inc, start_idx, stop_idx; + float *noiseLevelPtr, *scfs_bg, *scfs_for_shaping; + HANDLE_FD_CNG_COM hFdCngCom; + float whitenend_noise_shape[L_FRAME16k]; + float scfs_int[FDNS_NPTS]; + const PsychoacousticParameters *psychParams; + + push_wmops( "apply_sns_on_noise_shape" ); + + scfs_bg = &st->hTonalMDCTConc->scaleFactorsBackground[0]; + psychParams = st->hTonalMDCTConc->psychParams; + hFdCngCom = st->hFdCngDec->hFdCngCom; + + inc = ( ( whitening_mode == ON_FIRST_LOST_FRAME ? st->core : st->last_core ) > TCX_20_CORE ) ? 2 : 1; + start_idx = hFdCngCom->startBand / inc; + stop_idx = L_frame / inc; + noiseLevelPtr = hFdCngCom->cngNoiseLevel; + + set_zero( whitenend_noise_shape, start_idx ); + for ( int16_t j = start_idx; j < stop_idx; j++, noiseLevelPtr += inc ) + { + whitenend_noise_shape[j] = *noiseLevelPtr; + } + + if ( whitening_mode == ON_FIRST_LOST_FRAME ) + { + float scf[SNS_NPTS]; + + sns_compute_scf( whitenend_noise_shape, psychParams, L_frame, scf ); + sns_interpolate_scalefactors( scfs_int, scf, ENC ); + sns_interpolate_scalefactors( scfs_bg, scf, DEC ); + scfs_for_shaping = &scfs_int[0]; + } + else /* whitening_mode == ON_FIRST_GOOD_FRAME */ + { + scfs_for_shaping = &scfs_bg[0]; + } + + if ( sum_f( scfs_for_shaping, FDNS_NPTS ) > 0.0f ) + { + sns_shape_spectrum( whitenend_noise_shape, psychParams, scfs_for_shaping, L_frame ); + mvr2r( whitenend_noise_shape + start_idx, hFdCngCom->cngNoiseLevel, stop_idx - start_idx ); + } + else + { + set_zero( hFdCngCom->cngNoiseLevel, stop_idx - start_idx ); + } + + pop_wmops(); +} diff --git a/lib_dec/transition_dec.c b/lib_dec/transition_dec.c index 9bcecf40b87d70a5ca7b492b76fd03dd8f11607a..05c7887f4babdbef97dae6bf2a0644a4ae1bb675 100644 --- a/lib_dec/transition_dec.c +++ b/lib_dec/transition_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------* * Local function prototypes diff --git a/lib_dec/updt_dec.c b/lib_dec/updt_dec.c index 2241e919df0a09fbe431a4b579ad2c2c436c23e1..81f4027221fa6fefcc08ee46997f33fbda9179bf 100644 --- a/lib_dec/updt_dec.c +++ b/lib_dec/updt_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,8 @@ #include "prot.h" #include "rom_com.h" #include "cnst.h" -#include "wmops.h" +#include +#include "wmc_auto.h" /*-------------------------------------------------------------------* * updt_dec() @@ -326,7 +327,7 @@ void updt_IO_switch_dec( hf_synth_amr_wb_reset( st->hAmrwb_IO, st->hBWE_zero ); - /* reset VBR signalling */ + /* reset VBR signaling */ st->last_ppp_mode_dec = 0; st->last_nelp_mode_dec = 0; st->ppp_mode_dec = 0; @@ -413,6 +414,8 @@ void updt_dec_common( ) { int16_t i; + float log_energy, log_energy_diff; + int16_t output_frame; st->last_codec_mode = st->codec_mode; st->last_extl = st->extl; @@ -502,6 +505,22 @@ void updt_dec_common( mvr2r( synth + NS2SA( st->output_Fs, ACELP_LOOK_NS + DELAY_BWE_TOTAL_NS ), st->old_synth_sw, NS2SA( st->output_Fs, FRAME_SIZE_NS - ACELP_LOOK_NS - DELAY_BWE_TOTAL_NS ) ); } + /* Store long-term estimates of stab_fac and log energy diff to estimate env_stab in case of core switch ACELP/TCX->HQ */ + if ( st->element_mode != EVS_MONO ) + { + output_frame = NS2SA( st->output_Fs, FRAME_SIZE_NS ); + log_energy = log2f( ( sum2_f( synth, output_frame ) / output_frame ) + 1.0f ); + log_energy_diff = fabsf( st->log_energy_old - log_energy ); + st->log_energy_old = log_energy; + st->log_energy_diff_lt = ENV_SMOOTH_FAC * log_energy_diff + ( 1.0f - ENV_SMOOTH_FAC ) * st->log_energy_diff_lt; + if ( st->core == HQ_CORE ) + { + st->stab_fac = min( 1, ( STAB_FAC_EST1 + ( STAB_FAC_EST2 * st->hHQ_core->mem_env_delta ) + ( STAB_FAC_EST3 * st->log_energy_diff_lt ) ) ); + st->stab_fac = max( 0, st->stab_fac ); + } + st->stab_fac_smooth_lt = ENV_SMOOTH_FAC * st->stab_fac + ( 1.0f - ENV_SMOOTH_FAC ) * st->stab_fac_smooth_lt; + } + if ( ( st->core_brate <= SID_2k40 && st->cng_type == FD_CNG ) || ( st->tcxonly && st->codec_mode == MODE2 ) ) { /* reset LP memories */ @@ -622,6 +641,8 @@ void updt_dec_common( st->last_bits_frame_nominal = st->bits_frame_nominal; } + st->last_low_rate_mode = st->low_rate_mode; + /*-----------------------------------------------------------------* * Increase the counter of initialization frames * Limit the max number of init. frames diff --git a/lib_dec/vlpc_1st_dec.c b/lib_dec/vlpc_1st_dec.c index 1aa1ab72f21febd0970da62363b2cd19f0c2cb07..cc7b33bc9a5754ffb867eb9ba2a35d4e51e0262e 100644 --- a/lib_dec/vlpc_1st_dec.c +++ b/lib_dec/vlpc_1st_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "options.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * vlpc_1st_dec() diff --git a/lib_dec/vlpc_2st_dec.c b/lib_dec/vlpc_2st_dec.c index 83163cda78a2afc6c9b2bbd4f47916f0739a7066..8ac23141b83c681149148297be8f2fafbf1ed2f8 100644 --- a/lib_dec/vlpc_2st_dec.c +++ b/lib_dec/vlpc_2st_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * vlpc_2st_dec() diff --git a/lib_dec/voiced_dec.c b/lib_dec/voiced_dec.c index 08d58ffc7df0e364884823865f0c2652aea2fba3..5c2bcc1f15e6de19b2d7924b112b886d51696e90 100644 --- a/lib_dec/voiced_dec.c +++ b/lib_dec/voiced_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * ppp_voiced_decoder() @@ -233,9 +233,9 @@ ivas_error ppp_voiced_decoder( mvr2r( dtfs_temp->a, hSC_VBR->dtfs_dec_a, MAXLAG_WI ); mvr2r( dtfs_temp->b, hSC_VBR->dtfs_dec_b, MAXLAG_WI ); - count_free( TMPDTFS ); - count_free( CURRP_Q_D ); - count_free( dtfs_temp ); + free( TMPDTFS ); + free( CURRP_Q_D ); + free( dtfs_temp ); return error; } diff --git a/lib_dec/waveadjust_fec_dec.c b/lib_dec/waveadjust_fec_dec.c index 222fb66599b49e84059c6c48bb2743c97ab08d27..99a10e886c77a2326a1feefb81756b084c5a3acd 100644 --- a/lib_dec/waveadjust_fec_dec.c +++ b/lib_dec/waveadjust_fec_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/ACcontextMapping_enc.c b/lib_enc/ACcontextMapping_enc.c index 62ab9e7552c227cf1040737a7f71b70f16e989d5..a608db5ea2d160df5e64f5a470337dddfcdc720b 100644 --- a/lib_enc/ACcontextMapping_enc.c +++ b/lib_enc/ACcontextMapping_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/FEC_enc.c b/lib_enc/FEC_enc.c index 89868e6729551a8df58a69eb0e37e210b93db1a3..5bf8d1f1f40ad22daf5caf15e6570cfaf9a00d74 100644 --- a/lib_enc/FEC_enc.c +++ b/lib_enc/FEC_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * FEC_encode() diff --git a/lib_enc/SNR_calc.c b/lib_enc/SNR_calc.c index 1ccaad6e0fbfe5317655b1e1963dc173d3d32c35..6078062ea35c5a15155853f81e25650a0f93f4e0 100644 --- a/lib_enc/SNR_calc.c +++ b/lib_enc/SNR_calc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "prot.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index 8420810339a593c253dcddb24f8c8b1ef01d6dc1..48cdb5c53614619ab4a6e765bdb1450ef659d48a 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -50,7 +50,7 @@ #ifdef LSF_RE_USE_SECONDARY_CHANNEL #include "ivas_rom_com.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * acelp_core_enc() @@ -131,7 +131,7 @@ ivas_error acelp_core_enc( return error; } - wmops_sub_start( "acelp_core_enc" ); + push_wmops( "acelp_core_enc" ); /*------------------------------------------------------------------* * Initialization *------------------------------------------------------------------*/ @@ -314,10 +314,13 @@ ivas_error acelp_core_enc( if ( st->core_brate == SID_2k40 ) { - tmpF = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, exc, st->L_frame ); - i = (int16_t) ( ( tmpF + 2.0f ) * STEP_SID ); - i = min( max( i, 0 ), 127 ); - st->hTdCngEnc->old_enr_index = i; + if ( st->hTdCngEnc != NULL ) + { + tmpF = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, exc, st->L_frame ); + i = (int16_t) ( ( tmpF + 2.0f ) * STEP_SID ); + i = min( max( i, 0 ), 127 ); + st->hTdCngEnc->old_enr_index = i; + } } } @@ -473,6 +476,13 @@ ivas_error acelp_core_enc( residu( Aq, M, hLPDmem->old_exc, old_exc, st->L_frame ); } + if ( st->last_core != ACELP_CORE && st->element_mode > EVS_MONO ) + { + /* Prepare ACB memory of old_bwe_exc */ + lerp( old_exc, old_bwe_exc, L_EXC_MEM_DEC * HIBND_ACB_L_FAC, L_EXC_MEM_DEC ); + } + + /*---------------------------------------------------------------* * Calculation of LP residual (filtering through A[z] filter) *---------------------------------------------------------------*/ @@ -750,7 +760,7 @@ ivas_error acelp_core_enc( } } - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_enc/acelp_core_switch_enc.c b/lib_enc/acelp_core_switch_enc.c index 52c955732c9d8959831a2e83fd5504c5ba642125..291c2128a19a6423946c78e27b1dc0bff58e44f2 100644 --- a/lib_enc/acelp_core_switch_enc.c +++ b/lib_enc/acelp_core_switch_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes @@ -151,8 +151,7 @@ void acelp_core_switch_enc( * Excitation encoding *----------------------------------------------------------------*/ - config_acelp1( ENC, st->total_brate, cbrate, st->core, -1, -1, st->last_L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, GENERIC, -1, -1, &j, &i, st->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st->idchan, 0 /*tdm_Pitch_reuse_flag*/, 0, 0 /*GSC_IVAS_mode*/ - ); + config_acelp1( ENC, st->total_brate, cbrate, st->core, -1, -1, st->last_L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, GENERIC, -1, -1, &j, &i, st->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st->idchan, 0 /*tdm_Pitch_reuse_flag*/, 0, 0 /*GSC_IVAS_mode*/ ); encod_gen_voic_core_switch( st, st->last_L_frame, inp, Aq, A, T_op, st->voicing, exc, cbrate ); diff --git a/lib_enc/acelp_enc_util.c b/lib_enc/acelp_enc_util.c index 003dadb026122b366b91acff392189eea7ba3919..fdbc3a8b09a852ee66ee615018bb8c223f6ef96c 100644 --- a/lib_enc/acelp_enc_util.c +++ b/lib_enc/acelp_enc_util.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,11 +39,10 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "typedef.h" #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * E_ACELP_toeplitz_mul() diff --git a/lib_enc/amr_wb_enc.c b/lib_enc/amr_wb_enc.c index 76ddf9e705286e9cc3c70f85b7b204e2beef3f58..88b3faa5d6c16ffafa834706a7631fd915cf44fa 100644 --- a/lib_enc/amr_wb_enc.c +++ b/lib_enc/amr_wb_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_MODE_INFO extern float snr_[2][320]; @@ -292,7 +292,7 @@ void amr_wb_enc( } /* apply DTX hangover for CNG analysis */ - vad_flag_dtx = dtx_hangover_addition( st, st->vad_flag, st->lp_speech - st->lp_noise, 0, &vad_hover_flag, NULL, NULL ); + vad_flag_dtx = dtx_hangover_addition( st, st->vad_flag, st->lp_speech - st->lp_noise, 0, &vad_hover_flag, NULL, NULL, NULL ); /*-----------------------------------------------------------------* * Select SID or FRAME_NO_DATA frame if DTX enabled @@ -310,9 +310,7 @@ void amr_wb_enc( { st->fd_cng_reset_flag = 0; } - - dtx( st, vad_flag_dtx, inp ); - + dtx( st, -1, vad_flag_dtx, inp ); /*----------------------------------------------------------------* * Noise energy down-ward update and total noise energy estimation * Long-term energies and relative frame energy updates @@ -344,7 +342,12 @@ void amr_wb_enc( * WB, SWB and FB bandwidth detector *----------------------------------------------------------------*/ - bw_detect( st, st->input, NULL, NULL ); + bw_detect( st, st->input, NULL, NULL +#ifdef FIX_MDCT_BASED_BWD + , + 0 +#endif + ); /* in AMR_WB IO, limit the maximum band-width to WB */ if ( st->bwidth > WB ) @@ -531,7 +534,8 @@ void amr_wb_enc( updt_enc( st, old_exc, pitch_buf, 0, Aq, isf_new, isp_new, dummy_buf ); /* update main codec paramaters */ - updt_enc_common( st, Etot ); + updt_enc_common( st ); + #ifdef DEBUG_MODE_INFO dbgwrite( &st->codec_mode, sizeof( int16_t ), 1, input_frame, "res/codec" ); diff --git a/lib_enc/analy_lp.c b/lib_enc/analy_lp.c index b4b990634e401716793e511eeacc14fa1c8bd272..c0541e78fd6eae201ecbea101d63e7079bb63392 100644 --- a/lib_enc/analy_lp.c +++ b/lib_enc/analy_lp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * analy_lp() diff --git a/lib_enc/analy_sp.c b/lib_enc/analy_sp.c index 5828e72483509a2db1a0f0b4e0baa111678047d6..4a4bcb357dbee5cea73b8d7e8ef9c8d2ee026674 100644 --- a/lib_enc/analy_sp.c +++ b/lib_enc/analy_sp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include #include "ivas_cnst.h" diff --git a/lib_enc/ari_enc.c b/lib_enc/ari_enc.c index 3c6df474f873c408d6d7feaf6ea626aaf70cb9c6..405b3a8994a0a0973f7b90289695e837c14736de 100644 --- a/lib_enc/ari_enc.c +++ b/lib_enc/ari_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------- diff --git a/lib_enc/ari_hm_enc.c b/lib_enc/ari_hm_enc.c index c88ac3812a4b4d137fa3d751ac0ffe0140b30773..46a093369b1e057027af064ed29322e02c694845 100644 --- a/lib_enc/ari_hm_enc.c +++ b/lib_enc/ari_hm_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "basop_util.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * EncodeIndex() diff --git a/lib_enc/arith_coder_enc.c b/lib_enc/arith_coder_enc.c index 553721377c396bc79b2a8593a8f068e7028a6afd..546e7f07ab8715eab463dcaeb22893a923a8cfc4 100644 --- a/lib_enc/arith_coder_enc.c +++ b/lib_enc/arith_coder_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "rom_com.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants @@ -611,9 +611,9 @@ void tcx_arith_encode_envelope( gamma_w = 1.0f; gamma_uw = 1.0f / st->gamma; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP tcx_arith_render_envelope( A_ind, L_frame, L_spec, FL2WORD16( hTcxCfg->preemph_fac ), FL2WORD16( gamma_w ), FL2WORD16( 0.5f * gamma_uw ), env ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP for ( k = 0; k < L_spec; ++k ) { @@ -649,13 +649,13 @@ void tcx_arith_encode_envelope( envelope = (Word16 *) env; tcx_arith_scale_envelope( L_spec, L_spec_core, env, target_bits, low_complexity, envelope, &envelope_e ); -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP tmp = sub( envelope_e, 1 ); FOR( k = 0; k < L_spec; k++ ) { exponents[k] = expfp( negate( envelope[k] ), tmp ); } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP scale = tcx_arith_rateloop( spectrum, L_spec, envelope, envelope_e, exponents, target_bits, deadzone, deadzone_flags, &( hTcxEnc->tcx_target_bits_fac ) ); /* Final quantization */ diff --git a/lib_enc/avq_cod.c b/lib_enc/avq_cod.c index 601138ccd0803fe6cfc17a19cce8581afbbff4b3..78900b554cc8c5e1999657ddc66ec81921fd2cdd 100644 --- a/lib_enc/avq_cod.c +++ b/lib_enc/avq_cod.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local prototypes diff --git a/lib_enc/bass_psfilter_enc.c b/lib_enc/bass_psfilter_enc.c index 3d9a390945d4e8b42fa3d7a0e0ab73e1fda8e001..582ed3f22e59f51af0cd40a6311c6ebdd5efa89b 100644 --- a/lib_enc/bass_psfilter_enc.c +++ b/lib_enc/bass_psfilter_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* diff --git a/lib_enc/bw_detect.c b/lib_enc/bw_detect.c index c1357a7f7470346a038bfbd316f75d589c0e4e7b..810527e0ef2b6aab7f373d4fa5edbe02795c153a 100644 --- a/lib_enc/bw_detect.c +++ b/lib_enc/bw_detect.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants @@ -57,6 +57,9 @@ #define BWD_COUNT_MAX 100 #define BWD_COUNT_WIDER_BW 10 +#ifdef FIX_MDCT_BASED_BWD +#define BWD_COUNT_WIDER_BW_MDCT 0 +#endif #define CLDFB_ENER_OFFSET 1.6f @@ -71,6 +74,10 @@ void bw_detect( const float signal_in[], /* i : input signal */ float *spectrum, /* i : MDCT spectrum */ const float *enerBuffer /* i : energy buffer */ +#ifdef FIX_MDCT_BASED_BWD + , + const int16_t mct_on /* i : flag MCT mode */ +#endif ) { int16_t i, j, k, bw_max, bin_width, n_bins; @@ -80,6 +87,15 @@ void bw_detect( const float *pt, *pt1; float max_NB, max_WB, max_SWB, max_FB, mean_NB, mean_WB, mean_SWB, mean_FB; int16_t cldfb_bin_width = 4; +#ifdef FIX_MDCT_BASED_BWD + int16_t bwd_count_wider_bw, l_frame; + + bwd_count_wider_bw = BWD_COUNT_WIDER_BW; + if ( st->element_mode == IVAS_CPE_MDCT && ( st->element_brate > IVAS_64k || mct_on ) ) + { + bwd_count_wider_bw = BWD_COUNT_WIDER_BW_MDCT; + } +#endif if ( st->input_Fs > 8000 ) { @@ -173,8 +189,19 @@ void bw_detect( } else { +#ifndef FIX_MDCT_BASED_BWD bin_width *= (int16_t) ( ( st->input_Fs / FRAMES_PER_SEC ) / BWD_TOTAL_WIDTH ); mvr2r( spectrum, spect, (int16_t) ( st->input_Fs / FRAMES_PER_SEC ) ); +#else + l_frame = (int16_t) ( st->input_Fs / FRAMES_PER_SEC ); + if ( st->core == TCX_10_CORE ) + { + l_frame /= 2; + } + + bin_width *= ( l_frame / BWD_TOTAL_WIDTH ); + mvr2r( spectrum, spect, l_frame ); +#endif } /*---------------------------------------------------------------------* * compute energy per spectral bins @@ -392,17 +419,29 @@ void bw_detect( /* switching to a higher BW */ if ( st->last_input_bwidth == NB ) { +#ifdef FIX_MDCT_BASED_BWD + if ( st->count_WB > bwd_count_wider_bw ) +#else if ( st->count_WB > BWD_COUNT_WIDER_BW ) +#endif { st->input_bwidth = WB; st->count_WB = BWD_COUNT_MAX; +#ifdef FIX_MDCT_BASED_BWD + if ( st->count_SWB > bwd_count_wider_bw ) +#else if ( st->count_SWB > BWD_COUNT_WIDER_BW ) +#endif { st->input_bwidth = SWB; st->count_SWB = BWD_COUNT_MAX; +#ifdef FIX_MDCT_BASED_BWD + if ( st->count_FB > bwd_count_wider_bw ) +#else if ( st->count_FB > BWD_COUNT_WIDER_BW ) +#endif { st->input_bwidth = FB; st->count_FB = BWD_COUNT_MAX; @@ -413,12 +452,20 @@ void bw_detect( if ( st->last_input_bwidth == WB && st->input_Fs > 16000 ) { +#ifdef FIX_MDCT_BASED_BWD + if ( st->count_SWB > bwd_count_wider_bw ) +#else if ( st->count_SWB > BWD_COUNT_WIDER_BW ) +#endif { st->input_bwidth = SWB; st->count_SWB = BWD_COUNT_MAX; +#ifdef FIX_MDCT_BASED_BWD + if ( st->count_FB > bwd_count_wider_bw ) +#else if ( st->count_FB > BWD_COUNT_WIDER_BW ) +#endif { st->input_bwidth = FB; st->count_FB = BWD_COUNT_MAX; @@ -428,7 +475,11 @@ void bw_detect( if ( st->last_input_bwidth == SWB && st->input_Fs > 32000 ) { +#ifdef FIX_MDCT_BASED_BWD + if ( st->count_FB > bwd_count_wider_bw ) +#else if ( st->count_FB > BWD_COUNT_WIDER_BW ) +#endif { st->input_bwidth = FB; st->count_FB = BWD_COUNT_MAX; @@ -494,7 +545,6 @@ void bw_detect( st->input_bwidth = st->max_bwidth; } - if ( st->element_mode == EVS_MONO ) { set_bw( -1, -1, st, st->codec_mode ); @@ -621,6 +671,7 @@ void set_bw_stereo( if ( hCPE->element_mode == IVAS_CPE_MDCT ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE /* do not check bandwidth in LFE channel */ if ( sts[0]->mct_chan_mode == MCT_CHAN_MODE_LFE ) { @@ -641,6 +692,19 @@ void set_bw_stereo( sts[0]->bwidth = max( sts[0]->input_bwidth, sts[1]->input_bwidth ); sts[1]->bwidth = max( sts[0]->input_bwidth, sts[1]->input_bwidth ); } +#else + /* ensure that both CPE channels have the same audio band-width */ + if ( sts[0]->input_bwidth == sts[1]->input_bwidth ) + { + sts[0]->bwidth = sts[0]->input_bwidth; + sts[1]->bwidth = sts[0]->input_bwidth; + } + else + { + sts[0]->bwidth = max( sts[0]->input_bwidth, sts[1]->input_bwidth ); + sts[1]->bwidth = max( sts[0]->input_bwidth, sts[1]->input_bwidth ); + } +#endif } sts[0]->bwidth = max( sts[0]->bwidth, WB ); @@ -661,7 +725,7 @@ int16_t set_bw_mct( const int16_t nCPE /* i : number of CPEs */ ) { - Encoder_State *sts[MCT_MAX_CHANNELS]; + Encoder_State *st; int16_t ch, cpe_id; int16_t mct_bwidth, last_mct_bwidth, bw_changed; @@ -672,13 +736,17 @@ int16_t set_bw_mct( { for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - sts[ch] = hCPE[cpe_id]->hCoreCoder[ch]; - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + st = hCPE[cpe_id]->hCoreCoder[ch]; + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } - mct_bwidth = max( mct_bwidth, sts[ch]->input_bwidth ); + mct_bwidth = max( mct_bwidth, st->input_bwidth ); } } @@ -691,8 +759,8 @@ int16_t set_bw_mct( { for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - sts[ch] = hCPE[cpe_id]->hCoreCoder[ch]; - sts[ch]->bwidth = mct_bwidth; + st = hCPE[cpe_id]->hCoreCoder[ch]; + st->bwidth = mct_bwidth; } } } diff --git a/lib_enc/cng_enc.c b/lib_enc/cng_enc.c index 20787dd3f714f2af221046f5bfb148fea734104d..04d9e4116621c977f0ae6a60f4c4adc90d259576 100644 --- a/lib_enc/cng_enc.c +++ b/lib_enc/cng_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_enc/cod2t32.c b/lib_enc/cod2t32.c index 1efef884d48a2d1c235ea7965ac6a26ceb312b47..0d5e548bef1df7cf005da2677c37f1eab951dc06 100644 --- a/lib_enc/cod2t32.c +++ b/lib_enc/cod2t32.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_enc/cod4t64.c b/lib_enc/cod4t64.c index 2c9ad01e21ce27e3ca0adf8877b75b7e541afba8..79d1814f5cced5c37f656129cf1a968f6d2211bc 100644 --- a/lib_enc/cod4t64.c +++ b/lib_enc/cod4t64.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_enc.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_enc/cod4t64_fast.c b/lib_enc/cod4t64_fast.c index b67248ebe2bc65967e8cfb956a373a61228fb87f..9c16758d477e454ea61e6d0953491903a106fbbf 100644 --- a/lib_enc/cod4t64_fast.c +++ b/lib_enc/cod4t64_fast.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/cod_ace.c b/lib_enc/cod_ace.c index 091146298af6849bc4e6cf43fa9421819c7d043e..7a5c605d9ac852710e955c2f328869392bb19140 100644 --- a/lib_enc/cod_ace.c +++ b/lib_enc/cod_ace.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "debug.h" #endif #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * coder_acelp() diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c index 2ac9ca9aca2ed5c8aa2be413009a72a3874221af..ee948998a1ac48fdfdc95cd728a559b9cb27bd81 100644 --- a/lib_enc/cod_tcx.c +++ b/lib_enc/cod_tcx.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" #include "ivas_rom_com.h" #ifdef DEBUGGING @@ -73,7 +73,12 @@ void HBAutocorrelation( * Windowing * *-----------------------------------------------------------*/ - WindowSignal( hTcxCfg, hTcxCfg->tcx_offset, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, speech, &L_frame, xn_buf, 1, 0, 0 ); + WindowSignal( hTcxCfg, hTcxCfg->tcx_offset, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, speech, &L_frame, xn_buf, 1, 0 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); /*-----------------------------------------------------------* * Autocorrelation * @@ -134,11 +139,15 @@ void TNSAnalysisStereo( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { continue; } + hTcxEnc = st->hTcxEnc; nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; @@ -382,8 +391,11 @@ void TNSAnalysisStereo( /* individual decision for each channel */ for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) +#else + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { continue; } @@ -465,10 +477,15 @@ void TNSAnalysisStereo( /* we have the decision, set filter data accordingly */ for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) +#else + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { continue; } + nSubframes = ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; for ( k = 0; k < nSubframes; k++ ) @@ -501,10 +518,15 @@ void TNSAnalysisStereo( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { continue; } + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; for ( k = 0; k < nSubframes; k++ ) @@ -943,7 +965,7 @@ void EstimateStereoTCXNoiseLevel( const int16_t ignore_chan[], /* i : flag indicating whether the channel should be ignored */ float fac_ns[][NB_DIV], /* o : noise filling level */ int16_t param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */ - const int16_t is_mct /* i : is mct flag */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { int16_t ch, n; @@ -964,17 +986,18 @@ void EstimateStereoTCXNoiseLevel( { continue; } - total_brate = ( st->element_mode == IVAS_CPE_MDCT && !is_mct ) ? st->element_brate : st->total_brate; + total_brate = ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) ? st->element_brate : st->total_brate; for ( n = 0; n < nSubframes; n++ ) { fac_ns_q = param_core[ch] + n * NPRM_DIV + 1; maxNfCalcBw = min( noiseFillingBorder[ch][n], (int16_t) ( hTcxEnc->measuredBwRatio * (float) L_frame[ch][n] + 0.5f ) ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { maxNfCalcBw = min( maxNfCalcBw, MCT_LFE_MAX_LINE ); } - +#endif if ( ( total_brate >= HQ_96k && ( st->element_mode <= IVAS_SCE || st->bwidth < SWB ) ) || total_brate > IVAS_192k ) { fac_ns[ch][n] = 0.0f; @@ -2107,7 +2130,12 @@ void coder_tcx( if ( st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) { - WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX, &L_frame, win, 1, 1, 0 ); + WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX, &L_frame, win, 1, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); /* Compute MDCT for xn_buf[] */ TCX_MDCT( win, spectrum, left_overlap, L_frame - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); @@ -2116,7 +2144,12 @@ void coder_tcx( { wtda( st->hTcxEnc->new_speech_TCX, win, NULL, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, L_frame ); - WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode == ALDO_WINDOW ? FULL_OVERLAP : hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode == ALDO_WINDOW ? FULL_OVERLAP : hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX, &L_frame, winMDST, 1, 1, 0 ); + WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode == ALDO_WINDOW ? FULL_OVERLAP : hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode == ALDO_WINDOW ? FULL_OVERLAP : hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX, &L_frame, winMDST, 1, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); edct( win, spectrum, L_frame, st->element_mode ); @@ -2181,9 +2214,10 @@ void coder_tcx( *-------------------------------------------------------------------*/ void coder_tcx_post( - Encoder_State *st, - float *A, - const float *Ai ) + Encoder_State *st, /* i/o: encoder memory state */ + float *A, /* o : Quantized LPC coefficients */ + const float *Ai /* i : Unquantized (interpolated) LPC coefficients */ +) { float xn_buf[L_FRAME_MAX]; diff --git a/lib_enc/cod_uv.c b/lib_enc/cod_uv.c index 166a9685dc407bf585694b3cbb3ec9292d8a9770..2c22ed41888c8eff36115f44e10960347de4636b 100644 --- a/lib_enc/cod_uv.c +++ b/lib_enc/cod_uv.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * gauss_L2: diff --git a/lib_enc/comvad_decision.c b/lib_enc/comvad_decision.c index 4ccd0e41423097f0a0adce4702f212fe9b832b64..240f1754ba362a86053983f2b56b3e74249b35d7 100644 --- a/lib_enc/comvad_decision.c +++ b/lib_enc/comvad_decision.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include "prot.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/cor_shif.c b/lib_enc/cor_shif.c index d27b097a43b325ff8965c5f6bc343a41732c1f19..67c11d4b9030aa32b52e9d4a14da4bd87bf5bb6c 100644 --- a/lib_enc/cor_shif.c +++ b/lib_enc/cor_shif.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Correlation_shift diff --git a/lib_enc/core_enc_2div.c b/lib_enc/core_enc_2div.c index 65a5c786501be955f31e2f6ea15c0026cb5c40cd..faa7af35878234b35a4b3376964cf2453105d2e7 100644 --- a/lib_enc/core_enc_2div.c +++ b/lib_enc/core_enc_2div.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * core_encode_twodiv() diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c index 333700164acd3767d0bd4aa740ba8fcaf20e51e9..f89f4a132c0b38ba00ea4697e83dc151ab8e1970 100644 --- a/lib_enc/core_enc_init.c +++ b/lib_enc/core_enc_init.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,13 +43,13 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ -static void init_tcx( Encoder_State *st, const int16_t L_frame_old, const int32_t total_brate, const int32_t last_total_brate, const int16_t is_mct ); +static void init_tcx( Encoder_State *st, const int16_t L_frame_old, const int32_t total_brate, const int32_t last_total_brate, const int16_t MCT_flag ); static void init_sig_buffers( Encoder_State *st, const int16_t L_frame_old, const int16_t L_subfr, const int32_t total_brate, const int32_t last_total_brate ); static void init_core_sig_ana( Encoder_State *st ); static void init_acelp( Encoder_State *st, const int16_t L_frame_old, const int32_t total_brate, const int32_t last_total_brate ); @@ -62,16 +62,17 @@ static void init_modes( Encoder_State *st, const int32_t last_total_brate ); *-----------------------------------------------------------------------*/ void init_coder_ace_plus( - Encoder_State *st, - const int32_t last_total_brate, - const int16_t is_mct ) + Encoder_State *st, /* i : Encoder state */ + const int32_t last_total_brate, /* i : last total bitrate */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +) { TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; int16_t L_frame_old; /*keep old frame size for switching */ int16_t L_subfr; /* Bitrate */ - st->tcxonly = getTcxonly( st->element_mode, st->total_brate, is_mct ); + st->tcxonly = getTcxonly( st->element_mode, st->total_brate, MCT_flag ); /* Core Sampling Rate */ st->sr_core = getCoreSamplerateMode2( st->element_mode, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode ); @@ -167,7 +168,7 @@ void init_coder_ace_plus( /* Initialize TCX */ if ( hTcxEnc != NULL ) { - init_tcx( st, L_frame_old, st->total_brate, last_total_brate, is_mct ); + init_tcx( st, L_frame_old, st->total_brate, last_total_brate, MCT_flag ); } /* Initialize Signal Buffers */ @@ -252,7 +253,7 @@ static void init_tcx( const int16_t L_frame_old, const int32_t total_brate, const int32_t last_total_brate, - const int16_t is_mct ) + const int16_t MCT_flag ) { TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; @@ -260,7 +261,12 @@ static void init_tcx( hTcxEnc->spectrum[0] = hTcxEnc->spectrum_long; hTcxEnc->spectrum[1] = hTcxEnc->spectrum_long + N_TCX10_MAX; - init_tcx_cfg( st->hTcxCfg, total_brate, st->sr_core, st->input_Fs, st->L_frame, st->bwidth, hTcxEnc->L_frameTCX, st->fscale, st->encoderLookahead_enc, st->encoderLookahead_FB, st->preemph_fac, st->tcxonly, st->rf_mode, st->igf, st->hIGFEnc != NULL ? st->hIGFEnc->infoStopFrequency : 0, st->element_mode, st->ini_frame, is_mct, st->mct_chan_mode ); + init_tcx_cfg( st->hTcxCfg, total_brate, st->sr_core, st->input_Fs, st->L_frame, st->bwidth, hTcxEnc->L_frameTCX, st->fscale, st->encoderLookahead_enc, st->encoderLookahead_FB, st->preemph_fac, st->tcxonly, st->rf_mode, st->igf, st->hIGFEnc != NULL ? st->hIGFEnc->infoStopFrequency : 0, st->element_mode, st->ini_frame, MCT_flag +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); /* Init TCX target bits correction factor */ hTcxEnc->tcx_target_bits_fac = 1.0f; diff --git a/lib_enc/core_enc_ol.c b/lib_enc/core_enc_ol.c index b5fa43ae619d601c27ddd1697d3eb9665a82638c..e83fd598b49d8fefef3ea02b4602d357a8f57c8f 100644 --- a/lib_enc/core_enc_ol.c +++ b/lib_enc/core_enc_ol.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -356,8 +356,8 @@ void core_encode_openloop( if ( st->mdct_sw == MODE1 ) { - /* Account for core signalling bits difference: bandwidth and ACELP/TCX signaling bit are replaced */ - target_bits += ( FrameSizeConfig[st->frame_size_index].bandwidth_bits + 1 ) - signalling_mode1_tcx20_enc( st, 0 ); + /* Account for core signaling bits difference: bandwidth and ACELP/TCX signaling bit are replaced */ + target_bits += ( FrameSizeConfig[st->frame_size_index].bandwidth_bits + 1 ) - signaling_mode1_tcx20_enc( st, 0 ); } else if ( st->mdct_sw_enable == MODE2 ) { diff --git a/lib_enc/core_enc_reconf.c b/lib_enc/core_enc_reconf.c index 0489d210bc0bf40aa8a49eee0b391682e62bddb2..9dffda02072d3b831cdaa35a5e45063a34efe09b 100644 --- a/lib_enc/core_enc_reconf.c +++ b/lib_enc/core_enc_reconf.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Funtion core_coder_reconfig * diff --git a/lib_enc/core_enc_switch.c b/lib_enc/core_enc_switch.c index ca921357369698a6dc0ebacfb2d97d5c787a0698..806afd273bcc1ab4ad4e9cceb7f2cf8b2b60c3ee 100644 --- a/lib_enc/core_enc_switch.c +++ b/lib_enc/core_enc_switch.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * core_coder_mode_switch() @@ -50,9 +50,10 @@ *-------------------------------------------------------------------*/ void core_coder_mode_switch( - Encoder_State *st, - const int32_t last_total_brate, - const int16_t is_mct ) + Encoder_State *st, /* i/o: encoder state structure */ + const int32_t last_total_brate, /* i : last bitrate */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ +) { TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; int16_t i, fscale, switchWB; @@ -78,7 +79,7 @@ void core_coder_mode_switch( switchWB = 1; /*force init when coming from MODE1*/ } - tcxonly_tmp = getTcxonly( st->element_mode, st->total_brate, is_mct ); + tcxonly_tmp = getTcxonly( st->element_mode, st->total_brate, MCT_flag ); if ( tcxonly_tmp != st->tcxonly ) { @@ -90,11 +91,16 @@ void core_coder_mode_switch( st->sr_core = sr_core; st->L_frame = (int16_t) ( sr_core / FRAMES_PER_SEC ); - st->tcxonly = getTcxonly( st->element_mode, st->total_brate, is_mct ); + st->tcxonly = getTcxonly( st->element_mode, st->total_brate, MCT_flag ); st->bits_frame_nominal = (int16_t) ( (float) st->L_frame / (float) st->fscale * (float) FSCALE_DENOM / 128.0f * (float) st->total_brate / 100.0f + 0.49f ); - st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); /* switch IGF configuration */ if ( st->igf ) @@ -111,11 +117,16 @@ void core_coder_mode_switch( hTcxEnc->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->total_brate, st->rf_mode, st->element_mode ); st->hTcxCfg->tcxRateLoopOpt = ( st->hTcxCfg->resq && !st->tcxonly ) ? 1 : st->hTcxCfg->tcxRateLoopOpt; - st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( st->total_brate, st->igf, st->element_mode, st->mct_chan_mode ); + st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( st->total_brate, st->igf, st->element_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); if ( st->hTcxCfg->fIsTNSAllowed ) { - InitTnsConfigs( st->bwidth, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFEnc->infoStopFrequency, st->total_brate, st->element_mode, is_mct ); + InitTnsConfigs( st->bwidth, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFEnc->infoStopFrequency, st->total_brate, st->element_mode, MCT_flag ); SetAllowTnsOnWhite( st->hTcxCfg->tnsConfig, st->element_mode == IVAS_CPE_MDCT ); } @@ -150,8 +161,13 @@ void core_coder_mode_switch( } else { - st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode, st->mct_chan_mode ); - init_coder_ace_plus( st, last_total_brate, is_mct ); + st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + init_coder_ace_plus( st, last_total_brate, MCT_flag ); } if ( st->igf && st->hBWE_TD != NULL ) diff --git a/lib_enc/core_enc_updt.c b/lib_enc/core_enc_updt.c index 987910bcb54990322220cf2790aa9103a0f653f2..3d5476a894150c389f3c55107218e9d8b18ea72f 100644 --- a/lib_enc/core_enc_updt.c +++ b/lib_enc/core_enc_updt.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "rom_com.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * core_encode_update() diff --git a/lib_enc/core_switching_enc.c b/lib_enc/core_switching_enc.c index 6102bd5f6755e9bbd2a7e0e5d6b0bddd13afba4a..ad52e197b940c5a39fcbd2e3f434a0f7982e07eb 100644 --- a/lib_enc/core_switching_enc.c +++ b/lib_enc/core_switching_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * core_switching_pre_enc() @@ -401,18 +401,8 @@ void core_switching_post_enc( ( st->last_core == HQ_CORE || st->L_frame != st->last_L_frame || ( st->last_extl != SWB_TBE && st->last_extl != FB_TBE && st->last_core != TCX_20_CORE && st->last_core != TCX_10_CORE ) ) ) { set_f( st->hBWE_TD->state_ana_filt_shb, 0.0f, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); - set_f( st->hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); - set_f( st->hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); - set_f( st->hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); - st->hBWE_TD->old_mean_EnvSHBres = 0.0f; - st->hBWE_TD->prev_enr_EnvSHBres = 1.0f; - st->hBWE_TD->prev_shb_env_tilt = 0.0f; - st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; - st->hBWE_TD->prev_mix_factor = 1.0f; - st->hBWE_TD->prev_Env_error = 0.0f; - + InitSWBencBufferStates( st->hBWE_TD, NULL ); swb_tbe_reset( st->hBWE_TD->mem_csfilt, st->hBWE_TD->mem_genSHBexc_filt_down_shb, st->hBWE_TD->state_lpc_syn, st->hBWE_TD->syn_overlap, st->hBWE_TD->state_syn_shbexc, &( st->hBWE_TD->tbe_demph ), &( st->hBWE_TD->tbe_premph ), st->hBWE_TD->mem_stp_swb, &( st->hBWE_TD->gain_prec_swb ) ); - set_f( st->hBWE_TD->dec_2_over_3_mem, 0.0f, L_FILT_2OVER3 ); set_f( st->hBWE_TD->dec_2_over_3_mem_lp, 0.0f, L_FILT_2OVER3_LP ); } diff --git a/lib_enc/corr_xh.c b/lib_enc/corr_xh.c index bf4d473bdaa2259b1522fbd7d7200e3609ff5437..c317878e176ed0201c62e570eec19b115e82fd2a 100644 --- a/lib_enc/corr_xh.c +++ b/lib_enc/corr_xh.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * corr_xh() diff --git a/lib_enc/decision_matrix_enc.c b/lib_enc/decision_matrix_enc.c index 1683f8fe48f55ab15dd4dc2f7b5fb00d1c794145..9fc2bd17c9840e8671d5a472a6615596298023e5 100644 --- a/lib_enc/decision_matrix_enc.c +++ b/lib_enc/decision_matrix_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "stat_enc.h" #include "stat_dec.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* @@ -331,12 +331,12 @@ void decision_matrix_enc( } /*---------------------------------------------------------------------* - * signalling_mode1_tcx20_enc() + * signaling_mode1_tcx20_enc() * - * write MODE1 TCX20 signalling information into the bitstream + * write MODE1 TCX20 signaling information into the bitstream *---------------------------------------------------------------------*/ -int16_t signalling_mode1_tcx20_enc( +int16_t signaling_mode1_tcx20_enc( Encoder_State *st, /* i/o: encoder state structure */ const int16_t push /* i : flag to push indice */ ) @@ -352,17 +352,17 @@ int16_t signalling_mode1_tcx20_enc( /* Use ACELP signaling for LR MDCT */ if ( st->total_brate <= ACELP_16k40 ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ idx = 0; while ( acelp_sig_tbl[idx] != st->total_brate ) { idx++; } - /* retrieve the number of bits for signalling */ + /* retrieve the number of bits for signaling */ nBits = (int16_t) acelp_sig_tbl[++idx]; - /* retrieve the signalling index */ + /* retrieve the signaling index */ start_idx = ++idx; while ( acelp_sig_tbl[idx] != SIG2IND( LR_MDCT, st->bwidth, 0, 0 ) ) { @@ -429,12 +429,12 @@ int16_t signalling_mode1_tcx20_enc( /*---------------------------------------------------------------------* - * signalling_enc() + * signaling_enc() * - * write signalling information into the bitstream + * write signaling information into the bitstream *---------------------------------------------------------------------*/ -void signalling_enc( +void signaling_enc( Encoder_State *st /* i : encoder state structure */ ) { @@ -521,7 +521,7 @@ void signalling_enc( push_indice( hBstr, IND_CORE, 0, 1 ); } - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ idx = 0; while ( idx < MAX_ACELP_SIG ) { @@ -539,10 +539,10 @@ void signalling_enc( idx++; } - /* retrieve the number of bits for signalling */ + /* retrieve the number of bits for signaling */ nBits = (int16_t) acelp_sig_tbl[++idx]; - /* retrieve the signalling index */ + /* retrieve the signaling index */ start_idx = ++idx; if ( st->element_mode == IVAS_CPE_TD && st->bwidth == SWB && st->total_brate <= ACELP_9k60 ) { @@ -603,17 +603,17 @@ void signalling_enc( /* Use ACELP signaling for LR MDCT */ if ( st->total_brate <= ACELP_16k40 ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ idx = 0; while ( acelp_sig_tbl[idx] != st->total_brate ) { idx++; } - /* retrieve the number of bits for signalling */ + /* retrieve the number of bits for signaling */ nBits = (int16_t) acelp_sig_tbl[++idx]; - /* retrieve the signalling index */ + /* retrieve the signaling index */ start_idx = ++idx; while ( acelp_sig_tbl[idx] != SIG2IND( LR_MDCT, st->bwidth, 0, 0 ) ) { @@ -654,12 +654,12 @@ void signalling_enc( } /*---------------------------------------------------------------------* - * signalling_enc_rf() + * signaling_enc_rf() * - * write channel-aware signalling information into the bitstream + * write channel-aware signaling information into the bitstream *---------------------------------------------------------------------*/ -void signalling_enc_rf( +void signaling_enc_rf( Encoder_State *st /* i/o: encoder state structure */ ) { diff --git a/lib_enc/detect_transient.c b/lib_enc/detect_transient.c index 3eaddbc073a3bb9d81b029eb0182448436c06f38..0b73a12e680ad0e469d78579a0302ef418b7c37a 100644 --- a/lib_enc/detect_transient.c +++ b/lib_enc/detect_transient.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * hp_filter() diff --git a/lib_enc/diffcod.c b/lib_enc/diffcod.c index 3d0c47ca627f79cc02dcfc224540b779917f3572..fd6646c48abc263f7b7e4094798576f2b183b5b4 100644 --- a/lib_enc/diffcod.c +++ b/lib_enc/diffcod.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------*/ /* Function diffcod() */ diff --git a/lib_enc/dtx.c b/lib_enc/dtx.c index aeefb3116c3d194019639f52d24696defe7f4b09..c99a8faf286fdd9f87c0acfd9ecb2a66dcee6162 100644 --- a/lib_enc/dtx.c +++ b/lib_enc/dtx.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants @@ -63,6 +63,8 @@ #define LTE_VAR -4.0f +#define MAX_BRATE_DTX_EVS ACELP_24k40 /* maximum bitrate to which the default DTX is applied in EVS; otherwise DTX is applied only in silence */ +#define MAX_BRATE_DTX_IVAS IVAS_64k /* maximum bitrate to which the default DTX is applied in IVAS; otherwise DTX is applied only in silence */ /*-------------------------------------------------------------------* * Local function prototypes @@ -77,9 +79,10 @@ static void update_SID_cnt( DTX_ENC_HANDLE hDtxEnc, const int32_t core_brate, co *-------------------------------------------------------------------*/ void dtx( - Encoder_State *st, /* i/o: encoder state structure */ - const int16_t vad, /* i : VAD flag for DTX */ - const float speech[] /* i : Pointer to the speech frame */ + Encoder_State *st, /* i/o: encoder state structure */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t vad, /* i : VAD flag for DTX */ + const float speech[] /* i : Pointer to the speech frame */ ) { float alpha; @@ -87,7 +90,6 @@ void dtx( DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc; int16_t last_br_cng_flag, last_br_flag, br_dtx_flag; - if ( st->dtx_sce_sba != 0 ) { last_br_cng_flag = 1; @@ -96,9 +98,9 @@ void dtx( } else { - last_br_cng_flag = st->last_total_brate_cng <= ACELP_24k40 || st->lp_noise < 15 || ( ( st->element_mode == IVAS_SCE ) && st->last_total_brate_cng <= ACELP_32k ); + last_br_cng_flag = st->last_total_brate_cng <= MAX_BRATE_DTX_EVS || st->lp_noise < 15 || ( st->element_mode == IVAS_SCE && st->last_total_brate_cng <= MAX_BRATE_DTX_IVAS ); - last_br_flag = st->last_total_brate <= ACELP_24k40 || st->lp_noise < 15 || ( ( st->element_mode == IVAS_SCE ) && st->last_total_brate <= ACELP_32k ); + last_br_flag = st->last_total_brate <= MAX_BRATE_DTX_EVS || st->lp_noise < 15 || ( st->element_mode == IVAS_SCE && st->last_total_brate <= MAX_BRATE_DTX_IVAS ); br_dtx_flag = 0; } @@ -174,8 +176,9 @@ void dtx( if ( st->dtx_sce_sba == 0 ) { - br_dtx_flag = st->total_brate <= ACELP_24k40 || st->lp_noise < 15 || ( st->element_mode == IVAS_SCE && st->total_brate <= ACELP_32k ) || - st->element_mode == IVAS_CPE_DFT || ( st->element_mode == IVAS_CPE_MDCT && ( st->element_brate <= IVAS_64k || st->lp_noise < 15 ) ); + br_dtx_flag = ( st->element_mode == EVS_MONO && st->total_brate <= MAX_BRATE_DTX_EVS ) || + ( st->element_mode != EVS_MONO && ivas_total_brate <= MAX_BRATE_DTX_IVAS ) || + st->lp_noise < 15; } if ( st->Opt_DTX_ON && vad == 0 && @@ -235,7 +238,7 @@ void dtx( } else { - if ( ( st->cng_type == FD_CNG && ( st->total_brate <= ACELP_24k40 || ( st->element_mode == IVAS_SCE && st->total_brate <= ACELP_32k ) ) ) || ( st->element_mode == IVAS_CPE_MDCT ) ) /* at highest bitrates, use exclusively LP_CNG */ + if ( ( st->cng_type == FD_CNG && ( st->total_brate <= MAX_BRATE_DTX_EVS || ( st->element_mode == IVAS_SCE && ivas_total_brate <= MAX_BRATE_DTX_IVAS ) ) ) || ( st->element_mode == IVAS_CPE_MDCT ) ) /* at highest bitrates, use exclusively LP_CNG */ { if ( st->element_mode == EVS_MONO && ( st->total_brate == ACELP_9k60 || st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40 ) ) { @@ -253,7 +256,7 @@ void dtx( } } - /* reset the bitstream (IVAS format signalling was already written) */ + /* reset the bitstream (IVAS format signaling was already written) */ if ( st->element_mode != IVAS_CPE_MDCT && st->hBstr != NULL ) { reset_indices_enc( st->hBstr, MAX_NUM_INDICES ); @@ -442,7 +445,7 @@ void dtx( tmpBandwidthMin = WB; } - check_bounds_s( &( st->bwidth ), tmpBandwidthMin, FrameSizeConfig[n].bandwidth_max ); + st->bwidth = check_bounds_s( st->bwidth, tmpBandwidthMin, FrameSizeConfig[n].bandwidth_max ); } } @@ -493,7 +496,7 @@ static void update_SID_cnt( { hDtxEnc->interval_SID = INT_L + (int16_t) ( ( INT_H - INT_L ) * ( EstimatedSNR - SNR_L ) / ( SNR_H - SNR_L ) ); } - check_bounds_s( &( hDtxEnc->interval_SID ), INT_L, INT_H ); + hDtxEnc->interval_SID = check_bounds_s( hDtxEnc->interval_SID, INT_L, INT_H ); if ( !Opt_AMR_WB || hDtxEnc->max_SID != 3 ) { diff --git a/lib_enc/enc_acelp.c b/lib_enc/enc_acelp.c index 07d63fe25b653dbdca0c2c7aaa89cb399d674353..5e1401828ee47f4b0e12dd039618c975df37c6f2 100644 --- a/lib_enc/enc_acelp.c +++ b/lib_enc/enc_acelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,6 @@ ====================================================================================*/ #include -#include "typedef.h" #include #include "options.h" #ifdef DEBUGGING @@ -45,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* diff --git a/lib_enc/enc_acelp_tcx_main.c b/lib_enc/enc_acelp_tcx_main.c index e087c8cedece6912e3f641679e02ce03334455f9..5c549b23d292dd2abf57ab228e0b4b1e8463285b 100644 --- a/lib_enc/enc_acelp_tcx_main.c +++ b/lib_enc/enc_acelp_tcx_main.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * enc_acelp_tcx_main() @@ -64,7 +64,7 @@ void enc_acelp_tcx_main( float old_bwe_exc[( PIT16k_MAX + ( L_FRAME16k + 1 ) + L_SUBFR16k ) * 2]; /* excitation buffer */ float *ptr_bwe_exc; /* pointer to BWE excitation signal in the current frame */ - wmops_sub_start( "enc_acelp_tcx_main" ); + push_wmops( "enc_acelp_tcx_main" ); ptr_bwe_exc = old_bwe_exc + PIT16k_MAX * 2; @@ -129,6 +129,6 @@ void enc_acelp_tcx_main( /* coreSwitching update of Mode 1 parameters in the last frame */ st->last_coder_type = st->coder_type; - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_enc/enc_acelpx.c b/lib_enc/enc_acelpx.c index 6c8e783d76c804ee26607987079a8bde9b75be7c..c72f2fa1c340fa90d49b0d1cc2195bc3a2048f3f 100644 --- a/lib_enc/enc_acelpx.c +++ b/lib_enc/enc_acelpx.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,7 +35,6 @@ ====================================================================================*/ #include -#include "typedef.h" #include #include "options.h" #ifdef DEBUGGING @@ -43,7 +42,7 @@ #endif #include "prot.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /* Iterations: nb_pos_ix*16 */ diff --git a/lib_enc/enc_amr_wb.c b/lib_enc/enc_amr_wb.c index 2e88776d8f2e7686fd0c37275ea28dfa0fd8e5f6..bb09c0886b61dacb0d13955adab692aba4ad0d67 100644 --- a/lib_enc/enc_amr_wb.c +++ b/lib_enc/enc_amr_wb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * encod_amr_wb() diff --git a/lib_enc/enc_gain.c b/lib_enc/enc_gain.c index a5728e1f377cfee91c3e03d1704e99e2a689b87b..607c36f6e9a75843068355dfd4f8a88cecaa5abb 100644 --- a/lib_enc/enc_gain.c +++ b/lib_enc/enc_gain.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,11 +37,10 @@ #include #include #include "options.h" -#include "typedef.h" #include "prot.h" #include "rom_enc.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /* diff --git a/lib_enc/enc_gen_voic.c b/lib_enc/enc_gen_voic.c index dd642cd47035c4a7433c243a20147e1bba33b058..4c78b484c0a220df9d0afc91326e66b0e182e0fe 100644 --- a/lib_enc/enc_gen_voic.c +++ b/lib_enc/enc_gen_voic.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * encod_gen_voic() diff --git a/lib_enc/enc_gen_voic_rf.c b/lib_enc/enc_gen_voic_rf.c index e8af6856adee45d1d887ce2fd0f9fe88c6d150ae..7ceece404da285849d32cbfc147a3558881f379f 100644 --- a/lib_enc/enc_gen_voic_rf.c +++ b/lib_enc/enc_gen_voic_rf.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * reset_rf_indices() diff --git a/lib_enc/enc_higher_acelp.c b/lib_enc/enc_higher_acelp.c index ebda178d8b37f71bda0657efae99f87f73e7c8d1..5610bdfe4e9add94f1660bc404b11e07e06b868f 100644 --- a/lib_enc/enc_higher_acelp.c +++ b/lib_enc/enc_higher_acelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_enc/enc_nelp.c b/lib_enc/enc_nelp.c index 11ec6105b9b82ca923730d8349706512353e4a3e..7d828208b281e6a6f73dfcc9d180501ef239ea20 100644 --- a/lib_enc/enc_nelp.c +++ b/lib_enc/enc_nelp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * encod_nelp() diff --git a/lib_enc/enc_pit_exc.c b/lib_enc/enc_pit_exc.c index 900d4021d0632090c71580301ac6ac157d76763a..eba203b6a6ac5464268fd2ce09c7293534e5e380 100644 --- a/lib_enc/enc_pit_exc.c +++ b/lib_enc/enc_pit_exc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * enc_pit_exc() @@ -64,8 +64,8 @@ void enc_pit_exc( float *pitch_buf, /* i/o: Fractionnal per subframe pitch */ const int16_t nb_subfr, /* i : Number of subframe considered */ float *gpit, /* o : pitch mean gpit */ - const int16_t tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ - const float tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ + const int16_t tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const float tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ ) { float xn[PIT_EXC_L_SUBFR]; /* Target vector for pitch search */ diff --git a/lib_enc/enc_ppp.c b/lib_enc/enc_ppp.c index c7abd135cee978f72b9286397eb3c8c5c6f7b1fe..823d6cf3cdb244a96f0f894df172f66aafbf0b7d 100644 --- a/lib_enc/enc_ppp.c +++ b/lib_enc/enc_ppp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * encod_ppp() @@ -171,8 +171,8 @@ ivas_error encod_ppp( /* delete previous indices */ reset_indices_enc( hBstr, MAX_NUM_INDICES ); - /* signalling matrix (writing of signalling bits) */ - signalling_enc( st ); + /* signaling matrix (writing of signaling bits) */ + signaling_enc( st ); } else { diff --git a/lib_enc/enc_prm.c b/lib_enc/enc_prm.c index c48e171517be1e0770aeda097b682a784de60ecf..758d672d0b71fd6b9747c0fd580fb0a56c3764ee 100644 --- a/lib_enc/enc_prm.c +++ b/lib_enc/enc_prm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -53,12 +53,10 @@ *--------------------------------------------------------------------*/ void writeTCXMode( - Encoder_State *st, /* i/o: encoder state structure */ - BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t is_mct, -#endif - int16_t *nbits_start /* o : nbits start */ + Encoder_State *st, /* i/o: encoder state structure */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + int16_t *nbits_start /* o : nbits start */ ) { uint16_t index; @@ -88,31 +86,29 @@ void writeTCXMode( push_next_indice( hBstr, index, 2 ); -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - if ( st->element_mode == IVAS_CPE_MDCT && !is_mct ) + if ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) { push_next_indice( hBstr, st->vad_flag, 1 ); } -#endif } else { if ( st->core == ACELP_CORE ) { - /* write the RF signalling information */ + /* write the RF signaling information */ if ( st->rf_mode == 1 ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ idx = 0; while ( acelp_sig_tbl[idx] != st->total_brate ) /* total bitrate is kept at 13.2kbps */ { idx++; } - /* retrieve the number of bits for signalling */ + /* retrieve the number of bits for signaling */ nBits = (int16_t) acelp_sig_tbl[++idx]; - /* retrieve the signalling index */ + /* retrieve the signaling index */ start_idx = ++idx; while ( acelp_sig_tbl[idx] != SIG2IND( st->coder_type, st->bwidth, st->sharpFlag, st->rf_mode ) ) { @@ -144,17 +140,17 @@ void writeTCXMode( } else { - /*write the RF signalling information*/ + /*write the RF signaling information*/ if ( st->rf_mode == 1 ) { - /* find the section in the ACELP signalling table corresponding to bitrate */ + /* find the section in the ACELP signaling table corresponding to bitrate */ idx = 0; while ( acelp_sig_tbl[idx] != st->total_brate ) { idx++; } - /* retrieve the number of bits for signalling */ + /* retrieve the number of bits for signaling */ nBits = (int16_t) acelp_sig_tbl[++idx]; if ( st->hTcxCfg->coder_type == VOICED || st->hTcxCfg->coder_type == GENERIC || st->hTcxCfg->coder_type == TRANSITION ) @@ -166,7 +162,7 @@ void writeTCXMode( st->sharpFlag = 0; } - /* retrieve the signalling index */ + /* retrieve the signaling index */ start_idx = ++idx; while ( acelp_sig_tbl[idx] != SIG2IND( st->hTcxCfg->coder_type, st->bwidth, st->sharpFlag, st->rf_mode ) ) { @@ -787,16 +783,12 @@ void enc_prm( st->bits_frame_core += FrameSizeConfig[st->frame_size_index].bandwidth_bits; /* Write MODE1 core & coder_type signaling */ - signalling_mode1_tcx20_enc( st, 1 ); + signaling_mode1_tcx20_enc( st, 1 ); } /* EVS header */ /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - writeTCXMode( st, st->hBstr, 0, /* <- is_mct */ &nbits_start ); -#else - writeTCXMode( st, st->hBstr, &nbits_start ); -#endif + writeTCXMode( st, st->hBstr, 0 /* MCT_flag */, &nbits_start ); /* write last_core for error concealment */ if ( !( core == ACELP_CORE && st->hTcxCfg->lfacNext <= 0 ) ) diff --git a/lib_enc/enc_tran.c b/lib_enc/enc_tran.c index ee1768067e5aa3e54cb518f3f24069ea5cba2368..d713584fa7e9010d71159a2949014ee8d281b5dd 100644 --- a/lib_enc/enc_tran.c +++ b/lib_enc/enc_tran.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * encod_tran() diff --git a/lib_enc/enc_uv.c b/lib_enc/enc_uv.c index c34419c7dfd1a5c03294fbee08cf51af32abc70c..f6c17e410c324bc14e8f44f47ec48faa0f71a062 100644 --- a/lib_enc/enc_uv.c +++ b/lib_enc/enc_uv.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * encod_unvoiced() diff --git a/lib_enc/energy.c b/lib_enc/energy.c index e69063b873e12a99cb191eda821eb2d0a8206a87..f9cb7f6a2ef0630dde1f920d00e8dce2628d15cb 100644 --- a/lib_enc/energy.c +++ b/lib_enc/energy.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "prot.h" #include "cnst.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * background_update() diff --git a/lib_enc/eval_pit_contr.c b/lib_enc/eval_pit_contr.c index d7eb087e570da5dff87efb1d00429578c8ec2d7c..5dd310177230d29c68fe414a5eaa9db3e7ce91cd 100644 --- a/lib_enc/eval_pit_contr.c +++ b/lib_enc/eval_pit_contr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constantes diff --git a/lib_enc/evs_enc.c b/lib_enc/evs_enc.c index 060352246e83f4653f973da3635006f47a33ae5c..44c34a2bd7a6942fc17bc938d5dca44f2c95f59f 100644 --- a/lib_enc/evs_enc.c +++ b/lib_enc/evs_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -72,7 +72,6 @@ ivas_error evs_enc( float old_inp_12k8[L_INP_12k8], *inp; /* buffer of input signal @ 12k8 */ float old_inp_16k[L_INP]; /* buffer of input signal @ 16kHz */ float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ - float Etot; /* total energy; correlation shift */ float ener; /* residual energy from Levinson-Durbin */ float A[NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ float Aw[NB_SUBFR16k * ( M + 1 )]; /* weighted A(z) unquantized for subframes */ @@ -103,7 +102,7 @@ ivas_error evs_enc( error = IVAS_ERR_OK; - wmops_sub_start( "evs_enc" ); + push_wmops( "evs_enc" ); /*------------------------------------------------------------------* * Initialization *-----------------------------------------------------------------*/ @@ -163,15 +162,6 @@ ivas_error evs_enc( if ( st->last_core == AMR_WB_CORE ) { updt_IO_switch_enc( st, input_frame ); - set_f( st->hBWE_TD->old_speech_shb, 0, L_LOOK_16k + L_SUBFR16k ); - set_f( st->hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); - set_f( st->hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); - st->hBWE_TD->old_mean_EnvSHBres = 0.0f; - st->hBWE_TD->prev_enr_EnvSHBres = 1.0f; - st->hBWE_TD->prev_shb_env_tilt = 0.0f; - st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; - st->hBWE_TD->prev_mix_factor = 1.0f; - st->hBWE_TD->prev_Env_error = 0.0f; cldfb_reset_memory( st->cldfbAnaEnc ); cldfb_reset_memory( st->cldfbSynTd ); } @@ -181,12 +171,11 @@ ivas_error evs_enc( *---------------------------------------------------------------------*/ #ifdef FIX_I4_OL_PITCH - pre_proc( st, input_frame, old_inp_12k8, old_inp_16k, &inp, fr_bands, &Etot, &ener, A, Aw, epsP, lsp_new, lsp_mid, &vad_hover_flag, &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &hq_core_type ); + pre_proc( st, input_frame, old_inp_12k8, old_inp_16k, &inp, fr_bands, Etot, &ener, A, Aw, epsP, lsp_new, lsp_mid, &vad_hover_flag, &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &hq_core_type ); #else - pre_proc( st, input_frame, old_inp_12k8, old_inp_16k, &inp, fr_bands, &Etot, &ener, pitch_orig, A, Aw, epsP, lsp_new, lsp_mid, &vad_hover_flag, &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &hq_core_type ); + pre_proc( st, input_frame, old_inp_12k8, old_inp_16k, &inp, fr_bands, &ener, pitch_orig, A, Aw, epsP, lsp_new, lsp_mid, &vad_hover_flag, &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &hq_core_type ); #endif - if ( st->mdct_sw == MODE2 ) { st->bits_frame_nominal = (int16_t) ( st->total_brate / FRAMES_PER_SEC ); @@ -238,8 +227,8 @@ ivas_error evs_enc( if ( st->codec_mode == MODE1 ) { - /* write signalling info into the bitstream */ - signalling_enc( st ); + /* write signaling info into the bitstream */ + signaling_enc( st ); /*---------------------------------------------------------------------* * Preprocessing (preparing) for ACELP/HQ core switching @@ -390,7 +379,7 @@ ivas_error evs_enc( * WB TBE encoding * WB BWE encoding *---------------------------------------------------------------------*/ - wmops_sub_start( "BWE_encoding" ); + push_wmops( "BWE_encoding" ); if ( st->input_Fs >= 16000 && st->bwidth < SWB ) { @@ -426,16 +415,7 @@ ivas_error evs_enc( } else if ( st->input_Fs >= 32000 ) { - set_f( st->hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); - set_f( shb_speech, 0.0f, L_FRAME16k ); - set_f( st->hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); - set_f( st->hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); - st->hBWE_TD->old_mean_EnvSHBres = 0.0f; - st->hBWE_TD->prev_enr_EnvSHBres = 1.0f; - st->hBWE_TD->prev_shb_env_tilt = 0.0f; - st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; - st->hBWE_TD->prev_mix_factor = 1.0f; - st->hBWE_TD->prev_Env_error = 0.0f; + InitSWBencBufferStates( st->hBWE_TD, shb_speech ); } /* SWB TBE encoder */ @@ -497,19 +477,19 @@ ivas_error evs_enc( swb_CNG_enc( st, shb_speech, old_syn_12k8_16k ); } - wmops_sub_end(); + pop_wmops(); /*---------------------------------------------------------------------* * Channel-aware mode - write signaling information into the bitstream *---------------------------------------------------------------------*/ - signalling_enc_rf( st ); + signaling_enc_rf( st ); /*---------------------------------------------------------------------* * Updates *---------------------------------------------------------------------*/ - updt_enc_common( st, Etot ); + updt_enc_common( st ); if ( st->mdct_sw == MODE1 ) { @@ -565,7 +545,7 @@ ivas_error evs_enc( } #endif - wmops_sub_end(); + pop_wmops(); return error; } @@ -706,7 +686,12 @@ static void configure_core_coder( } } - st->igf = getIgfPresent( 0, st->total_brate, st->bwidth, st->rf_mode, st->mct_chan_mode ); + st->igf = getIgfPresent( 0, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); if ( st->core_brate != SID_2k40 && st->core_brate != FRAME_NO_DATA ) { diff --git a/lib_enc/ext_sig_ana.c b/lib_enc/ext_sig_ana.c index 58d1e34a5687da491394666ee4fd0fbddbc89226..0588f0ddf1638c2610c24dba5e8b954548120da0 100644 --- a/lib_enc/ext_sig_ana.c +++ b/lib_enc/ext_sig_ana.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif @@ -215,8 +215,10 @@ void core_signal_analysis_high_bitrate( if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif wtda( hTcxEnc->new_speech_TCX, tcx20Win, NULL, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX ); if ( windowed_samples != NULL ) /* store overlap data for later */ @@ -225,6 +227,7 @@ void core_signal_analysis_high_bitrate( windowed_samples[0] = (float) overlap_mode[frameno]; windowed_samples[1] = (float) overlap_mode[frameno + 1]; } +#ifndef ISSUE_24_CLEANUP_MCT_LFE } else { @@ -233,17 +236,27 @@ void core_signal_analysis_high_bitrate( st->element_mode != IVAS_CPE_MDCT /* truncate_aldo */, 1, 1 ); } - +#endif if ( st->element_mode != IVAS_CPE_MDCT ) { /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ - WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 1, 1, 0 ); + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 1, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); } } else { /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ - WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno], overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, tcx20Win, st->element_mode != IVAS_CPE_MDCT, 1, 0 ); + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno], overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, tcx20Win, st->element_mode != IVAS_CPE_MDCT, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); if ( windowed_samples != NULL ) /* save windowed speech_TCX samples */ { @@ -282,8 +295,15 @@ void core_signal_analysis_high_bitrate( for ( i = 0; i < 2; i++ ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE assert( st->mct_chan_mode != MCT_CHAN_MODE_LFE ); - WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, tcx20Win + i * tcx5SizeFB, &L_subframe, tcx5Win, st->element_mode != IVAS_CPE_MDCT, 1, 0 ); +#endif + WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, tcx20Win + i * tcx5SizeFB, &L_subframe, tcx5Win, st->element_mode != IVAS_CPE_MDCT, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); TCX_MDCT( tcx5Win, hTcxEnc->spectrum[frameno] + i * tcx5SizeFB, left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); @@ -298,7 +318,11 @@ void core_signal_analysis_high_bitrate( { assert( transform_type[frameno] == TCX_10 || transform_type[frameno] == TCX_20 ); - if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { edct( tcx20Win, hTcxEnc->spectrum[frameno], L_subframe, st->element_mode ); @@ -323,12 +347,13 @@ void core_signal_analysis_high_bitrate( { v_multc( hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes ); } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { set_f( &hTcxEnc->spectrum[frameno][MCT_LFE_MAX_LINE], 0.f, L_subframe - MCT_LFE_MAX_LINE ); st->hTcxCfg->tcx_coded_lines = MCT_LFE_MAX_LINE; } +#endif if ( st->element_mode != IVAS_CPE_MDCT ) { @@ -345,14 +370,23 @@ void core_signal_analysis_high_bitrate( { L_subframe = L_frameTCX / nSubframes; - if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { wtda_ext( hTcxEnc->new_speech_TCX, mdstWin, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX, 3 ); } else { /* Windowing for the MDST */ - WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 0, 1, st->mct_chan_mode == MCT_CHAN_MODE_LFE ); + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 0, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ); } if ( transform_type[frameno] == TCX_5 ) @@ -383,8 +417,15 @@ void core_signal_analysis_high_bitrate( for ( i = 0; i < 2; i++ ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE assert( st->mct_chan_mode != MCT_CHAN_MODE_LFE ); - WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, mdstWin + i * tcx5SizeFB, &L_subframe, tcx5Win, 0, 1, 0 ); +#endif + WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, mdstWin + i * tcx5SizeFB, &L_subframe, tcx5Win, 0, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); TCX_MDST( tcx5Win, mdst_spectrum[frameno] + i * tcx5SizeFB, left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); /* high-band gain control in case of BWS */ @@ -396,7 +437,11 @@ void core_signal_analysis_high_bitrate( } else /* transform_type[frameno] != TCX_5 */ { - if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { edst( mdstWin, mdst_spectrum[frameno], L_subframe, st->element_mode ); @@ -421,11 +466,12 @@ void core_signal_analysis_high_bitrate( v_multc( mdst_spectrum[frameno] + L_FRAME16k / nSubframes, (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, mdst_spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes ); } } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { set_f( &mdst_spectrum[frameno][MCT_LFE_MAX_LINE], 0.f, L_subframe - MCT_LFE_MAX_LINE ); } +#endif } if ( st->element_mode != IVAS_CPE_MDCT ) diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index d9e5a2014c4a6b55cf76101c20907e44337970a7..e43b65d56a88383a225e5228d77b2c06bf1d4018 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "prot.h" #include "ivas_prot.h" #include "stat_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * createFdCngEnc() @@ -66,8 +66,7 @@ ivas_error createFdCngEnc( *hFdCngEnc = NULL; /* Allocate memory */ - hs = (HANDLE_FD_CNG_ENC) count_malloc( sizeof( FD_CNG_ENC ) ); - if ( hs == NULL ) + if ( ( hs = (HANDLE_FD_CNG_ENC) malloc( sizeof( FD_CNG_ENC ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FD CNG ENC structure" ); } @@ -282,7 +281,7 @@ void deleteFdCngEnc( if ( hsEnc != NULL ) { deleteFdCngCom( &( hsEnc->hFdCngCom ) ); - count_free( hsEnc ); + free( hsEnc ); *hFdCngEnc = NULL; } @@ -709,11 +708,14 @@ void generate_comfort_noise_enc( /* Perform STFT synthesis */ SynthesisSTFT( fftBuffer, timeDomainOutput, hFdCngCom->olapBufferSynth, hFdCngCom->olapWinSyn, tcx_transition, hFdCngCom, -1, -1 ); - /* update CNG excitation energy for LP_CNG */ - /* calculate the residual signal energy */ - enr = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, hFdCngCom->exc_cng, hFdCngCom->frameSize ); + if ( st->hTdCngEnc != NULL ) + { + /* update CNG excitation energy for LP_CNG */ + /* calculate the residual signal energy */ + enr = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, hFdCngCom->exc_cng, hFdCngCom->frameSize ); - st->hTdCngEnc->lp_ener = (float) ( 0.8f * st->hTdCngEnc->lp_ener + 0.2f * pow( 2.0f, enr ) ); + st->hTdCngEnc->lp_ener = (float) ( 0.8f * st->hTdCngEnc->lp_ener + 0.2f * pow( 2.0f, enr ) ); + } /* Overlap-add when previous frame is active */ if ( st->last_core_brate > SID_2k40 && st->codec_mode == MODE2 ) @@ -902,6 +904,10 @@ void stereoFdCngCoherence( sts[0]->core_brate = SID_2k40; sts[1]->core_brate = SID_2k40; } + + /* synchronize SID counters */ + sts[0]->hDtxEnc->cnt_SID = min( sts[0]->hDtxEnc->cnt_SID, sts[1]->hDtxEnc->cnt_SID ); + sts[1]->hDtxEnc->cnt_SID = sts[0]->hDtxEnc->cnt_SID; } pt_fftL = fft_buff[0]; @@ -968,12 +974,11 @@ void FdCngEncodeMDCTStereoSID( int16_t is_inp_ms; is_inp_ms = 0; - if ( hCPE->hCoreCoder[0]->cng_spar_flag == 1 ) + if ( hCPE->hCoreCoder[0]->cng_sba_flag == 1 ) { is_inp_ms = 1; } - /* set pointers and initialize */ for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -1003,11 +1008,7 @@ void FdCngEncodeMDCTStereoSID( convertToMS( N, ms_ptr[0], ms_ptr[1], 0.5f ); } - side_energy = 0.0f; - for ( p = 0; p < N; p++ ) - { - side_energy += ms_ptr[1][p] * ms_ptr[1][p]; - } + side_energy = sum2_f( ms_ptr[1], N ); /* do not transmit side shape if initial noise shapes are very similar */ if ( side_energy <= 0.1f ) @@ -1129,6 +1130,9 @@ void FdCngEncodeMDCTStereoSID( push_indice( sts[ch]->hBstr, IND_ENERGY, gain_idx[ch], 7 ); } + /* pad with zeros to reach common SID frame size */ + push_indice( sts[1]->hBstr, IND_ENERGY, 0, ( IVAS_SID_5k2 - 4400 ) / FRAMES_PER_SEC ); + return; } @@ -1182,18 +1186,11 @@ void FdCngEncodeDiracMDCTStereoSID( /* M/S transform on log envelopes */ convertToMS( NPART, ms_ptr[0], ms_ptr[1], 0.5f ); - E[0] = 0.0f; - for ( p = 0; p < NPART; p++ ) - { - E[0] += ms_ptr[0][p]; - } + E[0] = sum_f( ms_ptr[0], NPART ); + /* Quantize M noise shape */ /* Normalize MSVW input */ - gain[0] = 0.f; - for ( p = N_GAIN_MIN; p < N_GAIN_MAX; p++ ) - { - gain[0] += ms_ptr[0][p]; - } + gain[0] = sum_f( ms_ptr[0] + N_GAIN_MIN, N_GAIN_MAX - N_GAIN_MIN ); gain[0] /= (float) ( N_GAIN_MAX - N_GAIN_MIN ); for ( p = 0; p < N[0]; p++ ) @@ -1209,11 +1206,7 @@ void FdCngEncodeDiracMDCTStereoSID( set_zero( ms_ptr[1], NPART ); /* compute M gain */ - gain[0] = 0.f; - for ( p = 0; p < NPART; p++ ) - { - gain[0] += ms_ptr[0][p]; - } + gain[0] = sum_f( ms_ptr[0], NPART ); gain[0] = ( E[0] - gain[0] ) / (float) N[0]; apply_scale( &gain[0], sts[0]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[0]->hDtxEnc->last_active_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); diff --git a/lib_enc/find_tar.c b/lib_enc/find_tar.c index b97cd8fd575444f703139ccd3b11ace049f61a9e..008fb17cb98a18b443a770d0726b92a815eda841 100644 --- a/lib_enc/find_tar.c +++ b/lib_enc/find_tar.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * find_targets() diff --git a/lib_enc/find_tilt.c b/lib_enc/find_tilt.c index 140c3b84bff77930041dfbe8a6617708aeeaee74..bdfac0569b07e2b49833e9c2f607e4ca8d30b314 100644 --- a/lib_enc/find_tilt.c +++ b/lib_enc/find_tilt.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_enc/find_uv.c b/lib_enc/find_uv.c index fcfbfaa497eec502dc1b87b0abae420d2cb54648..a80971880fbd3857c3975c5c7099e215912b2635 100644 --- a/lib_enc/find_uv.c +++ b/lib_enc/find_uv.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/find_wsp.c b/lib_enc/find_wsp.c index d2e2575b521ee2d71ae401c1ff196e387104072b..e08918a4de10e9e9d9f25d965e6552c75f0382bc 100644 --- a/lib_enc/find_wsp.c +++ b/lib_enc/find_wsp.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * find_wsp() diff --git a/lib_enc/frame_spec_dif_cor_rate.c b/lib_enc/frame_spec_dif_cor_rate.c index 1922964416dd473cf9a73f1d68a1ec71fb82beb4..b0ececfb38628c38ab0835e13a7ef35866ce14f7 100644 --- a/lib_enc/frame_spec_dif_cor_rate.c +++ b/lib_enc/frame_spec_dif_cor_rate.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * frame_spec_dif_cor_rate() @@ -82,7 +82,6 @@ void frame_spec_dif_cor_rate( /* 1073741.824 = 0.001 * 32768 * 32768 */ spec_low_dif_cor_rate = (float) ( m / sqrt( ( dx * dy + 1073741.824f ) ) ); - spec_dif_cor_rate = spec_low_dif_cor_rate; f_tonality_rate[0] = spec_dif_cor_rate; f_tonality_rate[1] = f_tonality_rate[1] * 0.96f + spec_dif_cor_rate * 0.04f; diff --git a/lib_enc/gain_enc.c b/lib_enc/gain_enc.c index 41389a6edba51c4cfb0f3d279021b1f48658fa8d..4883ea77b4129e77f1aca399ef458e8201c45741 100644 --- a/lib_enc/gain_enc.c +++ b/lib_enc/gain_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/gaus_enc.c b/lib_enc/gaus_enc.c index 080f12f707d5dcc422ab77a47d7b6721e95edd93..79b480e5161a0719f12d8d7ea4ce5c1b0e8966a1 100644 --- a/lib_enc/gaus_enc.c +++ b/lib_enc/gaus_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/gp_clip.c b/lib_enc/gp_clip.c index 036fcd2bf7bf75cd2a20297580afe59a1176bcf4..43394c2bf58b3246402d851a9aa08c709cdb13e3 100644 --- a/lib_enc/gp_clip.c +++ b/lib_enc/gp_clip.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/gs_enc.c b/lib_enc/gs_enc.c index cfee14b2ca1815cc8754c34908a3908b55465718..25f1f8fc762f3e985936a75585ddc0ab8b69a84a 100644 --- a/lib_enc/gs_enc.c +++ b/lib_enc/gs_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -97,7 +97,6 @@ void encod_audio( hGSCEnc = st->hGSCEnc; m_mean = 0.0f; - tmp_nb_bits_tot = 0; T0_tmp = 64; T0_frac_tmp = 0; diff --git a/lib_enc/guided_plc_enc.c b/lib_enc/guided_plc_enc.c index 28dd46c5448203906329e92344b7c81674cc1b9a..cb5e84683d5aa3163c1ddb7df3b609887b308d20 100644 --- a/lib_enc/guided_plc_enc.c +++ b/lib_enc/guided_plc_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "prot.h" #include "stat_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * coderLookAheadInnovation() diff --git a/lib_enc/hf_cod_amrwb.c b/lib_enc/hf_cod_amrwb.c index e731e13da959e2302681868191c0dbb9ff2fd4f3..c9cbba3cd472f8e96075cd6e0d14aa379eaeefa1 100644 --- a/lib_enc/hf_cod_amrwb.c +++ b/lib_enc/hf_cod_amrwb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes diff --git a/lib_enc/hq_classifier_enc.c b/lib_enc/hq_classifier_enc.c index 895f7ac2e0f5fdf8d2d62210cb4b22cd1b0fe11e..a8d798e65713e126a39dd65770b99ccf94d52535 100644 --- a/lib_enc/hq_classifier_enc.c +++ b/lib_enc/hq_classifier_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants @@ -128,10 +128,10 @@ int16_t hq_classifier_enc( } else if ( length == L_SPEC16k_EXT || length == L_SPEC48k_EXT ) { - bits = 0; /* HQ_NORMAL only -- no signalling needed */ + bits = 0; /* HQ_NORMAL only -- no signaling needed */ } - /* write signalling info to the bitstream */ + /* write signaling info to the bitstream */ push_indice( st->hBstr, IND_HQ_SWB_CLAS, *hqswb_clas, bits ); if ( st->core_brate <= HQ_32k && *hqswb_clas == HQ_NORMAL ) diff --git a/lib_enc/hq_core_enc.c b/lib_enc/hq_core_enc.c index 250d36c5a4c9d24d8c7f7ecb1ffbef419dd799b2..43b5ebd68c7c377da7346e7ae6196ef414453108 100644 --- a/lib_enc/hq_core_enc.c +++ b/lib_enc/hq_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * hq_core_enc() @@ -72,7 +72,7 @@ void hq_core_enc( BSTR_ENC_HANDLE hBstr = st->hBstr; - wmops_sub_start( "hq_core_enc" ); + push_wmops( "hq_core_enc" ); set_f( t_audio, 0, L_FRAME48k ); st->Nb_ACELP_frames = 0; @@ -94,7 +94,7 @@ void hq_core_enc( /*-------------------------------------------------------------------------- * Preprocessing in the first HQ frame after ACELP frame * Find the number of bits for PVQ coding - * Write signalling information + * Write signaling information *--------------------------------------------------------------------------*/ num_bits = (int16_t) ( st->total_brate / FRAMES_PER_SEC ); @@ -116,7 +116,12 @@ void hq_core_enc( left_overlap = -1; right_overlap = -1; - WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, TRANSITION_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX, &L_spec, wtda_audio, 1, 1, 0 ); + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, TRANSITION_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX, &L_spec, wtda_audio, 1, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); TCX_MDCT( wtda_audio, t_audio, left_overlap, L_spec - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); @@ -177,7 +182,7 @@ void hq_core_enc( } } - /* subtract signalling bits */ + /* subtract signaling bits */ num_bits -= hBstr->nb_bits_tot; /*-------------------------------------------------------------------------- @@ -289,7 +294,7 @@ void hq_core_enc( mvr2r( output, st->hLPDmem->old_exc, L_FRAME16k ); } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_enc/hq_env_enc.c b/lib_enc/hq_env_enc.c index 0ddfc2cb0ef43cb518a307666c1a91c7fd278687..4d57dde16475b0e99e55c941ad181c891e474b5f 100644 --- a/lib_enc/hq_env_enc.c +++ b/lib_enc/hq_env_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------------------* * encode_envelope_indices() diff --git a/lib_enc/hq_hr_enc.c b/lib_enc/hq_hr_enc.c index 569d616066fd257a209f85da4b428f3f4b804439..d815295a4df1246a9609dce1976cab538a173ddc 100644 --- a/lib_enc/hq_hr_enc.c +++ b/lib_enc/hq_hr_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_enc.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hq_hr_enc() diff --git a/lib_enc/hq_lr_enc.c b/lib_enc/hq_lr_enc.c index 184dc79e6b8094d21d1fe347b66ddbf4cb7ec0b4..e43baef59d23cc060f93c77123aca1117e194a97 100644 --- a/lib_enc/hq_lr_enc.c +++ b/lib_enc/hq_lr_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "prot.h" #include "stl.h" #include "basop_util.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* @@ -320,13 +320,13 @@ void hq_lr_enc( if ( flag_spt == 1 ) { - /* initalize the desired parameters for SPT */ + /* initialize the desired parameters for SPT */ spt_shorten_domain_band_save( bands, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width ); spt_shorten_domain_pre( band_start, band_end, hHQ_core->prev_SWB_peak_pos, bands, bwe_br, new_band_start, new_band_end, new_band_width ); spt_shorten_domain_set( hBstr, hHQ_core, t_audio, p2a_flags, new_band_start, new_band_end, new_band_width, bands, band_start, band_end, band_width, &bit_budget ); } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* Estimate number of bits per band */ Q_band_energy = SWB_BWE_LR_Qbe; FOR( i = 0; i < bands; i++ ) @@ -368,11 +368,11 @@ void hq_lr_enc( move32(); /*Q(31-exp2) */ Ep_tmp_fx[i] = L_shr( L_tmp, sub( 15, exp2 ) ); /*Q13 */ } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP if ( is_transient == 0 && inner_frame == L_FRAME8k && st->core_brate <= ACELP_13k20 ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP lowband = 6; move16(); trans_bit = 2; @@ -640,7 +640,7 @@ void hq_lr_enc( L_band_energy_tmp[i] = L_shl( L_tmp, 1 ); /*Q_band_energy */ } } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP for ( i = 0; i < bands; i++ ) { @@ -657,7 +657,7 @@ void hq_lr_enc( } else if ( is_transient == 0 && inner_frame == L_FRAME16k ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP bit_budget = sub( bit_budget, 2 ); /* bits in high bands to indicate the last 2 subbands is allocated bits or not */ FOR( i = 0; i < bands; i++ ) { @@ -909,7 +909,7 @@ void hq_lr_enc( L_band_energy_tmp[i] = L_shl( L_tmp, 1 ); /*Q_band_energy */ } } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP for ( i = 0; i < bands; i++ ) { @@ -1510,7 +1510,7 @@ static float band_energy_quant( for ( k = 0; k < bands; k++ ) L_band_energy[k] = (Word32) ( band_energy[k] * pow( 2.0f, SWB_BWE_LR_Qbe ) ); -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP exp_normd = norm_l( L_qint ); div_s( &rev_qint_fx, 0x4000, round_fx( L_shl( L_qint, exp_normd ) ) ); /* Q14-(29+exp_normd-16)+15 */ Qrev_qint = sub( 14 - ( 29 - 16 ) + 15, exp_normd ); @@ -1522,7 +1522,7 @@ static float band_energy_quant( L_tmp = L_mls( L_band_energy[k], rev_qint_fx ); /* Q14+Qrev_qint-15 */ bq1[k] = round_fx( L_shl( L_tmp, sub( 17, Qrev_qint ) ) ); /* 16-(14+Qrev_qint-15) */ } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP if ( is_transient ) { @@ -1604,10 +1604,10 @@ static float band_energy_quant( for ( k = 0; k < bands; k++ ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP L_band_energy[k] = L_mls( L_qint, (Word16) bq1[k] ); move32(); /* 29+0-15 -> Qbe(Q14) */ -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP band_energy[k] = (float) ( L_band_energy[k] / pow( 2.0f, SWB_BWE_LR_Qbe ) ); } @@ -1708,7 +1708,7 @@ static void mdct_spectrum_fine_gain_enc( Word16 Qgt; Word16 temp_lo_fx, temp_hi_fx; -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP /* Fine gain quantization on only the most significant energy bands */ /*delta = qint / gqlevs; */ exp_normn = norm_l( L_qint ); @@ -1733,7 +1733,7 @@ static void mdct_spectrum_fine_gain_enc( gain_table_fx[i] = shl( gain_table_fx[i], sub( 14, Qgt ) ); /* Qgt -> Q14 */ gain_table[i] = (float) ( gain_table_fx[i] / pow( 2.0f, 14 ) ); } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP for ( k = bands - Ngq; k < bands; k++ ) { diff --git a/lib_enc/hvq_enc.c b/lib_enc/hvq_enc.c index d82de6f5f394c6b55fba891ba02d217b12b49e08..42ac52cc3c56533b0b026a6dc38421271ad97189 100644 --- a/lib_enc/hvq_enc.c +++ b/lib_enc/hvq_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_enc.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * hvq_enc() diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 2cf98207bbde4d3698ef5c3ab6230aebc35d704e..9c68e3fcc760981ad66e0da3ec77b7ebd427ce18 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "ivas_prot.h" #include "cnst.h" #include "stat_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif @@ -1852,13 +1852,13 @@ void IGFEncApplyStereo( const IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS], /* i : instance handle of IGF Encoder */ const int16_t igfGridIdx, /* i : IGF grid index */ Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ - float pPowerSpectrum[CPE_CHANNELS][N_MAX], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ float *pPowerSpectrumMsInv[CPE_CHANNELS][2], /* i/o: inverse power spectrum */ float *inv_spectrum[CPE_CHANNELS][2], /* i : inverse spectrum */ const int16_t frameno, /* i : flag indicating index of current subfr. */ const int16_t sp_aud_decision0, /* i : sp_aud_decision0 */ const int32_t element_brate, /* i : element bitrate */ - const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ + const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ ) { float *pPowerSpectrumParameter[2]; /* If it is NULL it informs a function that specific handling is needed */ diff --git a/lib_enc/igf_scf_enc.c b/lib_enc/igf_scf_enc.c index b1a3842b8f4b534d0891a9352144cdb15969b8d3..f893a8b315d3f193d09b62c10f8f7c7ec029a0c4 100644 --- a/lib_enc/igf_scf_enc.c +++ b/lib_enc/igf_scf_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "stat_enc.h" #include "stat_com.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c index 9d355b83707b96b839a277393d294ff383517f83..d73434c15f54a1c9675d2b7e6d8b307ae8ee8225 100644 --- a/lib_enc/init_enc.c +++ b/lib_enc/init_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #include "prot.h" #include "ivas_prot.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * init_encoder() @@ -58,7 +58,8 @@ ivas_error init_encoder( const int16_t idchan, /* i : channel ID */ const int16_t var_SID_rate_flag, /* i : flag for variable SID update rate */ const int16_t interval_SID, /* i : interval for SID update */ - const int16_t vad_only_flag /* i : flag to indicate front-VAD structure */ + const int16_t vad_only_flag, /* i : flag to indicate front-VAD structure */ + const ISM_MODE ism_mode /* i : ISM mode */ ) { int16_t i; @@ -107,7 +108,7 @@ ivas_error init_encoder( if ( !vad_only_flag ) { - if ( ( st->hBstr = (BSTR_ENC_HANDLE) count_malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) + if ( ( st->hBstr = (BSTR_ENC_HANDLE) malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Bitstream structure\n" ) ); } @@ -256,7 +257,7 @@ ivas_error init_encoder( if ( !vad_only_flag ) { - if ( ( st->hSignalBuf = (SIGNAL_BUFFERS_ENC_HANDLE) count_malloc( sizeof( SIGNAL_BUFFERS_ENC_DATA ) ) ) == NULL ) + if ( ( st->hSignalBuf = (SIGNAL_BUFFERS_ENC_HANDLE) malloc( sizeof( SIGNAL_BUFFERS_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Signal buffers\n" ) ); } @@ -311,7 +312,7 @@ ivas_error init_encoder( if ( idchan == 0 || st->element_mode == IVAS_CPE_TD || st->element_mode == IVAS_CPE_MDCT || st->element_mode == EVS_MONO ) { - if ( ( st->hNoiseEst = (NOISE_EST_HANDLE) count_malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) + if ( ( st->hNoiseEst = (NOISE_EST_HANDLE) malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ); } @@ -332,7 +333,7 @@ ivas_error init_encoder( if ( ( idchan == 0 || st->element_mode == IVAS_CPE_TD || st->element_mode == IVAS_CPE_MDCT || st->element_mode == EVS_MONO ) && ( !vad_only_flag ) ) { - if ( ( st->hVAD = (VAD_HANDLE) count_malloc( sizeof( VAD_DATA ) ) ) == NULL ) + if ( ( st->hVAD = (VAD_HANDLE) malloc( sizeof( VAD_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n" ) ); } @@ -348,7 +349,7 @@ ivas_error init_encoder( /* CLDFB-based VAD */ if ( st->element_mode == EVS_MONO ) { - if ( ( st->hVAD_CLDFB = (VAD_CLDFB_HANDLE) count_malloc( sizeof( T_CldfbVadState ) ) ) == NULL ) + if ( ( st->hVAD_CLDFB = (VAD_CLDFB_HANDLE) malloc( sizeof( T_CldfbVadState ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB VAD\n" ) ); } @@ -366,7 +367,7 @@ ivas_error init_encoder( if ( idchan == 0 || st->element_mode == IVAS_CPE_TD || st->element_mode == IVAS_CPE_MDCT || st->element_mode == EVS_MONO ) { - if ( ( st->hSpMusClas = (SP_MUS_CLAS_HANDLE) count_malloc( sizeof( SP_MUS_CLAS_DATA ) ) ) == NULL ) + if ( ( st->hSpMusClas = (SP_MUS_CLAS_HANDLE) malloc( sizeof( SP_MUS_CLAS_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Speech/music classifier\n" ) ); } @@ -414,7 +415,7 @@ ivas_error init_encoder( if ( ( ( idchan == 0 && st->Opt_DTX_ON ) || st->element_mode == EVS_MONO ) || ( st->element_mode == IVAS_CPE_MDCT && st->Opt_DTX_ON ) ) { - if ( ( st->hDtxEnc = (DTX_ENC_HANDLE) count_malloc( sizeof( DTX_ENC_DATA ) ) ) == NULL ) + if ( ( st->hDtxEnc = (DTX_ENC_HANDLE) malloc( sizeof( DTX_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX variables\n" ) ); } @@ -462,9 +463,13 @@ ivas_error init_encoder( * LP-CNG *-----------------------------------------------------------------*/ - if ( ( ( idchan == 0 && st->Opt_DTX_ON && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == EVS_MONO ) ) +#ifdef DISCRETE_ISM_DTX_CNG + if ( ( ( idchan == 0 && st->Opt_DTX_ON && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == EVS_MONO ) && !( ism_mode == ISM_MODE_PARAM || ism_mode == ISM_MODE_DISC ) ) +#else + if ( ( ( idchan == 0 && st->Opt_DTX_ON && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == EVS_MONO ) && !( ism_mode == ISM_MODE_PARAM ) ) +#endif { - if ( ( st->hTdCngEnc = (TD_CNG_ENC_HANDLE) count_malloc( sizeof( TD_CNG_ENC_DATA ) ) ) == NULL ) + if ( ( st->hTdCngEnc = (TD_CNG_ENC_HANDLE) malloc( sizeof( TD_CNG_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n" ) ); } @@ -500,7 +505,7 @@ ivas_error init_encoder( if ( st->Opt_SC_VBR || st->element_mode == EVS_MONO ) { - if ( ( st->hSC_VBR = (SC_VBR_ENC_HANDLE) count_malloc( sizeof( SC_VBR_ENC_DATA ) ) ) == NULL ) + if ( ( st->hSC_VBR = (SC_VBR_ENC_HANDLE) malloc( sizeof( SC_VBR_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SC-VBR\n" ) ); } @@ -521,7 +526,7 @@ ivas_error init_encoder( if ( st->Opt_AMR_WB || st->element_mode == EVS_MONO ) { - if ( ( st->hAmrwb_IO = (AMRWB_IO_ENC_HANDLE) count_malloc( sizeof( AMRWB_IO_ENC_DATA ) ) ) == NULL ) + if ( ( st->hAmrwb_IO = (AMRWB_IO_ENC_HANDLE) malloc( sizeof( AMRWB_IO_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for AMR-WB IO\n" ) ); } @@ -539,7 +544,7 @@ ivas_error init_encoder( if ( ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == IVAS_CPE_TD ) { - if ( ( st->hLPDmem = (LPD_state_HANDLE) count_malloc( sizeof( LPD_state ) ) ) == NULL ) + if ( ( st->hLPDmem = (LPD_state_HANDLE) malloc( sizeof( LPD_state ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LPDmem\n" ) ); } @@ -560,7 +565,7 @@ ivas_error init_encoder( if ( ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) || st->element_mode == IVAS_CPE_TD ) { - if ( ( st->hGSCEnc = (GSC_ENC_HANDLE) count_malloc( sizeof( GSC_ENC_DATA ) ) ) == NULL ) + if ( ( st->hGSCEnc = (GSC_ENC_HANDLE) malloc( sizeof( GSC_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for GSC\n" ) ); } @@ -578,7 +583,7 @@ ivas_error init_encoder( if ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) { - if ( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) count_malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); } @@ -603,7 +608,7 @@ ivas_error init_encoder( if ( idchan == 0 && st->element_mode != IVAS_CPE_MDCT ) { - if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) count_malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); } @@ -621,7 +626,7 @@ ivas_error init_encoder( if ( st->element_mode != IVAS_CPE_TD && st->element_mode != IVAS_CPE_MDCT && idchan == 0 ) { - if ( ( st->hHQ_core = (HQ_ENC_HANDLE) count_malloc( sizeof( HQ_ENC_DATA ) ) ) == NULL ) + if ( ( st->hHQ_core = (HQ_ENC_HANDLE) malloc( sizeof( HQ_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ core\n" ) ); } @@ -646,13 +651,6 @@ ivas_error init_encoder( if ( !st->Opt_RF_ON || ( st->bwidth != WB && st->bwidth != SWB ) || st->total_brate != ACELP_13k20 ) { - if ( st->Opt_RF_ON ) - { // VE: this should be printed outside of library - printf( "\nWarning: Channel-aware mode only available for 13.2 kbps WB/SWB\n" ); - printf( " Switched to normal mode!\n" ); - st->Opt_RF_ON = 0; - st->rf_fec_offset = 0; - } st->rf_mode = 0; } else @@ -664,7 +662,7 @@ ivas_error init_encoder( if ( st->Opt_RF_ON || st->element_mode == EVS_MONO ) { - if ( ( st->hRF = (RF_ENC_HANDLE) count_malloc( sizeof( RF_ENC_DATA ) ) ) == NULL ) + if ( ( st->hRF = (RF_ENC_HANDLE) malloc( sizeof( RF_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for RF\n" ) ); } @@ -683,7 +681,7 @@ ivas_error init_encoder( if ( st->element_mode == EVS_MONO ) { - if ( ( st->hTECEnc = (TEC_ENC_HANDLE) count_malloc( sizeof( TEC_ENC_DATA ) ) ) == NULL ) + if ( ( st->hTECEnc = (TEC_ENC_HANDLE) malloc( sizeof( TEC_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TEC\n" ) ); } @@ -701,7 +699,7 @@ ivas_error init_encoder( // VE: reduction possible for MCT_CHAN_MODE_LFE channel - see I1-172 if ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) { - if ( ( st->hTcxEnc = (TCX_ENC_HANDLE) count_malloc( sizeof( TCX_ENC_DATA ) ) ) == NULL ) + if ( ( st->hTcxEnc = (TCX_ENC_HANDLE) malloc( sizeof( TCX_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxEnc\n" ) ); } @@ -718,7 +716,7 @@ ivas_error init_encoder( /* MDCT classifier */ MDCT_classifier_reset( st->hTcxEnc ); - if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) count_malloc( sizeof( TCX_config ) ) ) == NULL ) + if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxCfg\n" ) ); } @@ -733,9 +731,13 @@ ivas_error init_encoder( * IGF *-----------------------------------------------------------------*/ - if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( ( idchan == 0 || st->element_mode == IVAS_CPE_MDCT ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { - if ( ( st->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) count_malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) + if ( ( st->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n" ) ); } @@ -753,7 +755,12 @@ ivas_error init_encoder( if ( st->codec_mode == MODE2 || st->element_mode > EVS_MONO ) { - st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); } else { @@ -763,7 +770,7 @@ ivas_error init_encoder( /* PLC encoder */ if ( st->element_mode == EVS_MONO ) { - if ( ( st->hPlcExt = (PLC_ENC_EVS_HANDLE) count_malloc( sizeof( PLC_ENC_EVS ) ) ) == NULL ) + if ( ( st->hPlcExt = (PLC_ENC_EVS_HANDLE) malloc( sizeof( PLC_ENC_EVS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hPlcExt\n" ) ); } @@ -792,7 +799,12 @@ ivas_error init_encoder( } initFdCngEnc( st->hFdCngEnc, st->input_Fs, st->cldfbAnaEnc->scale ); - configureFdCngEnc( st->hFdCngEnc, st->bwidth, st->rf_mode && st->total_brate == ACELP_13k20 ? ACELP_9k60 : st->total_brate ); + + /* initialization for IVAS modes happens in first frame pre-processing */ + if ( st->element_mode == EVS_MONO ) + { + configureFdCngEnc( st->hFdCngEnc, st->bwidth, st->rf_mode && st->total_brate == ACELP_13k20 ? ACELP_9k60 : st->total_brate ); + } } else { @@ -802,10 +814,11 @@ ivas_error init_encoder( /*-----------------------------------------------------------------* * Transient detector *-----------------------------------------------------------------*/ - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE ) { - if ( ( st->hTranDet = (TRAN_DET_HANDLE) count_malloc( sizeof( TRAN_DET_DATA ) ) ) == NULL ) +#endif + if ( ( st->hTranDet = (TRAN_DET_HANDLE) malloc( sizeof( TRAN_DET_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Transient Detection\n" ) ); } @@ -818,19 +831,20 @@ ivas_error init_encoder( { InitTransientDetection( (int16_t) ( st->input_Fs / FRAMES_PER_SEC ), NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), st->hTranDet, 0 ); } +#ifndef ISSUE_24_CLEANUP_MCT_LFE } else { st->hTranDet = NULL; } +#endif /*-----------------------------------------------------------------* * IVAS parameters *-----------------------------------------------------------------*/ st->tdm_LRTD_flag = 0; - st->cng_dirac_flag = 0; - st->cng_spar_flag = 0; + st->cng_sba_flag = 0; st->bits_frame_channel = 0; st->side_bits_frame_channel = 0; @@ -864,32 +878,22 @@ void LPDmem_enc_init( return; } + + /*-----------------------------------------------------------------------* - * destroy_encoder() + * destroy_cldfb_encoder() * * Free memory which was allocated in init_encoder() *-----------------------------------------------------------------------*/ -void destroy_encoder( +void destroy_cldfb_encoder( Encoder_State *st /* i/o: Encoder static variables structure */ ) { - if ( st->cldfbSynTd != NULL ) - { - deleteCldfb( &st->cldfbSynTd ); - } - - if ( st->cldfbAnaEnc != NULL ) - { - deleteCldfb( &st->cldfbAnaEnc ); - } - - if ( st->hFdCngEnc != NULL ) - { - deleteFdCngEnc( &st->hFdCngEnc ); - } + deleteCldfb( &st->cldfbSynTd ); + deleteCldfb( &st->cldfbAnaEnc ); - /* Close Core */ + deleteFdCngEnc( &st->hFdCngEnc ); return; } diff --git a/lib_enc/inov_enc.c b/lib_enc/inov_enc.c index c80057f0551d0629adf17ca5c635f445c4fb073e..fedc98e103c2d67a90e3f5567d7ca4712d144b90 100644 --- a/lib_enc/inov_enc.c +++ b/lib_enc/inov_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "ivas_prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * inov_encode() diff --git a/lib_enc/isf_enc_amr_wb.c b/lib_enc/isf_enc_amr_wb.c index 441c66be9bf459f34d565c848cc62945c1022a30..c10ee6288b030dc738eb341571d36dd3111ed839 100644 --- a/lib_enc/isf_enc_amr_wb.c +++ b/lib_enc/isf_enc_amr_wb.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants diff --git a/lib_enc/ivas_agc_enc.c b/lib_enc/ivas_agc_enc.c index d001f8f48485860a46a4d2e04d988d59f6bf6353..83dbdad1e183efb3bb5990657633b3c68323b389 100644 --- a/lib_enc/ivas_agc_enc.c +++ b/lib_enc/ivas_agc_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "prot.h" #include #include -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -56,10 +56,39 @@ #ifdef DEBUG_AGC extern FILE *agcOut; -static int16_t ivas_agc_writeBits( FILE *stream, ivas_agc_enc_in_buf_t *in_buf, ivas_agc_enc_state_t *pState ); +static int16_t ivas_agc_writeBits( FILE *stream, const int16_t n_channels, ivas_agc_enc_state_t *pState ); #endif +/*-----------------------------------------------------------------------------------------* + * Function ivas_agc_enc_get_flag() + * + * This function determines if AGC is enabled or disabled. + *-----------------------------------------------------------------------------------------*/ + +/*! r: AGC enable flag */ +int16_t ivas_agc_enc_get_flag( +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + int16_t agc_configuration, /* i : AGC configuration from command-line */ +#endif + int16_t nchan_transport /* i : number of transport channels */ +) +{ + int16_t agc_flag; + + /* AGC is enabled only if there is one transport channel. */ + agc_flag = (int16_t) ( nchan_transport == 1 ); + +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + /* If agc_configuration is not undefined, then this value decides on the state of * enablement, + otherwise AGC is enabled only if there is one transport channel. */ + agc_flag = ( agc_configuration != SBA_AGC_DEFAULT ) ? agc_configuration : agc_flag; +#endif + + return agc_flag; +} + + /*-----------------------------------------------------------------------------------------* * Function ivas_agc_enc_init() * @@ -101,13 +130,13 @@ static void ivas_agc_enc_init( /* gain_data */ ptr->absGainExp = hAgcEnc->agc_com.absEmin; ptr->absGainExpCurr = hAgcEnc->agc_com.absEmin; - ptr->gainException = FALSE; ptr++; } return; } + /*------------------------------------------------------------------------- * ivas_spar_agc_enc_open() * @@ -121,37 +150,39 @@ ivas_error ivas_spar_agc_enc_open( ) { ivas_agc_enc_state_t *hAgc; - int16_t input_frame; + int16_t input_frame, delay; - if ( ( hAgc = (ivas_agc_enc_state_t *) count_malloc( sizeof( ivas_agc_enc_state_t ) ) ) == NULL ) + if ( ( hAgc = (ivas_agc_enc_state_t *) malloc( sizeof( ivas_agc_enc_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" ); } input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); + delay = NS2SA( input_Fs, ( IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ) ); - if ( ( hAgc->agc_com.winFunc = (float *) count_malloc( sizeof( float ) * input_frame ) ) == NULL ) + if ( ( hAgc->agc_com.winFunc = (float *) malloc( sizeof( float ) * ( input_frame - delay ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" ); } - if ( ( hAgc->gain_state = (ivas_agc_enc_chan_state_t *) count_malloc( sizeof( ivas_agc_enc_chan_state_t ) * nchan_inp ) ) == NULL ) + if ( ( hAgc->gain_state = (ivas_agc_enc_chan_state_t *) malloc( sizeof( ivas_agc_enc_chan_state_t ) * nchan_inp ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" ); } - if ( ( hAgc->gain_data = (ivas_agc_chan_data_t *) count_malloc( sizeof( ivas_agc_chan_data_t ) * nchan_inp ) ) == NULL ) + if ( ( hAgc->gain_data = (ivas_agc_chan_data_t *) malloc( sizeof( ivas_agc_chan_data_t ) * nchan_inp ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" ); } - ivas_agc_enc_init( hAgc, input_frame, nchan_inp, NS2SA( input_Fs, ( IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ) ) ); + ivas_agc_enc_init( hAgc, input_frame, nchan_inp, delay ); *hAgcEnc = hAgc; return IVAS_ERR_OK; } + /*------------------------------------------------------------------------- * ivas_spar_agc_enc_close() * @@ -164,26 +195,29 @@ void ivas_spar_agc_enc_close( { ivas_agc_enc_state_t *hAgc; + if ( hAgcEnc == NULL || *hAgcEnc == NULL ) + { + return; + } + hAgc = *hAgcEnc; - if ( hAgc != NULL ) - { - count_free( hAgc->agc_com.winFunc ); - hAgc->agc_com.winFunc = NULL; + free( hAgc->agc_com.winFunc ); + hAgc->agc_com.winFunc = NULL; - count_free( hAgc->gain_state ); - hAgc->gain_state = NULL; + free( hAgc->gain_state ); + hAgc->gain_state = NULL; - count_free( hAgc->gain_data ); - hAgc->gain_data = NULL; + free( hAgc->gain_data ); + hAgc->gain_data = NULL; - count_free( hAgc ); - hAgc = NULL; - } + free( *hAgcEnc ); + *hAgcEnc = NULL; return; } + /*-----------------------------------------------------------------------------------------* * Function ivas_agc_enc_process() * @@ -215,7 +249,7 @@ void ivas_agc_enc_process( { float sampleAbsVal; int16_t isClipped = FALSE; - int16_t clippedIdx = offset - 1; + int16_t clippedIdx = 0; int16_t MaxAbsValIdx = 0; float MaxAbsVal = pState->gain_state[i].MaxAbsVal_del; float predMaxAbsVal = fabsf( ppPcm_in[i][offset] ); @@ -242,27 +276,19 @@ void ivas_agc_enc_process( if ( !isClipped ) { - if ( ( ppPcm_out[i][j] > ( 1.f - pState->minDelta ) ) || ( ppPcm_out[i][j] < -1.f ) ) + if ( ( ppPcm_out[i][j] > ( 1.f - pState->minDelta ) * PCM16_TO_FLT_FAC ) || ( ppPcm_out[i][j] < MIN16B_FLT ) ) { - if ( j < offset ) - { - clippedIdx = j; - } + clippedIdx = j; isClipped = TRUE; } } } - if ( MaxAbsValIdx >= offset ) - { - MaxAbsValIdx = offset - 1; - } pState->gain_state[i].MaxAbsVal_del = predMaxAbsVal; isGainAdjusted = FALSE; if ( !isClipped ) { - pState->gain_data[i].gainException = FALSE; if ( pState->gain_state[i].lastExp == AGC_EMAX || MaxAbsVal < FLT_MIN ) { @@ -278,7 +304,7 @@ void ivas_agc_enc_process( maxGain = max( smoothedMaxAbsVal, MaxAbsVal ) * pState->gain_state[i].lastGain * 2.f; - if ( maxGain < 1.f - pState->minDelta ) + if ( maxGain < ( 1.f - pState->minDelta ) * PCM16_TO_FLT_FAC ) { pState->gain_state[i].gainExpVal = -1; } @@ -296,104 +322,75 @@ void ivas_agc_enc_process( if ( !isGainAdjusted ) { float actualMaxAbsVal = 0.f; - int16_t currMaxAttExp, gainExpValMaxRange; + int16_t currMaxAttExp; currMaxAttExp = min( ( pState->gain_state[i].lastExp + pState->agc_com.absEmin ), pState->agc_com.maxAttExp ); - gainExpValMaxRange = min( ( pState->gain_state[i].lastExp + pState->agc_com.absEmin ), pState->agc_com.maxAttExp + 1 ); extendedExpVal = FALSE; if ( isClipped ) { + int16_t isCompensated = FALSE; actualMaxAbsVal = pState->gain_state[i].lastMaxAbs * pState->gain_state[i].lastGain; - if ( MaxAbsValIdx == 0 ) - { - pState->gain_data[i].gainException = TRUE; - } - else + idx = min( offset - 1, MaxAbsValIdx ); + pState->gain_state[i].gainExpVal = (int16_t) ceilf( -logf( actualMaxAbsVal * MDFT_NORM_SCALING ) / logf( pState->agc_com.winFunc[idx] ) ); + + while ( !isCompensated ) { - int16_t isCompensated = FALSE; - pState->gain_data[i].gainException = FALSE; - pState->gain_state[i].gainExpVal = (int16_t) ceilf( -logf( actualMaxAbsVal ) / logf( pState->agc_com.winFunc[MaxAbsValIdx] ) ); + float tmpSignal; + isCompensated = TRUE; - while ( !isCompensated ) + for ( idx = clippedIdx; idx <= MaxAbsValIdx; idx++ ) { - float tmpSignal; - isCompensated = TRUE; - - for ( idx = clippedIdx; idx <= MaxAbsValIdx; idx++ ) + if ( idx >= offset ) { - tmpSignal = ppPcm_out[i][idx] * powf( pState->agc_com.winFunc[idx], (float) pState->gain_state[i].gainExpVal ); - - if ( ( tmpSignal > ( 1.f - pState->minDelta ) ) || ( tmpSignal < -1.f ) ) - { - isCompensated = FALSE; - break; - } + idx = MaxAbsValIdx; + tmpSignal = ppPcm_out[i][idx] * powf( pState->agc_com.winFunc[offset - 1], (float) pState->gain_state[i].gainExpVal ); } - - if ( !isCompensated ) + else { - pState->gain_state[i].gainExpVal++; + tmpSignal = ppPcm_out[i][idx] * powf( pState->agc_com.winFunc[idx], (float) pState->gain_state[i].gainExpVal ); } - if ( pState->gain_state[i].gainExpVal > currMaxAttExp ) + if ( ( tmpSignal > ( 1.f - pState->minDelta ) * PCM16_TO_FLT_FAC ) || ( tmpSignal < MIN16B_FLT ) ) { - pState->gain_data[i].gainException = TRUE; - - if ( pState->gain_state[i].gainExpVal == gainExpValMaxRange ) - { - extendedExpVal = TRUE; - if ( isCompensated ) - { - pState->gain_data[i].gainException = FALSE; - } - } + isCompensated = FALSE; break; } } - } - } - if ( !pState->gain_data[i].gainException ) - { - for ( idx = 0; idx < input_frame; idx++ ) - { - if ( idx < offset ) + if ( !isCompensated ) { - gain = powf( pState->agc_com.winFunc[idx], pState->gain_state[i].gainExpVal ); + pState->gain_state[i].gainExpVal++; } - else - { - gain = powf( pState->agc_com.winFunc[offset - 1], pState->gain_state[i].gainExpVal ); + if ( pState->gain_state[i].gainExpVal > currMaxAttExp ) + { + pState->gain_state[i].gainExpVal = min( pState->gain_state[i].gainExpVal, currMaxAttExp ); + break; } - ppPcm_out[i][idx] *= gain; } - - pState->gain_state[i].lastGain *= powf( pState->agc_com.winFunc[offset - 1], pState->gain_state[i].gainExpVal ); } - else - { - pState->gain_state[i].gainExpVal = (int16_t) ( -floorf( -logf( actualMaxAbsVal + pState->minDelta ) * INV_LOG_2 ) ); - pState->gain_state[i].gainExpVal = min( gainExpValMaxRange, pState->gain_state[i].gainExpVal ); - gain = powf( 2.0f, -1.0f * pState->gain_state[i].gainExpVal ); - for ( idx = 0; idx < input_frame; idx++ ) + for ( idx = 0; idx < input_frame; idx++ ) + { + if ( idx < offset ) { - ppPcm_out[i][idx] *= gain; + gain = powf( pState->agc_com.winFunc[idx], pState->gain_state[i].gainExpVal ); + } + else + { + + gain = powf( pState->agc_com.winFunc[offset - 1], pState->gain_state[i].gainExpVal ); } - pState->gain_state[i].lastGain *= gain; + ppPcm_out[i][idx] *= gain; } + pState->gain_state[i].lastGain *= powf( pState->agc_com.winFunc[offset - 1], pState->gain_state[i].gainExpVal ); /*safety check starts*/ if ( pState->gain_state[i].gainExpVal == pState->agc_com.maxAttExp + 1 ) { extendedExpVal = TRUE; } - else if ( pState->gain_state[i].gainExpVal == 0 ) - { - pState->gain_data[i].gainException = FALSE; - } /*safety check ends*/ pState->gain_state[i].prevExp = pState->gain_state[i].lastExp; @@ -401,30 +398,15 @@ void ivas_agc_enc_process( pState->gain_state[i].lastExp -= pState->gain_state[i].gainExpVal; if ( extendedExpVal ) { - if ( !pState->gain_data[i].gainException ) - { - pState->gain_data[i].gainException = TRUE; - pState->gain_state[i].gainExpVal = -1; - } - else - { - if ( pState->gain_state[i].gainExpVal == gainExpValMaxRange ) - { - pState->gain_state[i].gainExpVal = 0; - } - } + + pState->gain_state[i].gainExpVal = -1; } } pState->gain_data[i].absGainExp = pState->gain_state[i].prevExp + pState->agc_com.absEmin; - if ( extendedExpVal && pState->gain_data[i].gainException && pState->gain_state[i].gainExpVal <= 0 ) + if ( extendedExpVal && pState->gain_state[i].gainExpVal <= 0 ) { - if ( pState->gain_state[i].gainExpVal == -1 ) - { - pState->gain_data[i].gainException = FALSE; - } - pState->gain_state[i].gainExpVal = pState->agc_com.maxAttExp + 1; } @@ -465,17 +447,16 @@ void ivas_agc_enc_process( if ( per_ch_bit[i] == 1 ) { push_next_indice( hMetaData, (uint16_t) pState->gain_data[i].absGainExpCurr, (int16_t) pState->agc_com.betaE ); - push_next_indice( hMetaData, (uint16_t) pState->gain_data[i].gainException, 1 ); } } } #ifdef DEBUG_AGC /* writing to a temporary bitstream file */ - if ( ivas_agc_writeBits( agcOut, pIn_buf, pState ) ) + if ( ivas_agc_writeBits( agcOut, n_channels, pState ) ) { /* TODO: return error once error codes are harmonized */ - IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "SPAR FOA ENC AGC Failed to open agcOut\n " ); + IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "SPAR ENC AGC Failed to open agcOut\n " ); } #endif @@ -483,21 +464,7 @@ void ivas_agc_enc_process( } #ifdef DEBUG_AGC - -/*-----------------------------------------------------------------------------------------* - * Function description - - * Get a window function - * - * Inputs - - * float* winFunc - * unsigned integer frameLen - * - * Outputs - - * returns status - * - * - *-----------------------------------------------------------------------------------------*/ -static int16_t ivas_agc_writeBits( FILE *stream, ivas_agc_enc_in_buf_t *pIn_buf, ivas_agc_enc_state_t *pState ) +static int16_t ivas_agc_writeBits( FILE *stream, const int16_t n_channels, ivas_agc_enc_state_t *pState ) { if ( stream == NULL ) { @@ -505,7 +472,7 @@ static int16_t ivas_agc_writeBits( FILE *stream, ivas_agc_enc_in_buf_t *pIn_buf, } int16_t num_bits = 0, num_dmx_bits[4] = { 0 }; - for ( int16_t i = 0; i < pIn_buf->n_channels; i++ ) + for ( int16_t i = 0; i < n_channels; i++ ) { if ( pState->gain_data[i].absGainExpCurr < 0 || pState->gain_data[i].absGainExpCurr >= (int16_t) pow( 2, pState->agc_com.betaE ) ) @@ -516,8 +483,6 @@ static int16_t ivas_agc_writeBits( FILE *stream, ivas_agc_enc_in_buf_t *pIn_buf, fwrite( &( pState->gain_data[i].absGainExpCurr ), sizeof( int32_t ), 1, stream ); /* n bits */ num_bits += pState->agc_com.betaE; - fwrite( &( pState->gain_data[i].gainException ), sizeof( int16_t ), 1, stream ); /* 1 bit */ - num_bits++; num_dmx_bits[i]++; /*fprintf(stdout, "absGainExpCurr[%d]:= %d[%d bits]; ", i, pState->gain_data[i].absGainExpCurr, pState->betaE); */ diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index b2b96681fd4024e44b01fa16ad9ba9cbceadb7e2..0c85ca186dcafd0c1084465c8b6d34b350aaa028 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "prot.h" #include "ivas_cnst.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include #ifdef DEBUG_MODE_ACELP @@ -61,7 +61,6 @@ ivas_error ivas_core_enc( const int16_t n_CoreChannels, /* i : number of core channels to be coded */ float old_inp_12k8[CPE_CHANNELS][L_INP_12k8], /* i : buffer of old input signal */ float old_inp_16k[CPE_CHANNELS][L_INP], /* i : buffer of old input signal */ - const float Etot[CPE_CHANNELS], /* i : total energy */ float ener[CPE_CHANNELS], /* i : residual energy from Levinson-Durbin */ float A[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )], /* i : A(z) unquantized for the 4 subframes */ float Aw[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )], /* i : weighted A(z) unquantized for subframes */ @@ -79,11 +78,12 @@ ivas_error ivas_core_enc( float enerBuffer[CPE_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ float fft_buff[CPE_CHANNELS][2 * L_FFT], /* i : FFT buffer */ const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ + const int16_t ivas_format, /* i : IVAS format */ const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ ) { int16_t n, input_frame; - int16_t cpe_id, is_MCT; + int16_t cpe_id, MCT_flag; Encoder_State **sts, *st; STEREO_ICBWE_ENC_HANDLE hStereoICBWE; STEREO_TD_ENC_DATA_HANDLE hStereoTD; @@ -101,12 +101,10 @@ ivas_error ivas_core_enc( int16_t unbits[CPE_CHANNELS]; float tdm_lspQ_PCh[M], tdm_lsfQ_PCh[M]; int16_t last_element_mode, tdm_Pitch_reuse_flag; - int32_t element_brate, input_Fs; + int32_t element_brate, last_element_brate, input_Fs; ivas_error error; - error = IVAS_ERR_OK; - - wmops_sub_start( "ivas_core_enc" ); + push_wmops( "ivas_core_enc" ); error = IVAS_ERR_OK; @@ -114,29 +112,30 @@ ivas_error ivas_core_enc( * General initialization *-----------------------------------------------------------------*/ - if ( hSCE != NULL ) { cpe_id = -1; - is_MCT = 0; + MCT_flag = 0; sts = hSCE->hCoreCoder; hStereoTD = NULL; hStereoICBWE = NULL; element_brate = hSCE->element_brate; + last_element_brate = hSCE->last_element_brate; last_element_mode = IVAS_SCE; tdm_Pitch_reuse_flag = -1; } else { cpe_id = hCPE->cpe_id; - is_MCT = 0; + MCT_flag = 0; if ( hMCT != NULL ) { - is_MCT = 1; + MCT_flag = 1; } sts = hCPE->hCoreCoder; hStereoICBWE = hCPE->hStereoICBWE; element_brate = hCPE->element_brate; + last_element_brate = hCPE->last_element_brate; last_element_mode = hCPE->last_element_mode; if ( hCPE->hStereoTD != NULL ) @@ -177,8 +176,7 @@ ivas_error ivas_core_enc( * Pre-processing, incl. Decision matrix *---------------------------------------------------------------------*/ - if ( ( error = pre_proc_ivas( st, last_element_mode, element_brate, input_frame, old_inp_12k8[n], old_inp_16k[n], &inp[n], &ener[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], new_inp_resamp16k[n], &Voicing_flag[n], old_wsp[n], loc_harm[n], cor_map_sum[n], vad_flag_dtx[n], enerBuffer[n], fft_buff[n], is_MCT, vad_hover_flag[n], - flag_16k_smc ) ) != IVAS_ERR_OK ) + if ( ( error = pre_proc_ivas( st, last_element_mode, element_brate, ivas_format == SBA_FORMAT ? last_element_brate : element_brate, input_frame, old_inp_12k8[n], old_inp_16k[n], &inp[n], &ener[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], new_inp_resamp16k[n], &Voicing_flag[n], old_wsp[n], loc_harm[n], cor_map_sum[n], vad_flag_dtx[n], enerBuffer[n], fft_buff[n], MCT_flag, vad_hover_flag[n], flag_16k_smc ) ) != IVAS_ERR_OK ) { return error; } @@ -198,12 +196,12 @@ ivas_error ivas_core_enc( st = sts[n]; /*---------------------------------------------------------------------* - * Write signalling info into the bitstream + * Write signaling info into the bitstream *---------------------------------------------------------------------*/ - if ( !is_MCT || ( is_MCT && cpe_id == 0 ) ) + if ( !MCT_flag || ( MCT_flag && cpe_id == 0 ) ) { - ivas_signalling_enc( st, is_MCT, element_brate, tdm_SM_or_LRTD_Pri, tdm_Pitch_reuse_flag ); + ivas_signaling_enc( st, MCT_flag, element_brate, tdm_SM_or_LRTD_Pri, tdm_Pitch_reuse_flag ); } /*---------------------------------------------------------------------* @@ -258,10 +256,18 @@ ivas_error ivas_core_enc( { if ( sts[0]->core_brate > SID_2k40 && sts[1]->core_brate > SID_2k40 ) { - if ( is_MCT ) + if ( MCT_flag ) { ivas_mdct_core_whitening_enc( hCPE, old_inp_16k, old_wsp, pitch_buf, hMCT->p_mdst_spectrum_long[cpe_id], hMCT->tnsBits[cpe_id], hMCT->p_orig_spectrum_long[cpe_id], - hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], hMCT->hBstr, &hMCT->LFE_off, 1, hMCT->nchan_out_woLFE + hMCT->num_lfe ); + hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], hMCT->hBstr, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + &hMCT->LFE_off, +#endif + 1, hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); } else { @@ -280,7 +286,7 @@ ivas_error ivas_core_enc( } } - if ( sts[0]->cng_dirac_flag ) + if ( sts[0]->cng_sba_flag ) { FdCngEncodeDiracMDCTStereoSID( hCPE ); } @@ -344,16 +350,7 @@ ivas_error ivas_core_enc( { if ( st->hBWE_TD != NULL ) { - set_f( st->hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); - set_f( shb_speech, 0.0f, L_FRAME16k ); - set_f( st->hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); - set_f( st->hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); - st->hBWE_TD->old_mean_EnvSHBres = 0.0f; - st->hBWE_TD->prev_enr_EnvSHBres = 1.0f; - st->hBWE_TD->prev_shb_env_tilt = 0.0f; - st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; - st->hBWE_TD->prev_mix_factor = 1.0f; - st->hBWE_TD->prev_Env_error = 0.0f; + InitSWBencBufferStates( st->hBWE_TD, shb_speech ); } } @@ -404,13 +401,16 @@ ivas_error ivas_core_enc( * Channel-aware mode - write signaling information into the bitstream *---------------------------------------------------------------------*/ - signalling_enc_rf( st ); + signaling_enc_rf( st ); /*---------------------------------------------------------------------* * Common updates *---------------------------------------------------------------------*/ - updt_enc_common( st, Etot[n] ); + if ( !MCT_flag ) /* for MCT do this later, otherwise there can be a problem because TCX quant happens later and might get the wrong last_core on a bit rate switch */ + { + updt_enc_common( st ); + } } @@ -439,6 +439,7 @@ ivas_error ivas_core_enc( dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "extl_brate", n, id, ENC ) ); dbgwrite( &st->coder_type, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type", n, id, ENC ) ); + dbgwrite( &st->coder_type_raw, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type_raw", n, id, ENC ) ); dbgwrite( &st->clas, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "clas", n, id, ENC ) ); dbgwrite( &st->cng_type, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "cng_type", n, id, ENC ) ); dbgwrite( &st->L_frame, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "L_frame", n, id, ENC ) ); @@ -455,6 +456,8 @@ ivas_error ivas_core_enc( dbgwrite( &st->sp_aud_decision1, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "sp_aud_decision1", n, id, ENC ) ); dbgwrite( &st->sp_aud_decision2, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "sp_aud_decision2", n, id, ENC ) ); + dbgwrite( &st->lp_noise, sizeof( float ), 1, input_frame, fname( debug_dir, "lp_noise", n, id, ENC ) ); + #if ( defined DEBUG_MODE_ACELP ) || ( defined DEBUG_MODE_TCX ) if ( st->coder_type == INACTIVE || st->coder_type == UNVOICED ) { @@ -523,7 +526,7 @@ ivas_error ivas_core_enc( } #endif - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_enc/ivas_core_pre_proc.c b/lib_enc/ivas_core_pre_proc.c index a380ee917f966bd309bfa8b2d6dc1f4c65ffcead..7a0d25ddfa4e2883fd7db7eb507d72b24123e064 100644 --- a/lib_enc/ivas_core_pre_proc.c +++ b/lib_enc/ivas_core_pre_proc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -55,6 +55,7 @@ ivas_error pre_proc_ivas( Encoder_State *st, /* i/o: encoder state structure */ const int16_t last_element_mode, /* i : last element mode */ const int32_t element_brate, /* i : element bitrate */ + const int32_t last_element_brate, /* i : last element bitrate */ const int16_t input_frame, /* i : frame length */ float old_inp_12k8[], /* i/o: buffer of old input signal */ float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ @@ -73,7 +74,7 @@ ivas_error pre_proc_ivas( const int16_t vad_flag_dtx, /* i : HE-SAD flag with additional DTX HO */ const float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ const float fft_buff[2 * L_FFT], /* i : FFT buffer */ - const int16_t is_mct, /* i : MCT mode flag */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int16_t vad_hover_flag, /* i : VAD hangover flag */ const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ ) @@ -84,7 +85,7 @@ ivas_error pre_proc_ivas( int32_t sr_core_tmp, total_brate_tmp; ivas_error error; - wmops_sub_start( "pre_proc" ); + push_wmops( "pre_proc" ); error = IVAS_ERR_OK; @@ -234,7 +235,7 @@ ivas_error pre_proc_ivas( /* Configure TCX with the same bitrate as given when (re-)initializing TCX */ total_brate_tmp = st->total_brate; st->total_brate = st->bits_frame_nominal * FRAMES_PER_SEC; - SetModeIndex( st, st->last_bits_frame_nominal * FRAMES_PER_SEC, last_element_mode, is_mct ); + SetModeIndex( st, st->last_bits_frame_nominal * FRAMES_PER_SEC, last_element_mode, MCT_flag ); st->sr_core = getCoreSamplerateMode2( element_mode, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode ); st->total_brate = total_brate_tmp; @@ -275,6 +276,11 @@ ivas_error pre_proc_ivas( { st->hTcxEnc->tfm_mem = 0.75f; } + else if ( element_brate != last_element_brate ) + { + SetModeIndex( st, st->bits_frame_nominal * FRAMES_PER_SEC, element_mode, MCT_flag ); + } + /*-----------------------------------------------------------------* * Update of ACELP harmonicity counter (used in ACELP transform codebook @32kbps) @@ -335,13 +341,13 @@ ivas_error pre_proc_ivas( } } - /* channel-aware mode - due to lack of signalling bit, sharpFlag is 1 always in RF mode */ + /* channel-aware mode - due to lack of signaling bit, sharpFlag is 1 always in RF mode */ if ( st->rf_mode && ( st->coder_type == VOICED || st->coder_type == GENERIC ) ) { st->sharpFlag = 1; } - /* TD stereo, secondary channel - due to lack of signalling bits, sharpFlag is always 1 */ + /* TD stereo, secondary channel - due to lack of signaling bits, sharpFlag is always 1 */ if ( element_mode == IVAS_CPE_TD && st->idchan == 1 ) { st->sharpFlag = 0; @@ -453,7 +459,7 @@ ivas_error pre_proc_ivas( dbgwrite( inp_16k, sizeof( float ), L_FRAME, 1, fname( debug_dir, "inp_16k", st->idchan, st->id_element, ENC ) ); #endif - wmops_sub_end(); + pop_wmops(); return error; } @@ -653,7 +659,9 @@ ivas_error ivas_compute_core_buffers( * Perform fixed preemphasis (16kHz signal) through 1 - g*z^-1 *-----------------------------------------------------------------*/ - if ( !( ( element_mode == IVAS_CPE_TD && st->idchan == 1 ) || element_mode == IVAS_CPE_MDCT ) ) + if ( + st->tcxonly == 0 && + !( ( element_mode == IVAS_CPE_TD && st->idchan == 1 ) || element_mode == IVAS_CPE_MDCT ) ) { st->mem_preemph_enc = new_inp_16k[L_frame_tmp - 1]; } diff --git a/lib_enc/ivas_core_pre_proc_front.c b/lib_enc/ivas_core_pre_proc_front.c index c0dc1b7276676ef26410cda18f54a8ec923a8099..85eba72f006b477315f626931811aceb8c5443f3 100644 --- a/lib_enc/ivas_core_pre_proc_front.c +++ b/lib_enc/ivas_core_pre_proc_front.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,10 +41,17 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include +/*---------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------*/ + +#define SCE_SMC_THR 16000 + + /*-------------------------------------------------------------------* * Local function prototypes *--------------------------------------------------------------------*/ @@ -68,7 +75,6 @@ ivas_error pre_proc_front_ivas( const int16_t n, /* i : channel number */ float old_inp_12k8[], /* o : buffer of old input signal */ float old_inp_16k[], /* o : buffer of old input signal @16kHz */ - float *Etot, /* o : total energy */ float *ener, /* o : residual energy from Levinson-Durbin */ float *relE, /* o : frame relative energy */ float A[NB_SUBFR16k * ( M + 1 )], /* o : A(z) unquantized for the 4 subframes */ @@ -77,7 +83,7 @@ ivas_error pre_proc_front_ivas( float lsp_new[M], /* o : LSPs at the end of the frame */ float lsp_mid[M], /* o : LSPs in the middle of the frame */ int16_t *vad_hover_flag, /* o : VAD hangover flag */ - int16_t *attack_flag, /* o : flag signalling attack */ + int16_t *attack_flag, /* o : flag signaling attack */ float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: real buffer */ float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: imag buffer */ float old_wsp[], /* o : weighted input signal buffer */ @@ -98,13 +104,16 @@ ivas_error pre_proc_front_ivas( const int16_t localVAD_HE_SAD_LR[CPE_CHANNELS], /* i : HE-SAD flag without hangover, LR channels */ float band_energies_LR[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN */ const int16_t flag_16k_smc, /* i : flag to indicate if the OL SMC is run at 16 kHz */ - const int16_t spar_front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ - const int16_t spar_force_front_vad, /* i : flag to force VAD decision */ - const int16_t spar_front_vad_dtx_flag /* i : front-VAD DTX flag to overwrite VAD decision*/ + const int16_t front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ + const int16_t force_front_vad, /* i : flag to force VAD decision */ + const int16_t front_vad_dtx_flag, /* i : front-VAD DTX flag to overwrite VAD decision*/ + const int32_t ivas_total_brate /* i : IVAS total bitrate - for setting the DTX */ + ) { float *inp_12k8, *new_inp_12k8; /* pointers to current frame and new data */ float *wsp; /* weighted input signal buffer */ + float Etot; /* total energy */ float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ float tmpN[NB_BANDS]; /* Temporary noise update */ @@ -155,7 +164,7 @@ ivas_error pre_proc_front_ivas( int16_t LR_vad_flag; ivas_error error; - wmops_sub_start( "pre_proc_front" ); + push_wmops( "pre_proc_front" ); /*------------------------------------------------------------------* * Initialization @@ -406,11 +415,11 @@ ivas_error pre_proc_front_ivas( * Spectral analysis *--------------------------------------------------------------------------*/ - analy_sp( element_mode, hCPE, input_Fs, inp_12k8, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, Etot, st->min_band, st->max_band, band_energies, PS, fft_buff ); + analy_sp( element_mode, hCPE, input_Fs, inp_12k8, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, &Etot, st->min_band, st->max_band, band_energies, PS, fft_buff ); if ( hStereoClassif != NULL ) { - if ( st->lp_speech - *Etot > 25 ) + if ( st->lp_speech - Etot > 25 ) { hStereoClassif->silence_flag = 2; } @@ -425,7 +434,7 @@ ivas_error pre_proc_front_ivas( * SAD (1-signal, 0-noise) *----------------------------------------------------------------*/ - noise_est_pre( *Etot, st->ini_frame, st->hNoiseEst, st->idchan, element_mode, hCPE != NULL ? hCPE->last_element_mode : element_mode ); + noise_est_pre( Etot, st->ini_frame, st->hNoiseEst, st->idchan, element_mode, hCPE != NULL ? hCPE->last_element_mode : element_mode ); if ( element_mode == IVAS_CPE_TD && ( ( abs( hCPE->hStereoTD->tdm_last_ratio_idx - tdm_ratio_idx ) > 5 && st->idchan == 1 ) || abs( hCPE->hStereoTD->tdm_last_inst_ratio_idx - hCPE->hStereoTD->tdm_inst_ratio_idx ) > 10 ) ) { @@ -442,16 +451,15 @@ ivas_error pre_proc_front_ivas( } #endif - if ( spar_force_front_vad == 1 || spar_front_vad_flag == 1 ) + if ( force_front_vad == 1 || front_vad_flag == 1 ) { /* overwrite VAD decision with front-VAD decision if external VAD is set to 1*/ - st->vad_flag = spar_front_vad_flag; - st->localVAD = spar_front_vad_flag; + st->vad_flag = front_vad_flag; + st->localVAD = front_vad_flag; } - if ( ( hCPE != NULL && !( lr_vad_enabled && st->idchan == 0 ) ) || hSCE != NULL ) { - *vad_flag_dtx = dtx_hangover_addition( st, st->vad_flag, st->lp_speech - st->lp_noise, 0, vad_hover_flag, NULL, NULL ); + *vad_flag_dtx = dtx_hangover_addition( st, st->vad_flag, st->lp_speech - st->lp_noise, 0, vad_hover_flag, NULL, NULL, NULL ); } else { @@ -466,10 +474,10 @@ ivas_error pre_proc_front_ivas( *vad_hover_flag = *vad_flag_dtx && !( LR_localVAD || st->localVAD ); } - if ( spar_force_front_vad == 1 || spar_front_vad_dtx_flag == 1 ) + if ( force_front_vad == 1 || front_vad_dtx_flag == 1 ) { /* overwrite VAD decision with front-VAD decision if external VAD is set to 1*/ - *vad_flag_dtx = spar_front_vad_dtx_flag; + *vad_flag_dtx = front_vad_dtx_flag; } /*----------------------------------------------------------------* @@ -478,7 +486,12 @@ ivas_error pre_proc_front_ivas( if ( st->idchan == 0 && element_mode != IVAS_CPE_MDCT ) { - bw_detect( st, st->input, NULL, enerBuffer ); + bw_detect( st, st->input, NULL, enerBuffer +#ifdef FIX_MDCT_BASED_BWD + , + 0 +#endif + ); } if ( element_mode != IVAS_CPE_MDCT ) /* in MDCT stereo, set_bw_stereo() is used instead */ @@ -498,7 +511,7 @@ ivas_error pre_proc_front_ivas( * Correlation correction as a function of total noise level *----------------------------------------------------------------*/ - noise_est_down( fr_bands, st->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->hNoiseEst->totalNoise, *Etot, &st->hNoiseEst->Etot_last, &st->hNoiseEst->Etot_v_h2 ); + noise_est_down( fr_bands, st->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->hNoiseEst->totalNoise, Etot, &st->hNoiseEst->Etot_last, &st->hNoiseEst->Etot_v_h2 ); if ( lr_vad_enabled && st->idchan == 0 ) { @@ -508,7 +521,7 @@ ivas_error pre_proc_front_ivas( corr_shiftR = correlation_shift( hCPE->hFrontVad[1]->hNoiseEst->totalNoise ); } - *relE = *Etot - st->lp_speech; + *relE = Etot - st->lp_speech; corr_shift = correlation_shift( st->hNoiseEst->totalNoise ); @@ -547,13 +560,19 @@ ivas_error pre_proc_front_ivas( st->cng_type = LP_CNG; } - dtx( st, *vad_flag_dtx, inp_12k8 ); + dtx( st, ivas_total_brate, *vad_flag_dtx, inp_12k8 ); + + if ( hCPE != NULL && hCPE->hStereoDft != NULL && st->core_brate == SID_2k40 ) + { + /* Add another period of expected xcorr updates */ + hCPE->hStereoDft->expectedNumUpdates += st->hDtxEnc->max_SID; + } /*----------------------------------------------------------------* * Adjust FD-CNG Noise Estimator *----------------------------------------------------------------*/ - if ( st->hFdCngEnc != NULL && ( last_element_brate != element_brate || st->last_bwidth != st->bwidth ) ) + if ( st->hFdCngEnc != NULL && ( st->ini_frame == 0 || last_element_brate != element_brate || st->last_bwidth != st->bwidth ) ) { configureFdCngEnc( st->hFdCngEnc, max( st->input_bwidth, WB ), st->bits_frame_nominal * FRAMES_PER_SEC ); if ( hCPE != NULL ) @@ -648,7 +667,7 @@ ivas_error pre_proc_front_ivas( * Update estimated noise energy and voicing cut-off frequency *-----------------------------------------------------------------*/ - noise_est( st, old_pitch1, tmpN, epsP, *Etot, *relE, corr_shift, tmpE, fr_bands, cor_map_sum, &ncharX, &sp_div, + noise_est( st, old_pitch1, tmpN, epsP, Etot, *relE, corr_shift, tmpE, fr_bands, cor_map_sum, &ncharX, &sp_div, &non_staX, loc_harm, lf_E, &st->hNoiseEst->harm_cor_cnt, st->hNoiseEst->Etot_l_lp, &dummy /*sp_floor*/, S_map, hStereoClassif, NULL, st->ini_frame ); if ( lr_vad_enabled && st->idchan == 0 ) @@ -681,7 +700,7 @@ ivas_error pre_proc_front_ivas( find_tilt( fr_bands, st->hNoiseEst->bckr, ee, st->pitch, st->voicing, lf_E, corr_shift, st->input_bwidth, st->max_band, hp_E, MODE1, &( st->bckr_tilt_lt ), st->Opt_SC_VBR ); - st->coder_type = find_uv( st, pitch_fr, voicing_fr, inp_12k8, ee, &dE1X, corr_shift, *relE, *Etot, hp_E, &flag_spitch, last_core_orig, hStereoClassif ); + st->coder_type = find_uv( st, pitch_fr, voicing_fr, inp_12k8, ee, &dE1X, corr_shift, *relE, Etot, hp_E, &flag_spitch, last_core_orig, hStereoClassif ); /*-----------------------------------------------------------------* * channel aware mode configuration * @@ -717,7 +736,7 @@ ivas_error pre_proc_front_ivas( * 1st stage speech/music classification (GMM model) *----------------------------------------------------------------*/ - smc_dec = ivas_smc_gmm( st, hStereoClassif, localVAD_HE_SAD, *Etot, lsp_new, *cor_map_sum, epsP, PS, non_staX, *relE, &high_lpn_flag, flag_spitch ); + smc_dec = ivas_smc_gmm( st, hStereoClassif, localVAD_HE_SAD, Etot, lsp_new, *cor_map_sum, epsP, PS, non_staX, *relE, &high_lpn_flag, flag_spitch ); #ifdef DEBUGGING if ( st->idchan == 0 ) @@ -740,19 +759,16 @@ ivas_error pre_proc_front_ivas( * Update of old per-band energy spectrum *----------------------------------------------------------------*/ - long_enr( st, *Etot, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); + long_enr( st, Etot, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); mvr2r( fr_bands + NB_BANDS, st->hNoiseEst->enrO, NB_BANDS ); if ( lr_vad_enabled && st->idchan == 0 ) { - long_enr( st, *Etot, localVAD_HE_SAD, high_lpn_flag, hCPE->hFrontVad, CPE_CHANNELS, localVAD_HE_SAD_LR, Etot_LR ); + long_enr( st, -1, localVAD_HE_SAD, high_lpn_flag, hCPE->hFrontVad, CPE_CHANNELS, localVAD_HE_SAD_LR, Etot_LR ); mvr2r( fr_bands_LR[0] + NB_BANDS, hCPE->hFrontVad[0]->hNoiseEst->enrO, NB_BANDS ); mvr2r( fr_bands_LR[1] + NB_BANDS, hCPE->hFrontVad[1]->hNoiseEst->enrO, NB_BANDS ); - - hCPE->hFrontVad[0]->hNoiseEst->Etot_last = Etot_LR[0]; - hCPE->hFrontVad[1]->hNoiseEst->Etot_last = Etot_LR[1]; } /*----------------------------------------------------------------* @@ -776,7 +792,7 @@ ivas_error pre_proc_front_ivas( else if ( element_mode != IVAS_CPE_MDCT ) { /* SNR-based speech/music classification */ - if ( ( element_mode >= IVAS_CPE_DFT && element_brate >= IVAS_24k4 ) || ( element_mode == IVAS_SCE && element_brate >= 16000 ) ) + if ( ( element_mode >= IVAS_CPE_DFT && element_brate >= IVAS_24k4 ) || ( element_mode == IVAS_SCE && element_brate >= SCE_SMC_THR ) ) { if ( flag_16k_smc ) { @@ -794,9 +810,30 @@ ivas_error pre_proc_front_ivas( smc_dec = ivas_acelp_tcx20_switching( st, inp_12k8, wsp, non_staX, pitch_fr, voicing_fr, currFlatness, lsp_mid, stab_fac, res_cod_SNR_M, flag_16k_smc ); } } + /* Switch to ACELP for non-harmonic transient signals */ + else if ( ( ( element_mode >= IVAS_CPE_DFT && element_brate <= IVAS_16k4 ) || ( element_mode == IVAS_SCE && element_brate < SCE_SMC_THR ) ) && ( loc_harm[0] != 1 ) && smc_dec == MUSIC ) + { + if ( element_mode == IVAS_SCE ) + { + if ( transient_analysis( st->hTranDet, st->hNoiseEst->cor_map, st->hNoiseEst->multi_harm_limit ) ) + { + smc_dec = SPEECH; + } + } + else if ( element_mode == IVAS_CPE_DFT ) + { + for ( i = 0; i < CPE_CHANNELS; i++ ) + { + if ( smc_dec != SPEECH && transient_analysis( hCPE->hCoreCoder[i]->hTranDet, st->hNoiseEst->cor_map, st->hNoiseEst->multi_harm_limit ) ) + { + smc_dec = SPEECH; /* overwrite initial music decision, initial SPEECH_MUSIC never changed */ + } + } + } + } /* 2nd stage speech/music classification (ACELP/GSC/TCX core selection) */ - ivas_smc_mode_selection( st, element_brate, smc_dec, *relE, *Etot, attack_flag, inp_12k8, S_map, flag_spitch ); + ivas_smc_mode_selection( st, element_brate, smc_dec, *relE, Etot, attack_flag, inp_12k8, S_map, flag_spitch ); #ifdef ITD_WINNER_GAIN_MODIFY if ( element_mode == IVAS_CPE_DFT ) @@ -843,7 +880,7 @@ ivas_error pre_proc_front_ivas( mvr2r( &old_inp_12k8[L_FRAME], st->old_inp_12k8, L_INP_MEM ); - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_enc/ivas_corecoder_enc_reconfig.c b/lib_enc/ivas_corecoder_enc_reconfig.c new file mode 100644 index 0000000000000000000000000000000000000000..cbb48495bf6b7f34fcf079df5eebf284e4b0f4d7 --- /dev/null +++ b/lib_enc/ivas_corecoder_enc_reconfig.c @@ -0,0 +1,485 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "ivas_cnst.h" +#include "prot.h" +#include "ivas_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#include +#endif +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * ivas_corecoder_enc_reconfig() + * + * Allocate, initialize, and configure SCE/CPE/MCT handles in case of bitrate switching + *-------------------------------------------------------------------*/ + +ivas_error ivas_corecoder_enc_reconfig( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const int16_t nSCE_old, /* i : number of SCEs in previous frame */ + const int16_t nCPE_old, /* i : number of CPEs in previous frame */ + const int16_t nchan_transport_old, /* i : number of TCs in previous frame */ + const int32_t brate_SCE, /* i : bitrate to be set for the SCEs */ + const int32_t brate_CPE, /* i : bitrate to be set for the CPEs */ + const MC_MODE last_mc_mode /* i : switching between MC modes: last mode */ +) +{ + int16_t n, sce_id, cpe_id; + int16_t len_inp_memory, n_CoreCoder_existing, nSCE_existing, nCPE_existing; + float input_buff[MCT_MAX_BLOCKS][L_FRAME48k + NS2SA( 48000, IVAS_FB_ENC_DELAY_NS )]; + BSTR_ENC_HANDLE hBstr, hMetaData; + Indice *ind_list, *ind_list_metadata; + int16_t nb_bits_tot, next_ind, last_ind; + ENCODER_CONFIG_HANDLE hEncoderConfig; + ivas_error error; + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + hEncoderConfig = st_ivas->hEncoderConfig; + error = IVAS_ERR_OK; + + len_inp_memory = (int16_t) ( hEncoderConfig->input_Fs / FRAMES_PER_SEC ); + if ( hEncoderConfig->ivas_format == SBA_FORMAT ) + { + len_inp_memory += NS2SA( hEncoderConfig->input_Fs, IVAS_FB_ENC_DELAY_NS ); + } + + /*-----------------------------------------------------------------* + * Switching between SCE(s)/CPE(s)/MCT + *-----------------------------------------------------------------*/ + + if ( st_ivas->nchan_transport == nchan_transport_old && st_ivas->nSCE == nSCE_old && st_ivas->nCPE == nCPE_old ) /* in McMASA, nchan_transport may be the same, but nSCE/nCPE differs */ + { + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + copy_encoder_config( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 ); + st_ivas->hSCE[sce_id]->element_brate = brate_SCE; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + } + + for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + st_ivas->hCPE[cpe_id]->element_brate = brate_CPE; + + /* prepare bitstream buffers */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + copy_encoder_config( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 ); + + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + } + } + + if ( st_ivas->nCPE > 1 ) + { + if ( ( error = mct_enc_reconfigure( st_ivas, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else + { + int16_t nchan_transport_real, nchan_transport_old_real; + + nchan_transport_old_real = nchan_transport_old; + nchan_transport_real = st_ivas->nchan_transport; + + /* in SCE+CPE McMASA nchan_transport is still 2, fix the numbers */ + if ( hEncoderConfig->ivas_format == MC_FORMAT && last_mc_mode == MC_MODE_MCMASA ) + { + nchan_transport_old_real = nSCE_old + CPE_CHANNELS * nCPE_old; + } + + if ( hEncoderConfig->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) + { + nchan_transport_real = st_ivas->nSCE + CPE_CHANNELS * st_ivas->nCPE; + } + + /* something in transport changes */ + ind_list = NULL; + ind_list_metadata = NULL; + hBstr = NULL; + hMetaData = NULL; + + /* get the index list pointers */ + if ( nSCE_old ) + { + hBstr = st_ivas->hSCE[0]->hCoreCoder[0]->hBstr; + hMetaData = st_ivas->hSCE[0]->hMetaData; + } + else if ( nCPE_old ) + { + hBstr = st_ivas->hCPE[0]->hCoreCoder[0]->hBstr; + hMetaData = st_ivas->hCPE[nCPE_old - 1]->hMetaData; + } +#ifdef DEBUGGING + else + { + assert( 0 && "At least one SCE or one CPE should have existed before!\n" ); + } +#endif + + /* save bitstream information */ + ind_list = hBstr->ind_list; /* pointer to the beginning of the global list */ + nb_bits_tot = hBstr->nb_bits_tot; + next_ind = hBstr->next_ind; + last_ind = hBstr->last_ind; + ind_list_metadata = hMetaData->ind_list; /* pointer to the beginning of the global list */ + + if ( hEncoderConfig->ivas_format == MC_FORMAT && last_mc_mode == MC_MODE_MCMASA && st_ivas->mc_mode == MC_MODE_MCMASA ) + { + /* within McMASA we can modify the transport signals when switching */ + /* copy earlier dmx buffers */ + if ( nSCE_old > 0 ) + { + set_zero( input_buff[0], len_inp_memory ); + mvr2r( st_ivas->hSCE[0]->hCoreCoder[0]->input_buff, input_buff[0], len_inp_memory ); + } + + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + set_zero( input_buff[n + 1], len_inp_memory ); + if ( nCPE_old > 0 ) + { + mvr2r( st_ivas->hCPE[0]->hCoreCoder[n]->input_buff, input_buff[n + 1], len_inp_memory ); + } + } + + ivas_mcmasa_dmx_modify( len_inp_memory, input_buff, nSCE_old + CPE_CHANNELS * nCPE_old, st_ivas->nSCE + CPE_CHANNELS * st_ivas->nCPE ); + + n_CoreCoder_existing = 0; + } + else + { + n_CoreCoder_existing = min( nchan_transport_real, nchan_transport_old_real ); + } + + /* destroy superfluous core-coder elements */ + for ( sce_id = st_ivas->nSCE; sce_id < nSCE_old; sce_id++ ) + { + /* save input audio buffers */ + if ( n_CoreCoder_existing > sce_id ) + { + mvr2r( st_ivas->hSCE[sce_id]->hCoreCoder[0]->input_buff, input_buff[sce_id], len_inp_memory ); + } + + destroy_sce_enc( st_ivas->hSCE[sce_id] ); + st_ivas->hSCE[sce_id] = NULL; + } + + for ( cpe_id = st_ivas->nCPE; cpe_id < nCPE_old; cpe_id++ ) + { + /* save input audio buffers */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + if ( n_CoreCoder_existing > cpe_id * CPE_CHANNELS + n ) + { +#ifdef FIX_386_CORECODER_RECONFIG + mvr2r( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->input_buff, input_buff[( cpe_id - st_ivas->nCPE ) * CPE_CHANNELS + n], len_inp_memory ); +#else + mvr2r( st_ivas->hCPE[cpe_id]->hCoreCoder[0]->input_buff, input_buff[( cpe_id - st_ivas->nCPE ) * CPE_CHANNELS + n], len_inp_memory ); /* TODO VoiceAge: Please check if this should be hCoreCoder[n] */ +#endif + } + } + + destroy_cpe_enc( st_ivas->hCPE[cpe_id] ); + st_ivas->hCPE[cpe_id] = NULL; + } + + if ( st_ivas->nCPE <= 1 && st_ivas->hMCT != NULL ) + { + ivas_mct_enc_close( &( st_ivas->hMCT ) ); + } + + /* special case, if we have MCT now and had a single CPE before, remove the MDCT Stereo handles */ + if ( st_ivas->nCPE > 1 && nCPE_old == 1 ) + { + free( st_ivas->hCPE[0]->hStereoMdct ); + st_ivas->hCPE[0]->hStereoMdct = NULL; + } + + /* create missing core coder elements and set element bitrates for alrady existing ones */ + if ( st_ivas->nSCE > 0 ) + { + nSCE_existing = min( nSCE_old, st_ivas->nSCE ); + + for ( sce_id = 0; sce_id < nSCE_existing; sce_id++ ) + { + copy_encoder_config( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 ); + st_ivas->hSCE[sce_id]->element_brate = brate_SCE; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + } + + for ( sce_id = nSCE_existing; sce_id < st_ivas->nSCE; sce_id++ ) + { + if ( ( error = create_sce_enc( st_ivas, sce_id, brate_SCE ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* propagate input audio buffers */ + if ( n_CoreCoder_existing > sce_id ) + { + mvr2r( input_buff[sce_id], st_ivas->hSCE[sce_id]->hCoreCoder[0]->input_buff, len_inp_memory ); + } + + /* prepare bitstream buffers */ + st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->ind_list = ind_list + sce_id * MAX_NUM_INDICES; + + /* only reset indices if it is not the first index list, this already contains the IVAS format bits */ + if ( sce_id > 0 ) + { + reset_indices_enc( st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr, MAX_NUM_INDICES ); + } + else + { + st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->last_ind = last_ind; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->nb_bits_tot = nb_bits_tot; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->next_ind = next_ind; + } + + st_ivas->hSCE[sce_id]->hMetaData->ind_list = ind_list_metadata + sce_id * MAX_BITS_METADATA; + reset_indices_enc( st_ivas->hSCE[sce_id]->hMetaData, MAX_BITS_METADATA ); + } + } + + if ( st_ivas->nCPE > 0 ) + { + nCPE_existing = min( nCPE_old, st_ivas->nCPE ); + + for ( cpe_id = 0; cpe_id < nCPE_existing; cpe_id++ ) + { + st_ivas->hCPE[cpe_id]->element_brate = brate_CPE; + + /* prepare bitstream buffers */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + copy_encoder_config( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 ); + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->ind_list = ind_list + ( cpe_id * CPE_CHANNELS + n + st_ivas->nSCE ) * MAX_NUM_INDICES; + if ( cpe_id * CPE_CHANNELS + n > 0 || ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->nSCE > 0 ) ) + { + reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES ); + } + else + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->last_ind = last_ind; + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->nb_bits_tot = nb_bits_tot; + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->next_ind = next_ind; + } + } + } + + for ( cpe_id = nCPE_existing; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + if ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->hMcMasa->separateChannelEnabled ) + { + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + } + + if ( ( error = create_cpe_enc( st_ivas, cpe_id, brate_CPE ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* propagate input audio buffers */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + if ( n_CoreCoder_existing > cpe_id * CPE_CHANNELS + n ) + { + mvr2r( input_buff[n], st_ivas->hCPE[cpe_id]->hCoreCoder[0]->input_buff, len_inp_memory ); /* TODO VoiceAge: Please check if this should be hCoreCoder[n] */ + } + } + + /* prepare bitstream buffers */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->ind_list = ind_list + ( cpe_id * CPE_CHANNELS + n + st_ivas->nSCE ) * MAX_NUM_INDICES; + if ( cpe_id * CPE_CHANNELS + n > 0 || ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->nSCE > 0 ) ) + { + reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES ); + } + else + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->last_ind = last_ind; + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->nb_bits_tot = nb_bits_tot; + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->next_ind = next_ind; + } + + if ( hEncoderConfig->Opt_DTX_ON ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_sba_flag = 1; + } + } + } + } + + if ( last_mc_mode == MC_MODE_MCMASA && st_ivas->mc_mode == MC_MODE_MCMASA ) + { + /* restore modified transport signal */ + if ( st_ivas->nSCE ) + { + mvr2r( input_buff[0], st_ivas->hSCE[0]->hCoreCoder[0]->input_buff, len_inp_memory ); + } + if ( st_ivas->nCPE ) + { + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + mvr2r( input_buff[n + 1], st_ivas->hCPE[0]->hCoreCoder[n]->input_buff, len_inp_memory ); + } + } + } + + if ( st_ivas->nCPE > 1 && nCPE_old <= 1 ) + { + if ( nCPE_old == 1 ) + { + /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handles for MCT */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; + + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[0]->element_brate / FRAMES_PER_SEC ); + st_ivas->hCPE[0]->hCoreCoder[n]->igf = getIgfPresent( st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal * FRAMES_PER_SEC, + st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, + st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode +#endif + ); + + if ( st_ivas->hCPE[0]->hCoreCoder[n]->igf ) + { + IGFEncSetMode( st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, + st_ivas->hCPE[0]->element_brate, + st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, + st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, + st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); + } + } + } + + if ( ( error = create_mct_enc( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->hMCT != NULL && st_ivas->nCPE > 1 ) + { + if ( ( error = mct_enc_reconfigure( st_ivas, st_ivas->nchan_transport != nchan_transport_old ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* metadata handling for CPEs */ + if ( st_ivas->nCPE > 0 ) + { + if ( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData == NULL ) + { + if ( ( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData = (BSTR_ENC_HANDLE) malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MetaData structure\n" ) ); + } + } + + st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData->ind_list = ind_list_metadata + st_ivas->nSCE * MAX_NUM_INDICES; + reset_indices_enc( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData, MAX_BITS_METADATA ); + + for ( cpe_id = 0; cpe_id < st_ivas->nCPE - 1; cpe_id++ ) + { + if ( st_ivas->hCPE[cpe_id]->hMetaData != NULL ) + { + free( st_ivas->hCPE[cpe_id]->hMetaData ); + st_ivas->hCPE[cpe_id]->hMetaData = NULL; + } + } + } + + /* special case, if we have a single CPE and had MCT before we need to init the MDCT stereo handles here */ + if ( st_ivas->nCPE == 1 && nCPE_old > 1 ) + { + if ( ( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); + } + + /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handle */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; + + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[0]->element_brate / FRAMES_PER_SEC ); + st_ivas->hCPE[0]->hCoreCoder[n]->igf = getIgfPresent( st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal * FRAMES_PER_SEC, + st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, + st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode +#endif + ); + + if ( st_ivas->hCPE[0]->hCoreCoder[n]->igf ) + { + IGFEncSetMode( st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, + st_ivas->hCPE[0]->element_brate, + st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, + st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, + st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); + } + + /* reset mct_chan_mode */ + st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } + +#ifdef DEBUGGING + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->mdct_stereo_mode_cmdl = hEncoderConfig->stereo_mode_cmdl; +#endif + initMdctStereoEncData( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct, hEncoderConfig->ivas_format, st_ivas->hCPE[st_ivas->nCPE - 1]->element_mode, st_ivas->hCPE[st_ivas->nCPE - 1]->element_brate, hEncoderConfig->max_bwidth, 0, NULL, 1 ); + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->isSBAStereoMode = ( ( hEncoderConfig->ivas_format == SBA_FORMAT ) && ( st_ivas->nchan_transport == 2 ) ); + } + } + + return error; +} diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index e7c34ae0e83f763c9ea74fdc62cc3b44a08456b5..184a867cd1a13dda60a27833465f18b4cbc88334 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -65,7 +65,6 @@ ivas_error ivas_cpe_enc( int16_t n, n_CoreChannels; float old_inp_12k8[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ float old_inp_16k[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ - float Etot[CPE_CHANNELS]; /* total energy; correlation shift */ float ener[CPE_CHANNELS]; /* residual energy from Levinson-Durbin */ float relE[CPE_CHANNELS]; /* frame relative energy */ float A[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ @@ -87,7 +86,7 @@ ivas_error ivas_cpe_enc( float currFlatness[CPE_CHANNELS]; /* flatness parameter */ float fft_buff[CPE_CHANNELS][2 * L_FFT]; /* FFT buffer */ int16_t tdm_ratio_idx, tdm_ratio_idx_SM; /* temp. TD stereo parameters */ - int16_t tdm_SM_or_LRTD_Pri, last_tdm_LRTD_flag; /* temp. TD stereo parameters */ + int16_t tdm_SM_or_LRTD_Pri; /* temp. TD stereo parameters */ float tdm_last_ratio; /* temp. TD stereo parameters */ int16_t nb_bits; /* number of DFT stereo side bits */ float fr_bands[CPE_CHANNELS][2 * NB_BANDS]; /* energy in frequency bands */ @@ -96,6 +95,7 @@ ivas_error ivas_cpe_enc( int16_t localVAD_HE_SAD[CPE_CHANNELS]; /* HE-SAD flag without hangover, LR channels */ float band_energies_LR[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ float orig_input[CPE_CHANNELS][L_FRAME48k]; + float Etot_last[CPE_CHANNELS]; int32_t tmp, input_Fs; int16_t max_bwidth, ivas_format; ENCODER_CONFIG_HANDLE hEncoderConfig; @@ -104,7 +104,7 @@ ivas_error ivas_cpe_enc( error = IVAS_ERR_OK; - wmops_sub_start( "ivas_cpe_enc" ); + push_wmops( "ivas_cpe_enc" ); hCPE = st_ivas->hCPE[cpe_id]; sts = hCPE->hCoreCoder; @@ -115,22 +115,15 @@ ivas_error ivas_cpe_enc( input_Fs = hEncoderConfig->input_Fs; ivas_total_brate = hEncoderConfig->ivas_total_brate; - /*------------------------------------------------------------------* * Initialization - general *-----------------------------------------------------------------*/ tdm_SM_or_LRTD_Pri = 0; - last_tdm_LRTD_flag = 0; tdm_ratio_idx = -1; tdm_ratio_idx_SM = -1; tdm_last_ratio = 0; - if ( hCPE->hStereoTD != NULL ) - { - last_tdm_LRTD_flag = hCPE->hStereoTD->tdm_LRTD_flag; - } - #ifdef DEBUGGING if ( hCPE->hCoreCoder[0]->ini_frame == 0 ) { @@ -161,7 +154,14 @@ ivas_error ivas_cpe_enc( } mvr2r( data_f_ch0, sts[0]->input, input_frame ); +#ifdef ISSUE_24_CLEANUP_MCT_LFE + if ( data_f_ch1 != NULL ) /*this may happen for cases with odd number of channels*/ + { + mvr2r( data_f_ch1, sts[1]->input, input_frame ); + } +#else mvr2r( data_f_ch1, sts[1]->input, input_frame ); +#endif /*----------------------------------------------------------------* * Stereo technology selection @@ -193,7 +193,7 @@ ivas_error ivas_cpe_enc( * dynamically allocate data structures depending on the actual stereo mode *----------------------------------------------------------------*/ - if ( ( error = stereo_memory_enc( hCPE, input_Fs, max_bwidth, &tdm_last_ratio, ivas_format ) ) != IVAS_ERR_OK ) + if ( ( error = stereo_memory_enc( hCPE, input_Fs, max_bwidth, &tdm_last_ratio, ivas_format, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) { return error; } @@ -283,8 +283,7 @@ ivas_error ivas_cpe_enc( stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, hCPE->element_brate, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); } } - - if ( hCPE->element_mode == IVAS_CPE_TD && last_tdm_LRTD_flag != hCPE->hStereoTD->tdm_LRTD_flag ) + if ( hCPE->element_mode == IVAS_CPE_TD ) { if ( hCPE->hStereoTD->tdm_LRTD_flag ) { @@ -304,12 +303,27 @@ ivas_error ivas_cpe_enc( { if ( st_ivas->hMCT ) { +#ifdef ISSUE_24_CLEANUP_MCT_LFE + int16_t lfe_bits; + lfe_bits = ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ? st_ivas->hLFE->lfe_bits : 0 ); +#endif sts[n]->total_brate = hCPE->element_brate; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[n]->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif sts[n]->bits_frame_nominal = (int16_t) ( hCPE->element_brate / FRAMES_PER_SEC ); - sts[n]->bits_frame_channel = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC - ( st_ivas->hMCT->num_lfe == FALSE ? 0 : LFE_BITS ) - nb_bits_metadata ) / st_ivas->hMCT->nchan_out_woLFE ); + sts[n]->bits_frame_channel = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC - +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( st_ivas->hMCT->num_lfe == FALSE ? 0 : LFE_BITS ) - +#else + lfe_bits - +#endif + nb_bits_metadata ) / + st_ivas->hMCT->nchan_out_woLFE ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif } else { @@ -323,9 +337,10 @@ ivas_error ivas_cpe_enc( if ( hCPE->element_brate != hCPE->last_element_brate && st_ivas->hMCT == NULL ) { #ifdef DEBUGGING - hCPE->hStereoMdct->mdct_stereo_mode_cmdl = hEncoderConfig->stereo_mode_cmdl; + hCPE->hStereoMdct->mdct_stereo_mode_cmdl = hEncoderConfig->mdct_stereo_mode_cmdl; #endif initMdctStereoEncData( hCPE->hStereoMdct, ivas_format, hCPE->element_mode, hCPE->element_brate, max_bwidth, 0, NULL, 0 ); + hCPE->hStereoMdct->isSBAStereoMode = ( ( ivas_format == SBA_FORMAT ) && ( st_ivas->nchan_transport == 2 ) ); } } @@ -349,23 +364,14 @@ ivas_error ivas_cpe_enc( stereo_dft_enc_analyze( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT, hCPE->input_mem ); sts[0]->total_brate = ( sts[0]->bits_frame_nominal + 10 ) * FRAMES_PER_SEC; /* add small overhead; st[0]->total_brate used in coder_type_modif() */ - - if ( ( sts[0]->last_bwidth < max_bwidth ) || ( sts[0]->last_core_brate <= SID_2k40 ) ) /* IVAS_fmToDo: TBV - BWD output is not known here yet !!! */ - { - /* reconfigure in case of BW switching or if last frame was a SID/NO_DATA with coarse partitioning */ - hCPE->hStereoDft->nbands = stereo_dft_band_config( hCPE->hStereoDft->band_limits, hCPE->hStereoDft->hConfig->band_res, hCPE->hStereoDft->NFFT, ENC ); - } - - /* Update DFT Stereo memories */ - stereo_dft_enc_update( hCPE->hStereoDft, sts[0]->max_bwidth #ifdef DEBUG_MODE_DFT - , - (int16_t) ( ( hCPE->element_brate ) / FRAMES_PER_SEC - 0.8f * sts[0]->bits_frame_nominal ) + hCPE->hStereoDft->res_cod_bits = (int16_t) ( ( hCPE->element_brate ) / FRAMES_PER_SEC - 0.8f * sts[0]->bits_frame_nominal ); #endif - ); + /* Update DFT Stereo memories */ + stereo_dft_enc_update( hCPE->hStereoDft, sts[0]->max_bwidth ); /* DFT stereo processing */ - stereo_dft_enc_process( hCPE, input_frame ); + stereo_dft_enc_process( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); } else if ( hCPE->element_mode == IVAS_CPE_TD ) { @@ -382,10 +388,13 @@ ivas_error ivas_cpe_enc( { sts[1]->bits_frame_channel -= st_ivas->hQMetaData->metadata_max_bits; } + + Etot_last[0] = sts[0]->hNoiseEst->Etot_last; + Etot_last[1] = sts[1]->hNoiseEst->Etot_last; } else if ( hCPE->element_mode == IVAS_CPE_MDCT ) { - stereo_td_itd_mdct_stereo( hCPE, input_frame ); + stereo_td_itd_mdct_stereo( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); } /*----------------------------------------------------------------* @@ -429,9 +438,11 @@ ivas_error ivas_cpe_enc( } #ifdef DEBUG_MODE_INFO - dbgwrite( sts[0]->input - NS2SA( sts[0]->input_Fs, ACELP_LOOK_NS ), 4, input_frame, 1, "res/input_DMX" ); - dbgwrite( sts[1]->input - NS2SA( sts[1]->input_Fs, ACELP_LOOK_NS ), 4, input_frame, 1, "res/input_DMX.ch2" ); - dbgwrite( &hCPE->element_mode, 2, 1, input_frame, "res/element_mode" ); + for ( n = 0; n < n_CoreChannels; n++ ) + { + dbgwrite( sts[0]->input - NS2SA( sts[0]->input_Fs, ACELP_LOOK_NS ), sizeof( float ), input_frame, 1, fname( debug_dir, "input_DMX", n, sts[n]->id_element, ENC ) ); + } + dbgwrite( &hCPE->element_mode, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "element_mode", 0, sts[0]->id_element, ENC ) ); #endif /*----------------------------------------------------------------* @@ -440,9 +451,11 @@ ivas_error ivas_cpe_enc( for ( n = 0; n < n_CoreChannels; n++ ) { - error = pre_proc_front_ivas( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8[n], old_inp_16k[n], &Etot[n], &ener[n], &relE[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], + error = pre_proc_front_ivas( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8[n], old_inp_16k[n], + &ener[n], &relE[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], &vad_hover_flag[n], &attack_flag[n], realBuffer[n], imagBuffer[n], old_wsp[n], pitch_fr[n], voicing_fr[n], &loc_harm[n], &cor_map_sum[n], &vad_flag_dtx[n], enerBuffer[n], - fft_buff[n], A[0], lsp_new[0], currFlatness[n], tdm_ratio_idx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, band_energies_LR, 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, 0, 0 ); + fft_buff[n], A[0], lsp_new[0], currFlatness[n], tdm_ratio_idx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, band_energies_LR, 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, 0, 0, + ivas_total_brate ); if ( error != IVAS_ERR_OK ) { return error; @@ -455,6 +468,7 @@ ivas_error ivas_cpe_enc( if ( sts[0]->core_brate == SID_2k40 || sts[0]->core_brate == FRAME_NO_DATA ) { sts[0]->core_brate = -1; + sts[0]->total_brate = hCPE->element_brate; } } @@ -466,7 +480,7 @@ ivas_error ivas_cpe_enc( { if ( hCPE->element_mode == IVAS_CPE_DFT || hCPE->element_mode == IVAS_CPE_TD ) { - reset_metadata_spatial( ivas_format, hCPE->hMetaData, hCPE->element_brate, &tmp, sts[0]->core_brate, nb_bits_metadata, st_ivas->sba_mode, hCPE->element_mode ); + reset_metadata_spatial( ivas_format, hCPE->hMetaData, hCPE->element_brate, &tmp, sts[0]->core_brate, nb_bits_metadata, st_ivas->sba_mode ); } } @@ -476,9 +490,9 @@ ivas_error ivas_cpe_enc( stereoFdCngCoherence( sts, hCPE->last_element_mode, fft_buff ); /* Reset metadata */ - if ( sts[0]->cng_dirac_flag || ( ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) ) + if ( sts[0]->cng_sba_flag || ( ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) ) { - reset_metadata_spatial( ivas_format, hCPE->hMetaData, hCPE->element_brate, &tmp, sts[0]->core_brate, nb_bits_metadata, st_ivas->sba_mode, hCPE->element_mode ); + reset_metadata_spatial( ivas_format, hCPE->hMetaData, hCPE->element_brate, &tmp, sts[0]->core_brate, nb_bits_metadata, st_ivas->sba_mode ); } } @@ -495,6 +509,7 @@ ivas_error ivas_cpe_enc( if ( sts[0]->bwidth != sts[0]->last_bwidth || ( ( hCPE->last_element_brate != hCPE->element_brate || hCPE->last_element_mode != hCPE->element_mode ) && sts[0]->bwidth != sts[0]->max_bwidth ) ) { initMdctStereoEncData( hCPE->hStereoMdct, ivas_format, hCPE->element_mode, hCPE->element_brate, sts[0]->bwidth, 0, NULL, 0 ); + hCPE->hStereoMdct->isSBAStereoMode = ( ( ivas_format == SBA_FORMAT ) && ( st_ivas->nchan_transport == 2 ) ); if ( hCPE->element_brate <= MAX_MDCT_ITD_BRATE && ivas_format == STEREO_FORMAT ) { @@ -524,11 +539,11 @@ ivas_error ivas_cpe_enc( { tdm_ol_pitch_comparison( hCPE, pitch_fr, voicing_fr ); - tdm_configure_enc( hCPE, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); + tdm_configure_enc( hCPE, Etot_last, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); if ( hEncoderConfig->Opt_DTX_ON ) { - stereo_cng_upd_counters( hCPE->hStereoCng, hCPE->element_mode, -1, NULL, sts[0]->hTdCngEnc->burst_ho_cnt ); + stereo_cng_upd_counters( hCPE->hStereoCng, hCPE->element_mode, -1, NULL, sts[0]->hTdCngEnc->burst_ho_cnt, NULL ); } } @@ -543,10 +558,10 @@ ivas_error ivas_cpe_enc( } /*----------------------------------------------------------------* - * Write IVAS format signalling in SID frames + * Write IVAS format signaling in SID frames *----------------------------------------------------------------*/ - if ( sts[0]->core_brate == SID_2k40 && ( ivas_format != SBA_FORMAT || st_ivas->sba_mode != SBA_MODE_SPAR ) ) + if ( sts[0]->core_brate == SID_2k40 ) { ivas_write_format_sid( ivas_format, hCPE->element_mode, sts[0]->hBstr ); } @@ -565,7 +580,7 @@ ivas_error ivas_cpe_enc( /* Reconfigure DFT Stereo for inactive frames */ if ( sts[0]->core_brate == SID_2k40 ) { - stereo_dft_config( hCPE->hStereoDft->hConfig, IVAS_SID_4k4, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + stereo_dft_config( hCPE->hStereoDft->hConfig, IVAS_SID_5k2, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); } else { @@ -573,17 +588,15 @@ ivas_error ivas_cpe_enc( } stereo_dft_cng_side_gain( hCPE->hStereoDft, hCPE->hStereoCng, sts[0]->core_brate, sts[0]->last_core_brate, sts[0]->bwidth ); - - stereo_dft_enc_update( hCPE->hStereoDft, min( SWB, sts[0]->max_bwidth ) #ifdef DEBUG_MODE_DFT - , - 0 + hCPE->hStereoDft->res_cod_bits = 0; #endif - ); + + stereo_dft_enc_update( hCPE->hStereoDft, min( SWB, sts[0]->max_bwidth ) ); } else { - stereo_cng_upd_counters( hCPE->hStereoCng, hCPE->element_mode, hCPE->hStereoDft->nbands, hCPE->hStereoDft->sidSideGain, sts[0]->hTdCngEnc->burst_ho_cnt ); + stereo_cng_upd_counters( hCPE->hStereoCng, hCPE->element_mode, hCPE->hStereoDft->nbands, hCPE->hStereoDft->sidSideGain, sts[0]->hTdCngEnc->burst_ho_cnt, &hCPE->hStereoDft->coh_fade_counter ); } } @@ -609,7 +622,7 @@ ivas_error ivas_cpe_enc( if ( sts[0]->core_brate == FRAME_NO_DATA || sts[0]->core_brate == SID_2k40 ) { - assert( ( nb_bits <= ( ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS ) ) && "Stereo DFT CNG: bit budget is violated" ); + assert( ( nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS ) ) && "Stereo DFT CNG: bit budget is violated" ); } else { @@ -627,7 +640,7 @@ ivas_error ivas_cpe_enc( * Core Encoder *----------------------------------------------------------------*/ - if ( ( error = ivas_core_enc( NULL, hCPE, st_ivas->hMCT, n_CoreChannels, old_inp_12k8, old_inp_16k, Etot, ener, A, Aw, epsP, lsp_new, lsp_mid, vad_hover_flag, attack_flag, realBuffer, imagBuffer, old_wsp, loc_harm, cor_map_sum, vad_flag_dtx, enerBuffer, fft_buff, tdm_SM_or_LRTD_Pri, 0 ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_core_enc( NULL, hCPE, st_ivas->hMCT, n_CoreChannels, old_inp_12k8, old_inp_16k, ener, A, Aw, epsP, lsp_new, lsp_mid, vad_hover_flag, attack_flag, realBuffer, imagBuffer, old_wsp, loc_harm, cor_map_sum, vad_flag_dtx, enerBuffer, fft_buff, tdm_SM_or_LRTD_Pri, ivas_format, 0 ) ) != IVAS_ERR_OK ) { return error; } @@ -666,6 +679,19 @@ ivas_error ivas_cpe_enc( hCPE->hFrontVad[0]->ini_frame = min( hCPE->hFrontVad[0]->ini_frame, MAX_FRAME_COUNTER ); } + /* Store previous attack detection flag */ + for ( n = 0; n < CPE_CHANNELS; n++ ) + { +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( sts[n]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + { +#endif + sts[n]->hTranDet->transientDetector.prev_bIsAttackPresent = sts[n]->hTranDet->transientDetector.bIsAttackPresent; +#ifndef ISSUE_24_CLEANUP_MCT_LFE + } +#endif + } + #ifdef DEBUG_MODE_INFO if ( hCPE->element_mode == IVAS_CPE_DFT ) { @@ -702,7 +728,7 @@ ivas_error ivas_cpe_enc( } #endif - wmops_sub_end(); + pop_wmops(); return error; } @@ -740,7 +766,7 @@ ivas_error create_cpe_enc( * Allocate CPE handle *-----------------------------------------------------------------*/ - if ( ( hCPE = (CPE_ENC_HANDLE) count_malloc( sizeof( CPE_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE = (CPE_ENC_HANDLE) malloc( sizeof( CPE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CPE\n" ) ); } @@ -774,7 +800,7 @@ ivas_error create_cpe_enc( { if ( ivas_format == STEREO_FORMAT || ivas_format == MASA_FORMAT || ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) { - if ( ( hCPE->input_mem[n] = (float *) count_malloc( sizeof( float ) * NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ) ) == NULL ) + if ( ( hCPE->input_mem[n] = (float *) malloc( sizeof( float ) * NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } @@ -791,7 +817,7 @@ ivas_error create_cpe_enc( * stereo classifier: allocate and initialize *-----------------------------------------------------------------*/ - if ( ( hCPE->hStereoClassif = (STEREO_CLASSIF_HANDLE) count_malloc( sizeof( STEREO_CLASSIF_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoClassif = (STEREO_CLASSIF_HANDLE) malloc( sizeof( STEREO_CLASSIF_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo classifier structure\n" ) ); } @@ -802,9 +828,12 @@ ivas_error create_cpe_enc( * Metadata: allocate and initialize *-----------------------------------------------------------------*/ - if ( !( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) && ( cpe_id == ( st_ivas->nCPE - 1 ) ) ) + /* we need the meta data handle also if we init as MC_FORMAT/MCT since it might be needed + at a bit rate switch to ParamMC or McMASA and the metadata index list is only really reachable + in the ivas_init_encoder() function and has to be connected to the MD handle there */ + if ( cpe_id == ( st_ivas->nCPE - 1 ) ) { - if ( ( hCPE->hMetaData = (BSTR_ENC_HANDLE) count_malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hMetaData = (BSTR_ENC_HANDLE) malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MetaData structure\n" ) ); } @@ -816,7 +845,7 @@ ivas_error create_cpe_enc( for ( n = 0; n < CPE_CHANNELS; n++ ) { - if ( ( st = (ENC_CORE_HANDLE) count_malloc( sizeof( Encoder_State ) ) ) == NULL ) + if ( ( st = (ENC_CORE_HANDLE) malloc( sizeof( Encoder_State ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); } @@ -824,12 +853,13 @@ ivas_error create_cpe_enc( copy_encoder_config( st_ivas, st, 1 ); st->total_brate = hCPE->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT && ( n + cpe_id * CPE_CHANNELS ) == LFE_CHANNEL ) { st->mct_chan_mode = MCT_CHAN_MODE_LFE; } - - if ( ( error = init_encoder( st, n, hEncoderConfig->var_SID_rate_flag, hEncoderConfig->interval_SID, 0 ) ) != IVAS_ERR_OK ) +#endif + if ( ( error = init_encoder( st, n, hEncoderConfig->var_SID_rate_flag, hEncoderConfig->interval_SID, 0, st_ivas->ism_mode ) ) != IVAS_ERR_OK ) { return error; } @@ -850,7 +880,7 @@ ivas_error create_cpe_enc( { if ( hCPE->element_mode == IVAS_CPE_TD || hCPE->element_mode == IVAS_CPE_DFT ) { - if ( ( hCPE->hStereoCng = (STEREO_CNG_ENC_HANDLE) count_malloc( sizeof( STEREO_CNG_ENC ) ) ) == NULL ) + if ( ( hCPE->hStereoCng = (STEREO_CNG_ENC_HANDLE) malloc( sizeof( STEREO_CNG_ENC ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo Cng for Unified/TD \n" ) ); } @@ -903,7 +933,7 @@ ivas_error create_cpe_enc( if ( hCPE->element_mode != IVAS_CPE_MDCT ) { - if ( ( hCPE->hStereoTCA = (STEREO_TCA_ENC_HANDLE) count_malloc( sizeof( STEREO_TCA_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTCA = (STEREO_TCA_ENC_HANDLE) malloc( sizeof( STEREO_TCA_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); } @@ -917,7 +947,7 @@ ivas_error create_cpe_enc( if ( hCPE->element_mode != IVAS_CPE_MDCT ) { - if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) count_malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); } @@ -931,7 +961,7 @@ ivas_error create_cpe_enc( if ( hCPE->element_mode == IVAS_CPE_TD ) { - if ( ( hCPE->hStereoTD = (STEREO_TD_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_TD_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTD = (STEREO_TD_ENC_DATA_HANDLE) malloc( sizeof( STEREO_TD_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) ); } @@ -945,7 +975,7 @@ ivas_error create_cpe_enc( if ( hCPE->element_mode == IVAS_CPE_MDCT && st_ivas->nCPE == 1 ) { - if ( ( hCPE->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); } @@ -954,6 +984,7 @@ ivas_error create_cpe_enc( hCPE->hStereoMdct->mdct_stereo_mode_cmdl = st_ivas->hEncoderConfig->mdct_stereo_mode_cmdl; #endif initMdctStereoEncData( hCPE->hStereoMdct, ivas_format, hCPE->element_mode, hCPE->element_brate, max_bwidth, 0, NULL, 1 ); + hCPE->hStereoMdct->isSBAStereoMode = ( ( ivas_format == SBA_FORMAT ) && ( st_ivas->nchan_transport == 2 ) ); if ( hCPE->element_mode == IVAS_CPE_MDCT && element_brate <= MAX_MDCT_ITD_BRATE && ivas_format == STEREO_FORMAT ) { @@ -985,7 +1016,7 @@ void destroy_cpe_enc( if ( hCPE->hStereoClassif != NULL ) { - count_free( hCPE->hStereoClassif ); + free( hCPE->hStereoClassif ); hCPE->hStereoClassif = NULL; } @@ -993,14 +1024,14 @@ void destroy_cpe_enc( { if ( hCPE->input_mem[n] != NULL ) { - count_free( hCPE->input_mem[n] ); + free( hCPE->input_mem[n] ); hCPE->input_mem[n] = NULL; } } if ( hCPE->hMetaData != NULL ) { - count_free( hCPE->hMetaData ); + free( hCPE->hMetaData ); hCPE->hMetaData = NULL; } @@ -1023,7 +1054,7 @@ void destroy_cpe_enc( if ( hCPE->hStereoTD != NULL ) { - count_free( hCPE->hStereoTD ); + free( hCPE->hStereoTD ); hCPE->hStereoTD = NULL; } @@ -1035,19 +1066,19 @@ void destroy_cpe_enc( if ( hCPE->hStereoTCA != NULL ) { - count_free( hCPE->hStereoTCA ); + free( hCPE->hStereoTCA ); hCPE->hStereoTCA = NULL; } if ( hCPE->hStereoICBWE != NULL ) { - count_free( hCPE->hStereoICBWE ); + free( hCPE->hStereoICBWE ); hCPE->hStereoICBWE = NULL; } if ( hCPE->hStereoCng != NULL ) { - count_free( hCPE->hStereoCng ); + free( hCPE->hStereoCng ); hCPE->hStereoCng = NULL; } @@ -1060,7 +1091,7 @@ void destroy_cpe_enc( } } - count_free( hCPE ); + free( hCPE ); return; } diff --git a/lib_enc/ivas_decision_matrix_enc.c b/lib_enc/ivas_decision_matrix_enc.c index 7b9dccaec90747670ba7766b061eb19cd4c5668c..b8949329582e8684a9f1f185d86c71647ab7e807 100644 --- a/lib_enc/ivas_decision_matrix_enc.c +++ b/lib_enc/ivas_decision_matrix_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* @@ -114,7 +114,7 @@ void ivas_decision_matrix_enc( if ( st->element_mode == IVAS_SCE && st->low_rate_mode ) { - /* ISm low-rate mode */ + /* ISM low-rate mode */ st->core = ACELP_CORE; st->coder_type = INACTIVE; } @@ -368,17 +368,17 @@ void ivas_decision_matrix_enc( /*---------------------------------------------------------------------* - * ivas_signalling_enc() + * ivas_signaling_enc() * - * write signalling information of SCE/CPE mode into the bitstream + * write signaling information of SCE/CPE mode into the bitstream *---------------------------------------------------------------------*/ -void ivas_signalling_enc( - Encoder_State *st, /* i/o: encoder state structure */ - const int16_t is_MCT, /* i : MCT enabled */ - const int32_t element_brate, /* i : element bitrate */ +void ivas_signaling_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int32_t element_brate, /* i : element bitrate */ const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ - const int16_t tdm_Pitch_reuse_flag /* i : primary channel pitch reuse flag in TD stereo */ + const int16_t tdm_Pitch_reuse_flag /* i : primary channel pitch reuse flag in TD stereo */ ) { int16_t ind; @@ -386,12 +386,12 @@ void ivas_signalling_enc( if ( st->element_mode == IVAS_CPE_TD && st->idchan == 1 ) { - /* minimal signalling for the secondary channel, most of the parameters are deduced from the primary channel */ - signalling_enc_secondary( st, tdm_SM_or_LRTD_Pri, tdm_Pitch_reuse_flag ); + /* minimal signaling for the secondary channel, most of the parameters are deduced from the primary channel */ + signaling_enc_secondary( st, tdm_SM_or_LRTD_Pri, tdm_Pitch_reuse_flag ); } else if ( st->element_mode == IVAS_SCE && st->low_rate_mode ) { - /* ISm Low-rate mode -> do nothing -> always WB, ACELP core, IC coder_type */ + /* ISM Low-rate mode -> do nothing -> always WB, ACELP core, IC coder_type */ } else if ( ( st->element_mode == IVAS_CPE_MDCT && st->idchan == 1 ) || st->core_brate <= SID_2k40 ) { @@ -405,7 +405,7 @@ void ivas_signalling_enc( * Write element mode info *--------------------------------------------------------------------------*/ - if ( st->element_mode >= IVAS_CPE_DFT && element_brate < MIN_BRATE_MDCT_STEREO && !is_MCT ) /* note: in MCT, the MDCT stereo is used exclusively */ + if ( st->element_mode >= IVAS_CPE_DFT && element_brate < MIN_BRATE_MDCT_STEREO && !MCT_flag ) /* note: in MCT, the MDCT stereo is used exclusively */ { ind = st->element_mode - IVAS_CPE_DFT; push_indice( hBstr, IND_SMODE, ind, NBITS_ELEMENT_MODE ); @@ -451,7 +451,7 @@ void ivas_signalling_enc( } /*-------------------------------------------------------------------------- - * Write core dependent signalling + * Write core dependent signaling *--------------------------------------------------------------------------*/ if ( st->core == ACELP_CORE ) diff --git a/lib_enc/ivas_dirac_enc.c b/lib_enc/ivas_dirac_enc.c index 69ed35aa831aad26cb3ff37d181139473d8ea5aa..991e713afb0e368d5b5f1fad40f453142d0cb01e 100644 --- a/lib_enc/ivas_dirac_enc.c +++ b/lib_enc/ivas_dirac_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- * Local function prototypes @@ -70,12 +70,12 @@ ivas_error ivas_dirac_enc_open( error = IVAS_ERR_OK; - if ( ( hDirAC = (DIRAC_ENC_HANDLE) count_malloc( sizeof( DIRAC_ENC_DATA ) ) ) == NULL ) + if ( ( hDirAC = (DIRAC_ENC_HANDLE) malloc( sizeof( DIRAC_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } - if ( ( hDirAC->hConfig = (DIRAC_CONFIG_DATA_HANDLE) count_malloc( sizeof( DIRAC_CONFIG_DATA ) ) ) == NULL ) + if ( ( hDirAC->hConfig = (DIRAC_CONFIG_DATA_HANDLE) malloc( sizeof( DIRAC_CONFIG_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC Config\n" ) ); } @@ -104,7 +104,7 @@ ivas_error ivas_dirac_enc_open( return error; } /* Allocate and initialize FB mixer handle */ - if ( ( error = ivas_FB_mixer_open( &( hDirAC->hFbMixer ), input_Fs, fb_cfg ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_FB_mixer_open( &( hDirAC->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) { return error; } @@ -118,35 +118,44 @@ ivas_error ivas_dirac_enc_open( } dirac_slot_ns = DIRAC_SLOT_ENC_NS; - /* initalize delay for SPAR/DirAC delay synchronization */ + /* initialize delay for SPAR/DirAC delay synchronization */ if ( st_ivas->sba_mode == SBA_MODE_DIRAC ) { hDirAC->num_samples_synchro_delay = NS2SA( input_Fs, IVAS_FB_ENC_DELAY_NS ); - for ( i = 0; i < st_ivas->hEncoderConfig->nchan_inp; i++ ) + + for ( i = 0; i < DIRAC_MAX_ANA_CHANS; i++ ) { - hDirAC->sba_synchro_buffer[i] = (float *) count_malloc( hDirAC->num_samples_synchro_delay * sizeof( float ) ); + if ( ( hDirAC->sba_synchro_buffer[i] = (float *) malloc( hDirAC->num_samples_synchro_delay * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_zero( hDirAC->sba_synchro_buffer[i], hDirAC->num_samples_synchro_delay ); } - for ( ; i < IVAS_MAX_NUM_CH; i++ ) - { - hDirAC->sba_synchro_buffer[i] = NULL; - } } else { - for ( i = 0; i < IVAS_MAX_NUM_CH; i++ ) + hDirAC->num_samples_synchro_delay = 0; + + for ( i = 0; i < DIRAC_MAX_ANA_CHANS; i++ ) { hDirAC->sba_synchro_buffer[i] = NULL; } } + /* intensity 3-dim */ for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - hDirAC->direction_vector_m[i] = (float **) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ); + if ( ( hDirAC->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { - hDirAC->direction_vector_m[i][j] = (float *) count_malloc( DIRAC_MAX_NBANDS * sizeof( float ) ); + if ( ( hDirAC->direction_vector_m[i][j] = (float *) malloc( DIRAC_MAX_NBANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->direction_vector_m[i][j], 0.0f, DIRAC_MAX_NBANDS ); } } @@ -154,14 +163,24 @@ ivas_error ivas_dirac_enc_open( hDirAC->no_col_avg_diff = (int16_t) ( DIRAC_NO_COL_AVG_DIFF_NS / dirac_slot_ns ); for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - hDirAC->buffer_intensity_real[i] = (float **) count_malloc( hDirAC->no_col_avg_diff * sizeof( float * ) ); + if ( ( hDirAC->buffer_intensity_real[i] = (float **) malloc( hDirAC->no_col_avg_diff * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } for ( j = 0; j < hDirAC->no_col_avg_diff; j++ ) { - hDirAC->buffer_intensity_real[i][j] = (float *) count_malloc( DIRAC_MAX_NBANDS * sizeof( float ) ); + if ( ( hDirAC->buffer_intensity_real[i][j] = (float *) malloc( DIRAC_MAX_NBANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->buffer_intensity_real[i][j], 0.0f, DIRAC_MAX_NBANDS ); } } - hDirAC->buffer_energy = (float *) count_malloc( DIRAC_MAX_NBANDS * hDirAC->no_col_avg_diff * sizeof( float ) ); + + if ( ( hDirAC->buffer_energy = (float *) malloc( DIRAC_MAX_NBANDS * hDirAC->no_col_avg_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } set_f( hDirAC->buffer_energy, 0.0f, DIRAC_MAX_NBANDS * hDirAC->no_col_avg_diff ); if ( st_ivas->hQMetaData->useLowerRes ) @@ -180,8 +199,8 @@ ivas_error ivas_dirac_enc_open( if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - mvs2s( st_ivas->hDirAC->dirac_to_spar_md_bands, st_ivas->hSpar->hSparFoa->dirac_to_spar_md_bands, DIRAC_MAX_NBANDS ); - st_ivas->hSpar->hSparFoa->enc_param_start_band = st_ivas->hDirAC->hConfig->enc_param_start_band; + mvs2s( st_ivas->hDirAC->dirac_to_spar_md_bands, st_ivas->hSpar->dirac_to_spar_md_bands, DIRAC_MAX_NBANDS ); + st_ivas->hSpar->enc_param_start_band = st_ivas->hDirAC->hConfig->enc_param_start_band; } return error; @@ -226,26 +245,34 @@ ivas_error ivas_dirac_enc_reconfigure( /*------------------------------------------------------------------------- * ivas_dirac_enc_close() * - * Close DirAC + * Close DirAC encoder handle *------------------------------------------------------------------------*/ void ivas_dirac_enc_close( - DIRAC_ENC_HANDLE hDirAC, /* i/o: encoder DirAC handle */ - const int32_t input_Fs /* i : input sampling rate */ + DIRAC_ENC_HANDLE *hDirAC_out, /* i/o: encoder DirAC handle */ + const int32_t input_Fs /* i : input sampling rate */ ) { int16_t i, j; + DIRAC_ENC_HANDLE hDirAC; + + if ( hDirAC_out == NULL || *hDirAC_out == NULL ) + { + return; + } + + hDirAC = *hDirAC_out; if ( hDirAC->hFbMixer != NULL ) { - ivas_FB_mixer_close( &hDirAC->hFbMixer, input_Fs ); + ivas_FB_mixer_close( &hDirAC->hFbMixer, input_Fs, 0 ); } - for ( i = 0; i < IVAS_MAX_NUM_CH; i++ ) + for ( i = 0; i < DIRAC_MAX_ANA_CHANS; i++ ) { if ( hDirAC->sba_synchro_buffer[i] != NULL ) { - count_free( hDirAC->sba_synchro_buffer[i] ); + free( hDirAC->sba_synchro_buffer[i] ); hDirAC->sba_synchro_buffer[i] = NULL; } } @@ -255,7 +282,7 @@ void ivas_dirac_enc_close( { for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { - count_free( hDirAC->direction_vector_m[i][j] ); + free( hDirAC->direction_vector_m[i][j] ); hDirAC->direction_vector_m[i][j] = NULL; } @@ -263,28 +290,29 @@ void ivas_dirac_enc_close( { if ( hDirAC->buffer_intensity_real[i][j] != 0 ) { - count_free( hDirAC->buffer_intensity_real[i][j] ); + free( hDirAC->buffer_intensity_real[i][j] ); hDirAC->buffer_intensity_real[i][j] = NULL; } } - count_free( hDirAC->buffer_intensity_real[i] ); + free( hDirAC->buffer_intensity_real[i] ); hDirAC->buffer_intensity_real[i] = NULL; - count_free( hDirAC->direction_vector_m[i] ); + free( hDirAC->direction_vector_m[i] ); hDirAC->direction_vector_m[i] = NULL; } - count_free( hDirAC->buffer_energy ); + free( hDirAC->buffer_energy ); hDirAC->buffer_energy = NULL; if ( hDirAC->hConfig != NULL ) { - count_free( hDirAC->hConfig ); + free( hDirAC->hConfig ); hDirAC->hConfig = NULL; } - count_free( hDirAC ); + free( *hDirAC_out ); + *hDirAC_out = NULL; return; } @@ -303,19 +331,19 @@ void ivas_dirac_enc_close( *------------------------------------------------------------------------*/ void ivas_dirac_enc( - DIRAC_ENC_HANDLE hDirAC, /* i/o: encoder DirAC handle */ - IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ - BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */ - int16_t *nb_bits_metadata, /* o : number of metadata bits written */ - const int16_t Opt_DTX_ON, /* i : flag signalling DTX on */ - float data_f[][L_FRAME48k], /* i/o: input: ACN/SN3D, output: omni, stereo DMX or FOA*/ - const int16_t input_frame, /* i : input frame length */ - const int16_t sba_planar /* i : SBA planar flag */ + DIRAC_ENC_HANDLE hDirAC, /* i/o: encoder DirAC handle */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ + BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */ + int16_t *nb_bits_metadata, /* o : number of metadata bits written */ + const int16_t Opt_DTX_ON, /* i : flag signaling DTX on */ + float data_f[][L_FRAME48k], /* i/o: SBA channels */ + const int16_t input_frame, /* i : input frame length */ + const int16_t sba_planar /* i : SBA planar flag */ ) { int16_t i; - wmops_sub_start( "ivas_dirac_enc" ); + push_wmops( "ivas_dirac_enc" ); /*Check if highest band of input signal <= enc_param_start_band: could happen for WB input signal in 4TCs mode*/ if ( hDirAC->band_grouping[hDirAC->hConfig->nbands] <= hDirAC->band_grouping[hDirAC->hConfig->enc_param_start_band] ) @@ -336,7 +364,8 @@ void ivas_dirac_enc( set_zero( data_f[2], input_frame ); } - ivas_dirac_param_est_enc( hDirAC, &( hQMetaData->q_direction[0] ), hQMetaData->useLowerRes, data_f, NULL, NULL, input_frame ); + ivas_dirac_param_est_enc( hDirAC, &( hQMetaData->q_direction[0] ), hQMetaData->useLowerRes, data_f, NULL, NULL, input_frame, SBA_MODE_DIRAC ); + /* encode parameters */ if ( sba_planar || hQMetaData->useLowerRes ) { @@ -350,29 +379,7 @@ void ivas_dirac_enc( ivas_qmetadata_enc_encode( hMetaData, hQMetaData ); *nb_bits_metadata = hMetaData->nb_bits_tot; -#ifdef DEBUG_LBR_SBA - char f_name[100]; - int16_t nB = 1; - int16_t num_subframes = 1; - int16_t num_elem_per_subframe = 3; - int16_t num_block_group = 1; - int16_t byte_size = sizeof( float ); - - float dirac_kbps = (float) ( hMetaData->nb_bits_tot * 50 ) / 1000; - float sce_kbps = (float) 13.2 - dirac_kbps; - - sprintf( f_name, "DIRAC_MD_bitrate.bin" ); - ( frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elem_per_subframe, sizeof( num_elem_per_subframe ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; - dbgwrite( &dirac_kbps, byte_size, 1, 1, f_name ); - dbgwrite( &sce_kbps, byte_size, 1, 1, f_name ); - sce_kbps = (float) 16.4 - dirac_kbps; - dbgwrite( &sce_kbps, byte_size, 1, 1, f_name ); -#endif if ( Opt_DTX_ON ) { /* ToDo: If DIRAC_MIN_BITRATE_4_TRANS_CHAN is reached with DTX on (possible only with bitrate switching) @@ -433,9 +440,7 @@ void ivas_dirac_enc( } /* encode SID parameters */ - ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, -1, - SBA_FORMAT, - SBA_MODE_DIRAC ); + ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, -1, SBA_FORMAT, SBA_MODE_DIRAC ); /* restore original metadata */ hDirAC->hConfig->nbands = nbands; @@ -450,35 +455,70 @@ void ivas_dirac_enc( } else { + /*indicate whether SPAR or DiRAC mode*/ + push_next_indice( hMetaData, 0, 1 ); + /* encode SID parameters */ - ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, -1, - SBA_FORMAT, - SBA_MODE_DIRAC ); + ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, -1, SBA_FORMAT, SBA_MODE_DIRAC ); } } } - wmops_sub_end(); + pop_wmops(); return; } + /*------------------------------------------------------------------------- - * computeReferencePower_enc() - * + * ivas_dirac_enc_spar_delay_synchro() * + * Delay input channels to be synchronized between DirAC and SPAR *-------------------------------------------------------------------------*/ void ivas_dirac_enc_spar_delay_synchro( - Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ - const int16_t input_frame, /* i : input frame length */ - float data_f[][L_FRAME48k] /* i/o: input: ACN/SN3D, output: omni, stereo DMX or FOA*/ + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const int16_t input_frame, /* i : input frame length */ + float data_f[][L_FRAME48k] /* i/o: SBA channels (ACN / SN3D) */ ) { int16_t ch_idx; float tmp_buffer[L_FRAME48k]; + Encoder_State *sts[MCT_MAX_BLOCKS]; + int16_t sce_id, cpe_id, i_chan; + + /* check last sba_mode */ +#ifndef LBR_SBA + if ( ivas_sba_mode_select( st_ivas->hEncoderConfig->last_ivas_total_brate ) == SBA_MODE_SPAR ) +#else + if ( ivas_sba_mode_select( ) == SBA_MODE_SPAR ) +#endif + { + /* initializations */ + i_chan = 0; + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + sts[sce_id] = st_ivas->hSCE[sce_id]->hCoreCoder[0]; + i_chan++; + } + + for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + for ( int16_t ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts[i_chan] = st_ivas->hCPE[cpe_id]->hCoreCoder[ch]; + i_chan++; + } + } + + /* populate old synchro buffers */ + for ( ch_idx = 0; ch_idx < i_chan; ch_idx++ ) + { + mvr2r( sts[ch_idx]->input, st_ivas->hDirAC->sba_synchro_buffer[ch_idx], st_ivas->hDirAC->num_samples_synchro_delay ); + } + } - for ( ch_idx = 0; ch_idx < st_ivas->hEncoderConfig->nchan_inp; ch_idx++ ) + for ( ch_idx = 0; ch_idx < DIRAC_MAX_ANA_CHANS; ch_idx++ ) { mvr2r( data_f[ch_idx], tmp_buffer, input_frame ); mvr2r( st_ivas->hDirAC->sba_synchro_buffer[ch_idx], data_f[ch_idx], st_ivas->hDirAC->num_samples_synchro_delay ); @@ -489,6 +529,7 @@ void ivas_dirac_enc_spar_delay_synchro( return; } + /*------------------------------------------------------------------------- * computeReferencePower_enc() * @@ -501,19 +542,28 @@ void computeReferencePower_enc( float Cldfb_ImagBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], /* i : Imag part of input signal */ float *reference_power, /* o : Estimated power */ const int16_t enc_param_start_band, /* i : first band to process */ - const int16_t num_freq_bands /* i : Number of frequency bands */ + const int16_t num_freq_bands, /* i : Number of frequency bands */ + const SBA_MODE sba_mode /* i : SBA mode */ ) { int16_t brange[2]; int16_t ch_idx, i, j; + float reference_power_W[DIRAC_MAX_NBANDS]; + for ( i = 0; i < num_freq_bands; i++ ) { brange[0] = band_grouping[i + enc_param_start_band]; brange[1] = band_grouping[i + enc_param_start_band + 1]; reference_power[i] = 0; - for ( ch_idx = 0; ch_idx < DIRAC_MAX_ANA_CHANS; ch_idx++ ) + reference_power_W[i] = 0; + for ( j = brange[0]; j < brange[1]; j++ ) + { + reference_power_W[i] += ( Cldfb_RealBuffer[0][j] * Cldfb_RealBuffer[0][j] ) + ( Cldfb_ImagBuffer[0][j] * Cldfb_ImagBuffer[0][j] ); + } + reference_power[i] += reference_power_W[i]; + for ( ch_idx = 1; ch_idx < DIRAC_MAX_ANA_CHANS; ch_idx++ ) { /* abs()^2 */ for ( j = brange[0]; j < brange[1]; j++ ) @@ -524,15 +574,24 @@ void computeReferencePower_enc( } v_multc( reference_power, 0.5f, reference_power, num_freq_bands ); + if ( sba_mode == SBA_MODE_SPAR ) + { + for ( i = 0; i < num_freq_bands; i++ ) + { + reference_power[i] = max( reference_power[i], reference_power_W[i] ); + } + } return; } + /*------------------------------------------------------------------------- * ivas_dirac_param_est_enc() * * *------------------------------------------------------------------------*/ + void ivas_dirac_param_est_enc( DIRAC_ENC_HANDLE hDirAC, IVAS_QDIRECTION *q_direction, @@ -540,7 +599,8 @@ void ivas_dirac_param_est_enc( float data_f[][L_FRAME48k], float **pp_fr_real, float **pp_fr_imag, - const int16_t input_frame ) + const int16_t input_frame, + const SBA_MODE sba_mode ) { int16_t i, d, ts, index, l_ts, num_freq_bands; int16_t band_m_idx, block_m_idx; @@ -561,7 +621,7 @@ void ivas_dirac_param_est_enc( float reference_power[CLDFB_NO_COL_MAX][DIRAC_NO_FB_BANDS_MAX]; - wmops_sub_start( "dirac_enc_param_est" ); + push_wmops( "dirac_enc_param_est" ); /* Initialization */ l_ts = input_frame / MAX_PARAM_SPATIAL_SUBFRAMES; @@ -638,7 +698,8 @@ void ivas_dirac_param_est_enc( Cldfb_ImagBuffer, reference_power[ts], hDirAC->hConfig->enc_param_start_band, - num_freq_bands ); + num_freq_bands, + sba_mode ); computeIntensityVector_enc( hDirAC, @@ -741,6 +802,64 @@ void ivas_dirac_param_est_enc( } } +#ifdef DEBUG_SBA_MD_DUMP + { + char f_name[100]; + int16_t num_subframes = 1, num_block_groups = 1, num_elements = 1, byte_size = sizeof( float ); + sprintf( f_name, "dirac_enc_diffuseness.bin" ); + ( frame == 0 ) ? dbgwrite( &hDirAC->hConfig->nbands, sizeof( hDirAC->hConfig->nbands ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + dbgwrite( hDirAC->diffuseness_m, sizeof( float ), hDirAC->hConfig->nbands, 1, f_name ); + sprintf( f_name, "dirac_reference_power.bin" ); + ( frame == 0 ) ? dbgwrite( &hDirAC->hConfig->nbands, sizeof( hDirAC->hConfig->nbands ), 1, 1, f_name ) : false; + num_elements = hDirAC->block_grouping[1] - hDirAC->block_grouping[0]; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + num_block_groups = hDirAC->block_grouping[1]; + ( frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( ts = hDirAC->block_grouping[0]; ts < hDirAC->block_grouping[1]; ts++ ) + { + dbgwrite( reference_power[ts], sizeof( float ), hDirAC->hConfig->nbands, 1, f_name ); + } + num_elements = 1; + num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + num_block_groups = 1; + sprintf( f_name, "dirac_enc_dir0.bin" ); + ( frame == 0 ) ? dbgwrite( &hDirAC->hConfig->nbands, sizeof( hDirAC->hConfig->nbands ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + { + dbgwrite( hDirAC->direction_vector_m[0][block_m_idx], sizeof( float ), hDirAC->hConfig->nbands, 1, f_name ); + } + sprintf( f_name, "dirac_enc_dir1.bin" ); + ( frame == 0 ) ? dbgwrite( &hDirAC->hConfig->nbands, sizeof( hDirAC->hConfig->nbands ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + { + dbgwrite( hDirAC->direction_vector_m[1][block_m_idx], sizeof( float ), hDirAC->hConfig->nbands, 1, f_name ); + } + sprintf( f_name, "dirac_enc_dir2.bin" ); + ( frame == 0 ) ? dbgwrite( &hDirAC->hConfig->nbands, sizeof( hDirAC->hConfig->nbands ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + { + dbgwrite( hDirAC->direction_vector_m[2][block_m_idx], sizeof( float ), hDirAC->hConfig->nbands, 1, f_name ); + } + } +#endif #ifdef DEBUG_MODE_DIRAC { static FILE *fp_direction_vector = NULL, *fp_diffuseness = NULL, *fp_referencePower = NULL; @@ -778,7 +897,7 @@ void ivas_dirac_param_est_enc( } #endif - wmops_sub_end(); + pop_wmops(); return; } @@ -805,6 +924,7 @@ static void computeIntensityVector_enc( int16_t i, j; float real, img; int16_t brange[2]; + for ( i = 0; i < num_frequency_bands; i++ ) { brange[0] = hDirAC->band_grouping[i + enc_param_start_band]; diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index a1364d75df9893e0f1cbd422f2894280bd5b3c7f..535a1196abf8aaefbb6dda220bbfe4088bc98513 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * ivas_enc() @@ -65,10 +65,9 @@ ivas_error ivas_enc( float data_f[MAX_INPUT_CHANNELS][L_FRAME48k]; /* IVAS_fmToDo: buffer can be allocated dynamically based on the number of analysed channels */ int32_t ivas_total_brate; ivas_error error; - error = IVAS_ERR_OK; - wmops_sub_start( "ivas_enc" ); + push_wmops( "ivas_enc" ); /*------------------------------------------------------------------* * Initialization - general @@ -128,11 +127,16 @@ ivas_error ivas_enc( *----------------------------------------------------------------*/ n = getNumChanAnalysis( st_ivas ); + #ifndef DEBUG_SPAR_BYPASS_EVS_CODEC /* bypass EVS coding in float precision, emulating EVS encoder/decoder delay */ for ( i = 0; i < n; i++ ) { - if ( !( ivas_format == MC_FORMAT && i == LFE_CHANNEL ) ) /*TODO: is the HPF needed for LFE channel? */ + if ( ( ivas_format == SBA_FORMAT ) && ( st_ivas->sba_mode == SBA_MODE_SPAR ) ) + { + hp20( data_f[HOA_keep_ind[i]], input_frame, st_ivas->mem_hp20_in[i], input_Fs ); + } + else if ( !( ivas_format == MC_FORMAT && i == LFE_CHANNEL ) ) /*TODO: is the HPF needed for LFE channel? */ { hp20( data_f[i], input_frame, st_ivas->mem_hp20_in[i], input_Fs ); } @@ -160,7 +164,10 @@ ivas_error ivas_enc( else if ( ivas_format == ISM_FORMAT ) { /* select ISM format mode; reconfigure the ISM format encoder */ - ivas_ism_enc_config( st_ivas ); + if ( ( ivas_ism_enc_config( st_ivas ) ) ) + { + return error; + } if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { @@ -189,24 +196,18 @@ ivas_error ivas_enc( /* SBA/MASA configuration */ if ( ivas_format == SBA_FORMAT ) { - if ( st_ivas->sba_mode == SBA_MODE_DIRAC ) + if ( ( error = ivas_sba_enc_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) { - if ( ( error = ivas_sba_enc_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } - if ( !( st_ivas->sba_mode == SBA_MODE_SPAR && ivas_total_brate < IVAS_256k ) ) - { - st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; + st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; - /* Write SBA planar flag */ - push_indice( st->hBstr, IND_SMODE, hEncoderConfig->sba_planar, SBA_PLANAR_BITS ); + /* Write SBA planar flag */ + push_indice( st->hBstr, IND_SMODE, hEncoderConfig->sba_planar, SBA_PLANAR_BITS ); - /* Write SBA order */ - push_indice( st->hBstr, IND_SMODE, hEncoderConfig->sba_order, SBA_ORDER_BITS ); - } + /* Write SBA order */ + push_indice( st->hBstr, IND_SMODE, hEncoderConfig->sba_order, SBA_ORDER_BITS ); } else { @@ -226,15 +227,21 @@ ivas_error ivas_enc( } else { +#ifdef FIX_382_MASA_META_FRAMING_ASYNC + ivas_masa_estimate_energy( st_ivas->hMasa, data_f, input_frame, st_ivas->nchan_transport ); /* energy-estimation uses TF-resolution: 4x24 */ +#endif if ( ( error = ivas_masa_enc_config( st_ivas ) ) != IVAS_ERR_OK ) { return error; } - - ivas_masa_estimate_energy( st_ivas->hMasa, data_f, input_frame, st_ivas->nchan_transport ); - - ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, - ivas_total_brate, hEncoderConfig->Opt_DTX_ON, st_ivas->nchan_transport == 2 ? st_ivas->hCPE[0]->element_mode : -1 ); +#ifndef FIX_382_MASA_META_FRAMING_ASYNC + ivas_masa_estimate_energy( st_ivas->hMasa, data_f, input_frame, st_ivas->nchan_transport ); /* energy-estimation uses TF-resolution: 4x24 */ +#endif + if ( ( error = ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, + ivas_total_brate, hEncoderConfig->Opt_DTX_ON, st_ivas->nchan_transport == 2 ? st_ivas->hCPE[0]->element_mode : -1 ) ) != IVAS_ERR_OK ) + { + return error; + } } } else if ( st_ivas->sba_mode == SBA_MODE_SPAR ) @@ -253,50 +260,10 @@ ivas_error ivas_enc( /* core-coding of transport channels */ if ( st_ivas->nSCE == 1 ) { -#ifdef DEBUG_LBR_SBA -#ifndef LBR_SBA - for ( int t = 0; t < 960; t++ ) - { - for ( int c = 0; c < 1; c++ ) - { - float val = data_f[c][t] / MAX16B_FLT; - dbgwrite( &val, sizeof( float ), 1, 1, "int_enc_dmx.raw" ); - } - } -#endif -#endif if ( ( error = ivas_sce_enc( st_ivas, 0, data_f[0], input_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) { return error; } -#ifdef DEBUG_LBR_SBA - /* Dumping SPAR Coefficients */ - char f_name[100]; - int16_t nbands = 1; - int16_t num_subframes = 1; - int16_t num_elements = 1; - int16_t num_block_group = 1; - int16_t byte_size = sizeof( int16_t ); - - sprintf( f_name, "SCE_code_element.bin" ); - ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; - - for ( int16_t b = 0; b < nbands; b++ ) - { - for ( int16_t sf = 0; sf < num_subframes; sf++ ) - { - for ( int16_t bl = 0; bl < num_block_group; bl++ ) - { - dbgwrite( &st_ivas->hSCE[0]->hCoreCoder[0]->core, byte_size, 1, 1, f_name ); - // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); - } - } - } -#endif } else if ( st_ivas->nCPE == 1 ) /* Stereo DMX */ { @@ -316,7 +283,10 @@ ivas_error ivas_enc( else if ( ivas_format == MC_FORMAT ) { /* select MC format mode; write MC LS setup; reconfigure the MC format encoder */ - ivas_mc_enc_config( st_ivas ); + if ( ( ivas_mc_enc_config( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } hMetaData = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData : st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData; @@ -363,7 +333,10 @@ ivas_error ivas_enc( ivas_mcmasa_enc( st_ivas->hMcMasa, st_ivas->hQMetaData, st_ivas->hMasa, data_f, input_frame, st_ivas->nchan_transport, nchan_inp ); - ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, ivas_total_brate, 0, -1 ); + if ( ( error = ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, ivas_total_brate, 0, -1 ) ) != IVAS_ERR_OK ) + { + return error; + } if ( st_ivas->hMcMasa->separateChannelEnabled ) { @@ -385,36 +358,6 @@ ivas_error ivas_enc( { return error; } -#ifndef LBR_SBA -#ifdef DEBUG_LBR_SBA - /* Dumping SPAR Coefficients */ - char f_name[100]; - int16_t nbands = 1; - int16_t num_subframes = 1; - int16_t num_elements = 1; - int16_t num_block_group = 1; - int16_t byte_size = sizeof( int16_t ); - - sprintf( f_name, "SCE_code_element.bin" ); - ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; - - for ( int16_t b = 0; b < nbands; b++ ) - { - for ( int16_t sf = 0; sf < num_subframes; sf++ ) - { - for ( int16_t bl = 0; bl < num_block_group; bl++ ) - { - dbgwrite( &st_ivas->hSCE[0]->hCoreCoder[0]->core, byte_size, 1, 1, f_name ); - // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); - } - } - } -#endif -#endif } else if ( st_ivas->nCPE == 1 ) /* Stereo DMX */ { @@ -440,6 +383,6 @@ ivas_error ivas_enc( } #endif - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_enc/ivas_enc_cov_handler.c b/lib_enc/ivas_enc_cov_handler.c index 51835de0c36c1a2d2538f1544b39b5fb0e487b99..0e7f2f9559511dcfca6064d68066de2d61642ffa 100644 --- a/lib_enc/ivas_enc_cov_handler.c +++ b/lib_enc/ivas_enc_cov_handler.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* * Local constants @@ -48,9 +48,11 @@ #define MIN_POOL_SIZE_DTX 40 #define MAX_UPDATE_RATE_DTX 0.4f + /*------------------------------------------------------------------------------------------* * Local functions declarations *------------------------------------------------------------------------------------------*/ + static void ivas_band_cov( float **ppIn_FR_real, float **ppIn_FR_imag, const int16_t num_chans, const int16_t num_bins, int16_t stride, float **pFb_bin_to_band, const int16_t *pFb_start_bin_per_band, const int16_t *pFb_active_bins_per_band, const int16_t start_band, const int16_t end_band, float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH] ); /*------------------------------------------------------------------------- @@ -76,7 +78,7 @@ ivas_error ivas_spar_covar_enc_open( error = IVAS_ERR_OK; - if ( ( hCovState = (ivas_enc_cov_handler_state_t *) count_malloc( sizeof( ivas_enc_cov_handler_state_t ) ) ) == NULL ) + if ( ( hCovState = (ivas_enc_cov_handler_state_t *) malloc( sizeof( ivas_enc_cov_handler_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder" ); } @@ -84,6 +86,7 @@ ivas_error ivas_spar_covar_enc_open( cov_smooth_cfg.max_bands = IVAS_MAX_NUM_BANDS; cov_smooth_cfg.max_update_rate = MAX_UPDATE_RATE; cov_smooth_cfg.min_pool_size = MIN_POOL_SIZE; + #ifdef LBR_SBA_EXTRA_COV_SMOOTH if ( ( error = ivas_spar_covar_smooth_enc_open( &hCovState->pCov_state, &cov_smooth_cfg, pFb, nchan_inp, ivas_total_brate ) ) != IVAS_ERR_OK ) #else @@ -95,6 +98,7 @@ ivas_error ivas_spar_covar_enc_open( cov_smooth_cfg.max_update_rate = MAX_UPDATE_RATE_DTX; cov_smooth_cfg.min_pool_size = MIN_POOL_SIZE_DTX; + #ifdef LBR_SBA_EXTRA_COV_SMOOTH if ( ( error = ivas_spar_covar_smooth_enc_open( &hCovState->pCov_dtx_state, &cov_smooth_cfg, pFb, nchan_inp, ivas_total_brate ) ) != IVAS_ERR_OK ) #else @@ -125,17 +129,19 @@ void ivas_spar_covar_enc_close( { ivas_enc_cov_handler_state_t *hCovState; + if ( hCovEnc == NULL || *hCovEnc == NULL ) + { + return; + } + hCovState = *hCovEnc; - if ( hCovState != NULL ) - { - ivas_spar_covar_smooth_enc_close( &hCovState->pCov_state, nchan_inp ); + ivas_spar_covar_smooth_enc_close( &hCovState->pCov_state, nchan_inp ); - ivas_spar_covar_smooth_enc_close( &hCovState->pCov_dtx_state, nchan_inp ); + ivas_spar_covar_smooth_enc_close( &hCovState->pCov_dtx_state, nchan_inp ); - count_free( hCovState ); - hCovState = NULL; - } + free( *hCovEnc ); + *hCovEnc = NULL; return; } @@ -149,27 +155,30 @@ void ivas_spar_covar_enc_close( void ivas_enc_cov_handler_process( ivas_enc_cov_handler_state_t *hCovEnc, /* i/o: SPAR Covar. encoder handle */ - ivas_enc_cov_handler_in_buf_t *pIn_buf, + float **ppIn_FR_real, + float **ppIn_FR_imag, float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], ivas_filterbank_t *pFb, /* i/o: FB handle */ const int16_t start_band, - const int16_t end_band ) + const int16_t end_band, + const int16_t num_ch, + const int16_t dtx_vad, + const int16_t transient_det[2] ) { int16_t i, j; - ivas_cov_smooth_in_buf_t pCov_in_buf; - int16_t num_ch = pIn_buf->num_ch; - ivas_enc_cov_handler_state_t *pState = hCovEnc; + int16_t dtx_cov_flag; - pCov_in_buf.num_ch = num_ch; + dtx_cov_flag = ( dtx_vad == 1 ) ? 0 : 1; - ivas_band_cov( pIn_buf->ppIn_FR_real, pIn_buf->ppIn_FR_imag, pIn_buf->num_ch, pState->num_bins, + ivas_band_cov( ppIn_FR_real, ppIn_FR_imag, num_ch, hCovEnc->num_bins, pFb->fb_bin_to_band.short_stride, pFb->fb_bin_to_band.pp_short_stride_bin_to_band, pFb->fb_bin_to_band.p_short_stride_start_bin_per_band, pFb->fb_bin_to_band.p_short_stride_num_bins_per_band, start_band, end_band, cov_real ); + #ifdef DEBUG_SPAR_WRITE_OUT_COV { static FILE *fid = 0; @@ -197,68 +206,38 @@ void ivas_enc_cov_handler_process( { for ( j = 0; j < num_ch; j++ ) { - pCov_in_buf.cov_real[i][j] = cov_real[i][j]; - mvr2r( cov_real[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); } } - pCov_in_buf.reset_cov = 0; - if ( pIn_buf->transient_det == 1 ) - { - pCov_in_buf.reset_cov = 1; - } - - ivas_cov_smooth_process( pState->pCov_state, &pCov_in_buf, pFb, - start_band, end_band ); + ivas_cov_smooth_process( hCovEnc->pCov_state, cov_real, pFb, start_band, end_band, num_ch, transient_det ); - if ( pIn_buf->dtx_cov_flag == 0 ) + if ( dtx_cov_flag == 0 ) { for ( i = 0; i < num_ch; i++ ) { for ( j = 0; j < num_ch; j++ ) { - mvr2r( pCov_in_buf.cov_real[i][j], pState->pCov_dtx_state->pPrior_cov_real[i][j], pFb->filterbank_num_bands ); - mvr2r( pCov_in_buf.cov_real[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); + mvr2r( cov_real[i][j], hCovEnc->pCov_dtx_state->pPrior_cov_real[i][j], pFb->filterbank_num_bands ); + mvr2r( cov_real[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); } } - pState->prior_dtx_present = 1; + hCovEnc->prior_dtx_present = 1; } else { - - if ( pIn_buf->transient_det == 0 ) + if ( ( transient_det[0] == 0 ) && ( transient_det[1] == 0 ) ) { - for ( i = 0; i < num_ch; i++ ) - { - for ( j = 0; j < num_ch; j++ ) - { - pCov_in_buf.cov_real[i][j] = cov_dtx_real[i][j]; - } - } - - pCov_in_buf.reset_cov = 0; - ivas_cov_smooth_process( pState->pCov_dtx_state, &pCov_in_buf, pFb, - start_band, end_band ); - pState->prior_dtx_present = 1; + ivas_cov_smooth_process( hCovEnc->pCov_dtx_state, cov_dtx_real, pFb, start_band, end_band, num_ch, transient_det ); + hCovEnc->prior_dtx_present = 1; } else { - if ( pState->prior_dtx_present == 0 ) + if ( hCovEnc->prior_dtx_present == 0 ) { - for ( i = 0; i < num_ch; i++ ) - { - for ( j = 0; j < num_ch; j++ ) - { - pCov_in_buf.cov_real[i][j] = cov_dtx_real[i][j]; - } - } - - pCov_in_buf.reset_cov = 1; - ivas_cov_smooth_process( pState->pCov_dtx_state, &pCov_in_buf, pFb, - start_band, end_band ); - pState->prior_dtx_present = 1; + ivas_cov_smooth_process( hCovEnc->pCov_dtx_state, cov_dtx_real, pFb, start_band, end_band, num_ch, transient_det ); + hCovEnc->prior_dtx_present = 1; } else { @@ -266,11 +245,11 @@ void ivas_enc_cov_handler_process( { for ( j = 0; j < num_ch; j++ ) { - mvr2r( pState->pCov_dtx_state->pPrior_cov_real[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); + mvr2r( hCovEnc->pCov_dtx_state->pPrior_cov_real[i][j], cov_dtx_real[i][j], pFb->filterbank_num_bands ); } } - pState->prior_dtx_present = 1; + hCovEnc->prior_dtx_present = 1; } } } @@ -278,6 +257,7 @@ void ivas_enc_cov_handler_process( return; } + static void ivas_band_cov( float **ppIn_FR_real, float **ppIn_FR_imag, @@ -303,14 +283,18 @@ static void ivas_band_cov( { pV_re[k] = ppIn_FR_real[i][k] * ppIn_FR_real[j][k] + ppIn_FR_imag[i][k] * ppIn_FR_imag[j][k]; } + for ( k = start_band; k < end_band; k++ ) { float temp = 0.0f; const float *p_bin_to_band = pFb_bin_to_band[k]; float *cov_ptr = pV_re; - int16_t num_blocks = num_bins / stride; + int16_t num_blocks; + + num_blocks = num_bins / stride; start_bin = pFb_start_bin_per_band[k]; active_bins = pFb_active_bins_per_band[k]; + for ( int16_t blk = 0; blk < num_blocks; blk++ ) { /* optional: add temporal weight here */ diff --git a/lib_enc/ivas_entropy_coder.c b/lib_enc/ivas_entropy_coder.c index 3236e528a91c047245ef2e92d736394481a6106b..a8f5219f2a3f692b44e6edfcfbfce3771d0a8315 100644 --- a/lib_enc/ivas_entropy_coder.c +++ b/lib_enc/ivas_entropy_coder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,12 +41,7 @@ #include "ivas_rom_com.h" #include "math.h" #include -#include "wmops.h" - -#ifdef DEBUG_SPAR_FOA -#define MREF_BPS_TOL ( 2e-4 ) -extern FILE *fModels_data; -#endif +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* * Local constants @@ -55,107 +50,6 @@ extern FILE *fModels_data; #define IVAS_MAX_ENCODED_BITS ( 150 ) -/*---------------------------------------------------------------------------------------- - * - * Function ivas_arith_enc_init() - * - * arith coder init - *---------------------------------------------------------------------------------------- - */ - -static void ivas_arith_enc_init( - ivas_arith_t *pArith, - const ivas_freq_models_t *pFreq_models, - ivas_arith_t *pArith_diff, - const int16_t q_levels ) -{ - int16_t i, j; - float sum = 0; - - pArith->vals = pFreq_models->vals; - pArith->range = q_levels; - pArith->num_models = pFreq_models->num_models; - pArith->dyn_model_bits = ivas_get_bits_to_encode( pArith->num_models - 1 ); - pArith->pFreq_model = pFreq_models->freq_model[0]; - ivas_get_cum_freq_model( pArith->pFreq_model, pArith->range, pArith->cum_freq[0] ); - - for ( i = 0; i < pArith->num_models - 1; i++ ) - { - pArith->pAlt_freq_models[i] = pFreq_models->freq_model[i + 1]; - ivas_get_cum_freq_model( pArith->pAlt_freq_models[i], pArith->range, pArith->cum_freq[i + 1] ); - } - - for ( i = 1; i < pArith->range + 1; i++ ) - { - sum += pArith->pFreq_model[i]; - } - - for ( i = 1; i < pArith->range + 1; i++ ) - { - pArith->saved_dist_arr[0][i - 1] = log2f( max( 1e-10f, pArith->pFreq_model[i] ) ); - pArith->saved_dist_arr[0][i - 1] -= log2f( max( 1e-10f, sum ) ); - } - - for ( j = 0; j < pArith->num_models - 1; j++ ) - { - sum = 0; - - for ( i = 1; i < pArith->range + 1; i++ ) - { - sum += pArith->pAlt_freq_models[j][i]; - } - - for ( i = 1; i < pArith->range + 1; i++ ) - { - pArith->saved_dist_arr[j + 1][i - 1] = log2f( max( 1e-10f, pArith->pAlt_freq_models[j][i] ) ); - pArith->saved_dist_arr[j + 1][i - 1] -= log2f( max( 1e-10f, sum ) ); - } - } - - pArith_diff->vals = pFreq_models->diff_vals; - pArith_diff->range = q_levels; - pArith_diff->num_models = pFreq_models->diff_num_models; - pArith_diff->dyn_model_bits = ivas_get_bits_to_encode( pArith_diff->num_models - 1 ); - pArith_diff->pFreq_model = pFreq_models->diff_freq_model[0]; - ivas_get_cum_freq_model( pArith_diff->pFreq_model, pArith_diff->range, pArith_diff->cum_freq[0] ); - - sum = 0; - - for ( i = 0; i < pArith_diff->num_models - 1; i++ ) - { - pArith_diff->pAlt_freq_models[i] = pFreq_models->diff_freq_model[i + 1]; - ivas_get_cum_freq_model( pArith_diff->pAlt_freq_models[i], pArith_diff->range, pArith_diff->cum_freq[i + 1] ); - } - - for ( i = 1; i < pArith_diff->range + 1; i++ ) - { - sum += pArith_diff->pFreq_model[i]; - } - - for ( i = 1; i < pArith_diff->range + 1; i++ ) - { - pArith_diff->saved_dist_arr[0][i - 1] = log2f( max( 1e-10f, pArith_diff->pFreq_model[i] ) ); - pArith_diff->saved_dist_arr[0][i - 1] -= log2f( max( 1e-10f, sum ) ); - } - - for ( j = 0; j < pArith_diff->num_models - 1; j++ ) - { - sum = 0; - - for ( i = 1; i < pArith_diff->range + 1; i++ ) - { - sum += pArith_diff->pAlt_freq_models[j][i]; - } - - for ( i = 1; i < pArith_diff->range + 1; i++ ) - { - pArith_diff->saved_dist_arr[j + 1][i - 1] = log2f( max( 1e-10f, pArith_diff->pAlt_freq_models[j][i] ) ); - pArith_diff->saved_dist_arr[j + 1][i - 1] -= log2f( max( 1e-10f, sum ) ); - } - } - - return; -} - - /*-----------------------------------------------------------------------------------------* * Function ivas_get_dyn_freq_model() * @@ -223,29 +117,6 @@ static ivas_error ivas_get_dyn_freq_model( *ppCum_freq = pArith->cum_freq[0]; } -#ifdef DEBUG_SPAR_FOA - if ( fModels_data != NULL ) - { - float ref_min_bps = 0; - int32_t ref_model_idx = 0; - fscanf( fModels_data, "%f\n", &ref_min_bps ); - fscanf( fModels_data, "%d\n", &ref_model_idx ); - - if ( fabs( curr_bps_min - ref_min_bps ) > MREF_BPS_TOL ) - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "SPAR FOA model selection min BPS mismatch: %f, ref: %f, diff: %f \n", curr_bps_min, ref_min_bps, curr_bps_min - ref_min_bps ); - } - else - { - if ( model_idx != ref_model_idx ) - { - model_idx = (int16_t) ref_model_idx; - *ppCum_freq = pArith->cum_freq[model_idx]; - } - } - } -#endif - *model_index = model_idx; return error; @@ -352,60 +223,6 @@ void ivas_huffman_encode( } -/*-----------------------------------------------------------------------------------------* - * Function ivas_arith_coeffs_enc_init() - * - * Init for Arithm. coding - *-----------------------------------------------------------------------------------------*/ - -void ivas_arith_coeffs_enc_init( - ivas_arith_coeffs_t *pArith_coeffs, - ivas_spar_foa_md_com_cfg *pSpar_cfg, - const int16_t table_idx ) -{ - int16_t i; - - for ( i = 0; i < MAX_QUANT_STRATS; i++ ) - { - ivas_arith_enc_init( &pArith_coeffs->pred_arith_re[i], &ivas_arith_consts[table_idx][i].pred_r, - &pArith_coeffs->pred_arith_re_diff[i], pSpar_cfg->quant_strat[i].PR.q_levels[0] ); - - ivas_arith_enc_init( &pArith_coeffs->drct_arith_re[i], &ivas_arith_consts[table_idx][i].drct_r, - &pArith_coeffs->drct_arith_re_diff[i], pSpar_cfg->quant_strat[i].C.q_levels[0] ); - - ivas_arith_enc_init( &pArith_coeffs->decd_arith_re[i], &ivas_arith_consts[table_idx][i].decd_r, - &pArith_coeffs->decd_arith_re_diff[i], pSpar_cfg->quant_strat[i].P_r.q_levels[0] ); - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_huff_coeffs_enc_init() - * - * Init for Huffman coding - *-----------------------------------------------------------------------------------------*/ - -void ivas_huff_coeffs_enc_init( - ivas_huff_coeffs_t *pHuff_coeffs, - const int16_t table_idx ) -{ - int16_t i; - - for ( i = 0; i < MAX_QUANT_STRATS; i++ ) - { - pHuff_coeffs->pred_huff_re[i].codebook = &ivas_huff_const[table_idx][i].pred_r.code_book[0][0]; - - pHuff_coeffs->drct_huff_re[i].codebook = &ivas_huff_const[table_idx][i].drct_r.code_book[0][0]; - - pHuff_coeffs->decd_huff_re[i].codebook = &ivas_huff_const[table_idx][i].decd_r.code_book[0][0]; - } - - return; -} - - /*-----------------------------------------------------------------------------------------* * Function arith_encode_cell_array() * @@ -499,11 +316,13 @@ void ivas_arith_encode_cmplx_cell_array( int16_t input[IVAS_MAX_INPUT_LEN]; ivas_cell_dim_t cell_dim[IVAS_MAX_NUM_BANDS], cell_dim_diff[IVAS_MAX_NUM_BANDS]; int16_t len, idx, i, j, idx1; + int16_t total_len; idx1 = 0; if ( any_diff == 1 ) { idx = 0; + total_len = 0; for ( i = 0; i < nB; i++ ) { len = ( pCell_dims[i].dim1 * pCell_dims[i].dim2 ); @@ -511,8 +330,8 @@ void ivas_arith_encode_cmplx_cell_array( { for ( j = 0; j < len; j++ ) { - input_old[idx] = pSymbol_old_re[i * len + j]; - input_new[idx++] = pSymbol_re[i * len + j]; + input_old[idx] = pSymbol_old_re[total_len + j]; + input_new[idx++] = pSymbol_re[total_len + j]; } cell_dim_diff[i].dim1 = pCell_dims[i].dim1; cell_dim_diff[i].dim2 = pCell_dims[i].dim2; @@ -523,13 +342,14 @@ void ivas_arith_encode_cmplx_cell_array( { for ( j = 0; j < len; j++ ) { - input[idx1++] = pSymbol_re[i * len + j]; + input[idx1++] = pSymbol_re[total_len + j]; } cell_dim_diff[i].dim1 = 0; cell_dim_diff[i].dim2 = 0; cell_dim[i].dim1 = pCell_dims[i].dim1; cell_dim[i].dim2 = pCell_dims[i].dim2; } + total_len += len; } #ifdef SPAR_HOA_DBG /*if ( 0 )*/ /*(pCell_dims[0].dim1 == 12)*/ diff --git a/lib_enc/ivas_front_vad.c b/lib_enc/ivas_front_vad.c index 09fd624ca50d92248fb93043731aad97a5e47c7c..be476b1244c1bd897f14d76ac2ac4879e106e3ff 100644 --- a/lib_enc/ivas_front_vad.c +++ b/lib_enc/ivas_front_vad.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "ivas_prot.h" #include -#include "wmops.h" +#include "wmc_auto.h" #include @@ -57,7 +57,7 @@ ivas_error front_vad( Encoder_State *st, /* i/o: encoder state structure */ const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ FRONT_VAD_ENC_HANDLE *hFrontVads, /* i/o: FrontVad handles */ - const int16_t hMCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int16_t input_frame, /* i : frame length */ int16_t vad_flag_dtx[], /* o : HE-SAD flag with additional DTX HO */ float fr_bands[][2 * NB_BANDS], /* i : energy in frequency bands */ @@ -83,7 +83,7 @@ ivas_error front_vad( error = IVAS_ERR_OK; - wmops_sub_start( "front_vad" ); + push_wmops( "front_vad" ); if ( hCPE != NULL ) { @@ -110,13 +110,14 @@ ivas_error front_vad( { localVAD_HE_SAD[n] = 0; vad_hover_flag[n] = 0; + vad_flag_dtx[n] = 1; } /*------------------------------------------------------------------* * Allocate/deallocate hFrontVad handles in case of element_mode change *-----------------------------------------------------------------*/ - if ( sts[0]->ini_frame > 0 && hMCT_flag == 0 && last_element_mode != element_mode ) + if ( sts[0]->ini_frame > 0 && MCT_flag == 0 && last_element_mode != element_mode ) { if ( element_mode == IVAS_CPE_MDCT ) { @@ -192,7 +193,7 @@ ivas_error front_vad( } /* DTX hangover addition */ - vad_flag_dtx[n] = dtx_hangover_addition( sts[n], hFrontVad->hVAD->vad_flag, hFrontVad->lp_speech - hFrontVad->lp_noise, 0 /* <- no cldfb addition */, &vad_hover_flag[n], hFrontVad->hVAD, hFrontVad->hNoiseEst ); + vad_flag_dtx[n] = dtx_hangover_addition( sts[n], hFrontVad->hVAD->vad_flag, hFrontVad->lp_speech - hFrontVad->lp_noise, 0 /* <- no cldfb addition */, &vad_hover_flag[n], hFrontVad->hVAD, hFrontVad->hNoiseEst, &hFrontVads[n]->rem_dtx_ho ); if ( n_chan == 1 ) { @@ -248,7 +249,7 @@ ivas_error front_vad( mvr2r( Bin_E, Bin_E_out, L_FRAME ); } - wmops_sub_end(); + pop_wmops(); return error; } @@ -266,18 +267,18 @@ ivas_error front_vad_create( { FRONT_VAD_ENC_HANDLE hFrontVad; - if ( ( hFrontVad = (FRONT_VAD_ENC_HANDLE) count_malloc( sizeof( FRONT_VAD_ENC ) ) ) == NULL ) + if ( ( hFrontVad = (FRONT_VAD_ENC_HANDLE) malloc( sizeof( FRONT_VAD_ENC ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for front-VAD structure \n" ) ); } - if ( ( hFrontVad->hNoiseEst = (NOISE_EST_HANDLE) count_malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) + if ( ( hFrontVad->hNoiseEst = (NOISE_EST_HANDLE) malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ) ); } noise_est_init( hFrontVad->hNoiseEst ); - if ( ( hFrontVad->hVAD = (VAD_HANDLE) count_malloc( sizeof( VAD_DATA ) ) ) == NULL ) + if ( ( hFrontVad->hVAD = (VAD_HANDLE) malloc( sizeof( VAD_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n" ) ); } @@ -296,7 +297,7 @@ ivas_error front_vad_create( hFrontVad->delay_buf = NULL; if ( hFrontVad->delay_samples > 0 ) { - if ( ( hFrontVad->delay_buf = (float *) count_malloc( hFrontVad->delay_samples * sizeof( float ) ) ) == NULL ) + if ( ( hFrontVad->delay_buf = (float *) malloc( hFrontVad->delay_samples * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD delay buffer\n" ) ); } @@ -322,19 +323,19 @@ void front_vad_destroy( { if ( *hFrontVad != NULL ) { - count_free( ( *hFrontVad )->hNoiseEst ); + free( ( *hFrontVad )->hNoiseEst ); ( *hFrontVad )->hNoiseEst = NULL; - count_free( ( *hFrontVad )->hVAD ); + free( ( *hFrontVad )->hVAD ); ( *hFrontVad )->hVAD = NULL; if ( ( *hFrontVad )->delay_buf != NULL ) { - count_free( ( *hFrontVad )->delay_buf ); + free( ( *hFrontVad )->delay_buf ); ( *hFrontVad )->delay_buf = NULL; } - count_free( *hFrontVad ); + free( *hFrontVad ); *hFrontVad = NULL; } @@ -389,14 +390,14 @@ ivas_error front_vad_spar( int16_t old_pitch; ivas_error error; - wmops_sub_start( "front_vad_SPAR" ); + push_wmops( "front_vad_SPAR" ); error = IVAS_ERR_OK; hFrontVad = hSpar->hFrontVad; st = hSpar->hCoreCoderVAD; - if ( hEncoderConfig->Opt_DTX_ON && hEncoderConfig->ivas_total_brate <= IVAS_80k ) + if ( hEncoderConfig->Opt_DTX_ON && hEncoderConfig->ivas_total_brate <= SBA_DTX_BITRATE_THRESHOLD ) { /*------------------------------------------------------------------* * Initialization @@ -422,7 +423,7 @@ ivas_error front_vad_spar( * Front-VAD *-----------------------------------------------------------------*/ - if ( ( error = front_vad( NULL, st, hEncoderConfig, &hFrontVad, 0 /* hMCT_flag */, input_frame, vad_flag_dtx, fr_bands, Etot, lf_E, localVAD_HE_SAD, vad_hover_flag, band_energies, &PS[0], &st->Bin_E[0] ) ) != IVAS_ERR_OK ) + if ( ( error = front_vad( NULL, st, hEncoderConfig, &hFrontVad, 0 /* MCT_flag */, input_frame, vad_flag_dtx, fr_bands, Etot, lf_E, localVAD_HE_SAD, vad_hover_flag, band_energies, &PS[0], &st->Bin_E[0] ) ) != IVAS_ERR_OK ) { return error; } @@ -430,7 +431,7 @@ ivas_error front_vad_spar( noise_est_down( fr_bands[0], hFrontVad->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &hFrontVad->hNoiseEst->totalNoise, Etot[0], &hFrontVad->hNoiseEst->Etot_last, &hFrontVad->hNoiseEst->Etot_v_h2 ); corr_shift = correlation_shift( hFrontVad->hNoiseEst->totalNoise ); - dtx( st, vad_flag_dtx[0], inp_12k8 ); + dtx( st, hEncoderConfig->ivas_total_brate, vad_flag_dtx[0], inp_12k8 ); /* linear prediction analysis */ alw_pitch_lag_12k8[0] = st->old_pitch_la; @@ -471,11 +472,10 @@ ivas_error front_vad_spar( /* 1st stage speech/music classification (GMM model) */ /* run only to get 'high_lpn_flag' parameter */ - ivas_smc_gmm( st, NULL /* <-- hStereoClassif */, localVAD_HE_SAD[0], *Etot, lsp_new, cor_map_sum, epsP, PS, non_staX, relE, &high_lpn_flag, flag_spitch ); + ivas_smc_gmm( st, NULL, localVAD_HE_SAD[0], Etot[0], lsp_new, cor_map_sum, epsP, PS, non_staX, relE, &high_lpn_flag, flag_spitch ); /* long-term energy update */ - long_enr( st, *Etot, localVAD_HE_SAD[0], high_lpn_flag, &hFrontVad, 1, localVAD_HE_SAD, Etot ); - hFrontVad->hNoiseEst->Etot_last = Etot[0]; + long_enr( st, -1, localVAD_HE_SAD[0], high_lpn_flag, &hFrontVad, 1, localVAD_HE_SAD, Etot ); /* increase ini_frame counter */ hFrontVad->ini_frame = min( hFrontVad->ini_frame + 1, MAX_FRAME_COUNTER ); @@ -497,7 +497,7 @@ ivas_error front_vad_spar( hSpar->force_front_vad = 0; } - wmops_sub_end(); + pop_wmops(); return error; } diff --git a/lib_enc/ivas_init_enc.c b/lib_enc/ivas_init_enc.c index 5949e5ceabdc5962a3e375262a38b376114b3be9..846be236ee453846ccd87f422c3e80bf6b4bcdb1 100644 --- a/lib_enc/ivas_init_enc.c +++ b/lib_enc/ivas_init_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -123,7 +123,7 @@ void ivas_write_format_sid( } else { - assert( !"Wrong stereo mode for SID format signalling" ); + assert( !"Wrong stereo mode for SID format signaling" ); } break; case ISM_FORMAT: @@ -184,12 +184,16 @@ int16_t getNumChanAnalysis( n = st_ivas->nSCE + CPE_CHANNELS * st_ivas->nCPE; if ( st_ivas->hEncoderConfig->ivas_format == SBA_FORMAT ) { - n = DIRAC_MAX_ANA_CHANS; + n = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order ); } else if ( st_ivas->hEncoderConfig->ivas_format == MC_FORMAT && ( st_ivas->mc_mode == MC_MODE_PARAMMC || st_ivas->mc_mode == MC_MODE_MCMASA ) ) { n = st_ivas->hEncoderConfig->nchan_inp; } + else if ( st_ivas->hEncoderConfig->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) + { + n = st_ivas->hEncoderConfig->nchan_inp; + } return n; } @@ -233,53 +237,22 @@ void copy_encoder_config( st->force = st_ivas->hEncoderConfig->force; #endif st->element_mode = st_ivas->hEncoderConfig->element_mode_init; + return; } -/*-------------------------------------------------------------------* - * ivas_init_encoder() +/*------------------------------------------------------------------------- + * ivas_initialize_handles_enc() * - * Initialize IVAS encoder state structure - *-------------------------------------------------------------------*/ + * NULL initialization of handles + *-------------------------------------------------------------------------*/ -ivas_error ivas_init_encoder( - Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ - Indice ind_list[][MAX_NUM_INDICES], /* o : bitstream indices */ - Indice ind_list_metadata[][MAX_BITS_METADATA] /* o : bitstream indices metadata */ +void ivas_initialize_handles_enc( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ) { - int16_t i, n; - int16_t sce_id, cpe_id; - IVAS_FORMAT ivas_format; - int32_t input_Fs, ivas_total_brate; - ENCODER_CONFIG_HANDLE hEncoderConfig; - ivas_error error; - - error = IVAS_ERR_OK; - - hEncoderConfig = st_ivas->hEncoderConfig; - ivas_format = hEncoderConfig->ivas_format; - input_Fs = hEncoderConfig->input_Fs; - ivas_total_brate = hEncoderConfig->ivas_total_brate; - - hEncoderConfig->last_ivas_total_brate = ivas_total_brate; - - if ( ivas_format != MONO_FORMAT ) - { - /* In IVAS, ensure that minimum coded bandwidth is WB */ - hEncoderConfig->max_bwidth = max( hEncoderConfig->max_bwidth, WB ); - } - - st_ivas->ism_mode = ISM_MODE_NONE; - st_ivas->mc_mode = MC_MODE_NONE; - st_ivas->sba_mode = SBA_MODE_NONE; - - /*-----------------------------------------------------------------* - * Dummy pointers to max. number of SCEs and CPEs - *-----------------------------------------------------------------*/ - - st_ivas->nchan_transport = -1; + int16_t i; for ( i = 0; i < MAX_SCE; i++ ) { @@ -291,12 +264,17 @@ ivas_error ivas_init_encoder( st_ivas->hCPE[i] = NULL; } - /* ISm metadata handles */ - for ( n = 0; n < MAX_NUM_OBJECTS; n++ ) + st_ivas->mem_hp20_in = NULL; + + /* ISM metadata handles */ + for ( i = 0; i < MAX_NUM_OBJECTS; i++ ) { - st_ivas->hIsmMetaData[n] = NULL; + st_ivas->hIsmMetaData[i] = NULL; } + /* ISM DTX handle */ + st_ivas->hISMDTX = NULL; + /* Q Metadata handle */ st_ivas->hQMetaData = NULL; @@ -324,6 +302,49 @@ ivas_error ivas_init_encoder( /* LFE handle */ st_ivas->hLFE = NULL; + return; +} + + +/*-------------------------------------------------------------------* + * ivas_init_encoder() + * + * Initialize IVAS encoder state structure + *-------------------------------------------------------------------*/ + +ivas_error ivas_init_encoder( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + Indice ind_list[][MAX_NUM_INDICES], /* o : bitstream indices */ + Indice ind_list_metadata[][MAX_BITS_METADATA] /* o : bitstream indices metadata */ +) +{ + int16_t i, n; + int16_t sce_id, cpe_id; + IVAS_FORMAT ivas_format; + int32_t input_Fs, ivas_total_brate; + ENCODER_CONFIG_HANDLE hEncoderConfig; + ivas_error error; + + error = IVAS_ERR_OK; + + hEncoderConfig = st_ivas->hEncoderConfig; + ivas_format = hEncoderConfig->ivas_format; + input_Fs = hEncoderConfig->input_Fs; + ivas_total_brate = hEncoderConfig->ivas_total_brate; + + hEncoderConfig->last_ivas_total_brate = ivas_total_brate; + + if ( ivas_format != MONO_FORMAT ) + { + /* In IVAS, ensure that minimum coded bandwidth is WB */ + hEncoderConfig->max_bwidth = max( hEncoderConfig->max_bwidth, WB ); + } + + st_ivas->ism_mode = ISM_MODE_NONE; + st_ivas->mc_mode = MC_MODE_NONE; + st_ivas->sba_mode = SBA_MODE_NONE; + + st_ivas->nchan_transport = -1; /*-----------------------------------------------------------------* * Allocate and initialize SCE/CPE and other handles *-----------------------------------------------------------------*/ @@ -382,7 +403,7 @@ ivas_error ivas_init_encoder( st_ivas->ism_mode = ivas_ism_mode_select( hEncoderConfig->nchan_inp, ivas_total_brate ); - if ( ( error = create_ism_metadata_enc( st_ivas, hEncoderConfig->nchan_inp, element_brate_tmp ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_ism_metadata_enc_create( st_ivas, hEncoderConfig->nchan_inp, element_brate_tmp ) ) != IVAS_ERR_OK ) { return error; } @@ -409,32 +430,46 @@ ivas_error ivas_init_encoder( return error; } } - } - else if ( ivas_format == SBA_FORMAT || ivas_format == MASA_FORMAT ) - { + +#ifdef DISCRETE_ISM_DTX_CNG + if ( st_ivas->hEncoderConfig->Opt_DTX_ON ) +#else + if ( st_ivas->hEncoderConfig->Opt_DTX_ON && st_ivas->ism_mode == ISM_MODE_PARAM ) +#endif { - if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_ism_dtx_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } } + } + else if ( ivas_format == SBA_FORMAT || ivas_format == MASA_FORMAT ) + { + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) + { + return error; + } if ( ivas_format == SBA_FORMAT ) { +#ifndef LBR_SBA st_ivas->sba_mode = ivas_sba_mode_select( ivas_total_brate ); +#else + st_ivas->sba_mode = ivas_sba_mode_select( ); +#endif + st_ivas->sba_analysis_order = ivas_sba_get_analysis_order( ivas_total_brate, st_ivas->hEncoderConfig->sba_order ); if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - if ( ( error = ivas_spar_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_spar_enc_open( st_ivas, 0 ) ) != IVAS_ERR_OK ) { return error; } } + + if ( ( error = ivas_dirac_enc_open( st_ivas ) ) != IVAS_ERR_OK ) { - if ( ( error = ivas_dirac_enc_open( st_ivas ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } } else @@ -459,6 +494,11 @@ ivas_error ivas_init_encoder( st_ivas->hSCE[sce_id]->hMetaData->ind_list = ind_list_metadata[sce_id]; reset_indices_enc( st_ivas->hSCE[sce_id]->hMetaData, MAX_BITS_METADATA ); + + if ( st_ivas->sba_mode == SBA_MODE_SPAR && st_ivas->hEncoderConfig->Opt_DTX_ON ) + { + st_ivas->hSCE[sce_id]->hCoreCoder[0]->dtx_sce_sba = 1; + } } for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) @@ -473,21 +513,14 @@ ivas_error ivas_init_encoder( { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->ind_list = ind_list[cpe_id * CPE_CHANNELS + n]; reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES ); + if ( hEncoderConfig->Opt_DTX_ON ) { - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_spar_flag = 1; - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_dirac_flag = 1; - } - else - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_dirac_flag = 1; - } + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_sba_flag = 1; } } - /* Metadata only initialized for the last cpe index */ + /* Metadata only initialized for the last CPE index */ if ( cpe_id == st_ivas->nCPE - 1 ) { st_ivas->hCPE[cpe_id]->hMetaData->ind_list = ind_list_metadata[st_ivas->nSCE]; @@ -506,12 +539,8 @@ ivas_error ivas_init_encoder( else if ( ivas_format == MC_FORMAT ) { st_ivas->mc_mode = ivas_mc_mode_select( hEncoderConfig->mc_input_setup, ivas_total_brate ); - hEncoderConfig->nchan_inp = ivas_mc_ls_setup_get_num_channels( hEncoderConfig->mc_input_setup ); - if ( ( error = ivas_create_lfe_enc( &st_ivas->hLFE, input_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } + hEncoderConfig->nchan_inp = ivas_mc_ls_setup_get_num_channels( hEncoderConfig->mc_input_setup ); if ( st_ivas->mc_mode == MC_MODE_MCT ) { @@ -527,14 +556,18 @@ ivas_error ivas_init_encoder( for ( n = 0; n < CPE_CHANNELS; n++ ) { - if ( cpe_id * CPE_CHANNELS + n == LFE_CHANNEL ) - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->nb_bits_tot = 0; - continue; - } + /* we need the correct bitstream also for the LFE channel since it might become a proper coded channel when + switching to ParamMC and ind_list is only visible here, can't be done later */ st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->ind_list = ind_list[cpe_id * CPE_CHANNELS + n]; reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES ); } + + /* Metadata only initialized for the last CPE index*/ + if ( cpe_id == st_ivas->nCPE - 1 ) + { + st_ivas->hCPE[cpe_id]->hMetaData->ind_list = ind_list_metadata[st_ivas->nSCE]; + reset_indices_enc( st_ivas->hCPE[cpe_id]->hMetaData, MAX_BITS_METADATA ); + } } if ( ( error = create_mct_enc( st_ivas ) ) != IVAS_ERR_OK ) @@ -542,6 +575,11 @@ ivas_error ivas_init_encoder( return error; } + if ( ( error = ivas_create_lfe_enc( &st_ivas->hLFE, input_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + st_ivas->nchan_transport = ivas_mc_ls_setup_get_num_channels( st_ivas->hEncoderConfig->mc_input_setup ); } else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) @@ -565,7 +603,7 @@ ivas_error ivas_init_encoder( reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES ); } - /* Metadata only initialized for the last cpe index*/ + /* Metadata only initialized for the last CPE index*/ if ( cpe_id == st_ivas->nCPE - 1 ) { st_ivas->hCPE[cpe_id]->hMetaData->ind_list = ind_list_metadata[st_ivas->nSCE]; @@ -583,7 +621,10 @@ ivas_error ivas_init_encoder( } else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { + int32_t brate_sce, brate_cpe; + ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( hEncoderConfig->element_mode_init ), ivas_total_brate ); + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) { return error; @@ -599,21 +640,13 @@ ivas_error ivas_init_encoder( return error; } + ivas_mcmasa_split_brate( st_ivas->hMcMasa->separateChannelEnabled, ivas_total_brate, st_ivas->nSCE, st_ivas->nCPE, &brate_sce, &brate_cpe ); + for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) { - if ( st_ivas->hMcMasa->separateChannelEnabled ) + if ( ( error = create_sce_enc( st_ivas, sce_id, brate_sce ) ) != IVAS_ERR_OK ) { - if ( ( error = create_sce_enc( st_ivas, sce_id, ivas_mcmasa_mono_brate( ivas_total_brate ) ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - if ( ( error = create_sce_enc( st_ivas, sce_id, ivas_total_brate / ( st_ivas->nCPE + st_ivas->nSCE ) ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } /* prepare bitstream buffers */ @@ -626,21 +659,11 @@ ivas_error ivas_init_encoder( for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { - if ( st_ivas->hMcMasa->separateChannelEnabled ) - { - hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; - if ( ( error = create_cpe_enc( st_ivas, cpe_id, ivas_total_brate - st_ivas->hSCE[0]->element_brate ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else + if ( ( error = create_cpe_enc( st_ivas, cpe_id, brate_cpe ) ) != IVAS_ERR_OK ) { - if ( ( error = create_cpe_enc( st_ivas, cpe_id, ivas_total_brate / ( st_ivas->nCPE + st_ivas->nSCE ) ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } /* prepare bitstream buffers */ @@ -650,7 +673,7 @@ ivas_error ivas_init_encoder( reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES ); } - /* Metadata only initialized for the last cpe index*/ + /* Metadata only initialized for the last CPE index*/ if ( cpe_id == st_ivas->nCPE - 1 ) { st_ivas->hCPE[cpe_id]->hMetaData->ind_list = ind_list_metadata[st_ivas->nSCE]; @@ -675,7 +698,7 @@ ivas_error ivas_init_encoder( if ( n > 0 ) { - if ( ( st_ivas->mem_hp20_in = (float **) count_malloc( n * sizeof( float * ) ) ) == NULL ) + if ( ( st_ivas->mem_hp20_in = (float **) malloc( n * sizeof( float * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); } @@ -687,7 +710,7 @@ ivas_error ivas_init_encoder( for ( i = 0; i < n; i++ ) { - if ( ( st_ivas->mem_hp20_in[i] = (float *) count_malloc( L_HP20_MEM * sizeof( float ) ) ) == NULL ) + if ( ( st_ivas->mem_hp20_in[i] = (float *) malloc( L_HP20_MEM * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); } @@ -709,141 +732,141 @@ void destroy_core_enc( ENC_CORE_HANDLE hCoreCoder /* i/o: core encoder structure */ ) { - destroy_encoder( hCoreCoder ); + destroy_cldfb_encoder( hCoreCoder ); if ( hCoreCoder->hSignalBuf != NULL ) { - count_free( hCoreCoder->hSignalBuf ); + free( hCoreCoder->hSignalBuf ); hCoreCoder->hSignalBuf = NULL; } if ( hCoreCoder->hBstr != NULL ) { - count_free( hCoreCoder->hBstr ); + free( hCoreCoder->hBstr ); hCoreCoder->hBstr = NULL; } if ( hCoreCoder->hLPDmem != NULL ) { - count_free( hCoreCoder->hLPDmem ); + free( hCoreCoder->hLPDmem ); hCoreCoder->hLPDmem = NULL; } if ( hCoreCoder->hTranDet != NULL ) { - count_free( hCoreCoder->hTranDet ); + free( hCoreCoder->hTranDet ); hCoreCoder->hTranDet = NULL; } if ( hCoreCoder->hNoiseEst != NULL ) { - count_free( hCoreCoder->hNoiseEst ); + free( hCoreCoder->hNoiseEst ); hCoreCoder->hNoiseEst = NULL; } if ( hCoreCoder->hVAD != NULL ) { - count_free( hCoreCoder->hVAD ); + free( hCoreCoder->hVAD ); hCoreCoder->hVAD = NULL; } if ( hCoreCoder->hVAD_CLDFB != NULL ) { - count_free( hCoreCoder->hVAD_CLDFB ); + free( hCoreCoder->hVAD_CLDFB ); hCoreCoder->hVAD_CLDFB = NULL; } if ( hCoreCoder->hTdCngEnc != NULL ) { - count_free( hCoreCoder->hTdCngEnc ); + free( hCoreCoder->hTdCngEnc ); hCoreCoder->hTdCngEnc = NULL; } if ( hCoreCoder->hDtxEnc != NULL ) { - count_free( hCoreCoder->hDtxEnc ); + free( hCoreCoder->hDtxEnc ); hCoreCoder->hDtxEnc = NULL; } if ( hCoreCoder->hSpMusClas != NULL ) { - count_free( hCoreCoder->hSpMusClas ); + free( hCoreCoder->hSpMusClas ); hCoreCoder->hSpMusClas = NULL; } if ( hCoreCoder->hGSCEnc != NULL ) { - count_free( hCoreCoder->hGSCEnc ); + free( hCoreCoder->hGSCEnc ); hCoreCoder->hGSCEnc = NULL; } if ( hCoreCoder->hSC_VBR != NULL ) { - count_free( hCoreCoder->hSC_VBR ); + free( hCoreCoder->hSC_VBR ); hCoreCoder->hSC_VBR = NULL; } if ( hCoreCoder->hAmrwb_IO != NULL ) { - count_free( hCoreCoder->hAmrwb_IO ); + free( hCoreCoder->hAmrwb_IO ); hCoreCoder->hAmrwb_IO = NULL; } if ( hCoreCoder->hBWE_TD != NULL ) { - count_free( hCoreCoder->hBWE_TD ); + free( hCoreCoder->hBWE_TD ); hCoreCoder->hBWE_TD = NULL; } if ( hCoreCoder->hBWE_FD != NULL ) { - count_free( hCoreCoder->hBWE_FD ); + free( hCoreCoder->hBWE_FD ); hCoreCoder->hBWE_FD = NULL; } if ( hCoreCoder->hRF != NULL ) { - count_free( hCoreCoder->hRF ); + free( hCoreCoder->hRF ); hCoreCoder->hRF = NULL; } if ( hCoreCoder->hTECEnc != NULL ) { - count_free( hCoreCoder->hTECEnc ); + free( hCoreCoder->hTECEnc ); hCoreCoder->hTECEnc = NULL; } if ( hCoreCoder->hTcxEnc != NULL ) { - count_free( hCoreCoder->hTcxEnc ); + free( hCoreCoder->hTcxEnc ); hCoreCoder->hTcxEnc = NULL; } if ( hCoreCoder->hTcxCfg != NULL ) { - count_free( hCoreCoder->hTcxCfg ); + free( hCoreCoder->hTcxCfg ); hCoreCoder->hTcxCfg = NULL; } if ( hCoreCoder->hIGFEnc != NULL ) { - count_free( hCoreCoder->hIGFEnc ); + free( hCoreCoder->hIGFEnc ); hCoreCoder->hIGFEnc = NULL; } if ( hCoreCoder->hPlcExt != NULL ) { - count_free( hCoreCoder->hPlcExt ); + free( hCoreCoder->hPlcExt ); hCoreCoder->hPlcExt = NULL; } if ( hCoreCoder->hHQ_core != NULL ) { - count_free( hCoreCoder->hHQ_core ); + free( hCoreCoder->hHQ_core ); hCoreCoder->hHQ_core = NULL; } - count_free( hCoreCoder ); + free( hCoreCoder ); return; } @@ -871,7 +894,7 @@ void ivas_destroy_enc( if ( st_ivas->hSCE[i] != NULL ) { destroy_sce_enc( st_ivas->hSCE[i] ); - st_ivas->hSCE[0] = NULL; + st_ivas->hSCE[i] = NULL; } } @@ -892,98 +915,70 @@ void ivas_destroy_enc( for ( i = 0; i < n; i++ ) { - count_free( st_ivas->mem_hp20_in[i] ); + free( st_ivas->mem_hp20_in[i] ); st_ivas->mem_hp20_in[i] = NULL; } - count_free( st_ivas->mem_hp20_in ); + free( st_ivas->mem_hp20_in ); st_ivas->mem_hp20_in = NULL; } /* ISM metadata handles */ - for ( n = 0; n < MAX_NUM_OBJECTS; n++ ) + ivas_ism_metadata_close( st_ivas->hIsmMetaData ); + + /* ISM DTX Handle */ + if ( st_ivas->hISMDTX != NULL ) { - if ( st_ivas->hIsmMetaData[n] != NULL ) - { - count_free( st_ivas->hIsmMetaData[n] ); - st_ivas->hIsmMetaData[n] = NULL; - } + free( st_ivas->hISMDTX ); + st_ivas->hISMDTX = NULL; } /* Q Metadata handle */ ivas_qmetadata_close( &( st_ivas->hQMetaData ) ); /* DirAC handle */ - if ( st_ivas->hDirAC != NULL ) + if ( ivas_format == ISM_FORMAT ) { - if ( ivas_format == ISM_FORMAT ) - { - ivas_param_ism_enc_close( st_ivas->hDirAC, st_ivas->hEncoderConfig->input_Fs ); - } - else - { - ivas_dirac_enc_close( st_ivas->hDirAC, st_ivas->hEncoderConfig->input_Fs ); - } - st_ivas->hDirAC = NULL; + ivas_param_ism_enc_close( &( st_ivas->hDirAC ), st_ivas->hEncoderConfig->input_Fs ); } - - /* SPAR handle */ - if ( st_ivas->hSpar != NULL ) + else { - ivas_spar_enc_close( st_ivas->hSpar, st_ivas->hEncoderConfig->input_Fs, nchan_inp ); - st_ivas->hSpar = NULL; + ivas_dirac_enc_close( &( st_ivas->hDirAC ), st_ivas->hEncoderConfig->input_Fs ); } + /* SPAR handle */ + ivas_spar_enc_close( &( st_ivas->hSpar ), st_ivas->hEncoderConfig->input_Fs, nchan_inp, 0 ); + /* MASA handle */ - if ( st_ivas->hMasa != NULL ) - { - ivas_masa_enc_close( st_ivas->hMasa, st_ivas->nchan_transport, ivas_format ); - st_ivas->hMasa = NULL; - } +#ifdef FIX_350_MASA_DELAY_COMP + ivas_masa_enc_close( &( st_ivas->hMasa ) ); +#else + ivas_masa_enc_close( &( st_ivas->hMasa ), st_ivas->nchan_transport, ivas_format ); +#endif /* MCT handle */ - if ( st_ivas->hMCT != NULL ) - { - ivas_mct_enc_close( st_ivas->hMCT ); - st_ivas->hMCT = NULL; - } + ivas_mct_enc_close( &( st_ivas->hMCT ) ); + + /* LFE handle */ + ivas_lfe_enc_close( &( st_ivas->hLFE ) ); /* Parametric MC handle */ - if ( st_ivas->hParamMC != NULL ) - { - ivas_param_mc_enc_close( st_ivas->hParamMC, st_ivas->hEncoderConfig->input_Fs ); - st_ivas->hParamMC = NULL; - } + ivas_param_mc_enc_close( &( st_ivas->hParamMC ), st_ivas->hEncoderConfig->input_Fs ); /* Multi-channel MASA handle */ - if ( st_ivas->hMcMasa != NULL ) - { - ivas_mcmasa_enc_close( st_ivas->hMcMasa, st_ivas->hEncoderConfig->input_Fs ); - st_ivas->hMcMasa = NULL; - } + ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); /* Stereo downmix for EVS encoder handle */ - if ( st_ivas->hStereoDmxEVS != NULL ) - { - stereo_dmx_evs_close_encoder( st_ivas->hStereoDmxEVS ); - st_ivas->hStereoDmxEVS = NULL; - } - - /* LFE handle */ - if ( st_ivas->hLFE != NULL ) - { - ivas_lfe_enc_close( st_ivas->hLFE ); - st_ivas->hLFE = NULL; - } + stereo_dmx_evs_close_encoder( &( st_ivas->hStereoDmxEVS ) ); /* Encoder configuration handle */ if ( st_ivas->hEncoderConfig != NULL ) { - count_free( st_ivas->hEncoderConfig ); + free( st_ivas->hEncoderConfig ); st_ivas->hEncoderConfig = NULL; } /* main IVAS handle */ - count_free( st_ivas ); + free( st_ivas ); return; } diff --git a/lib_enc/ivas_ism_dtx_enc.c b/lib_enc/ivas_ism_dtx_enc.c new file mode 100644 index 0000000000000000000000000000000000000000..3839a42a9df8518f01561990ac87dadefe70696f --- /dev/null +++ b/lib_enc/ivas_ism_dtx_enc.c @@ -0,0 +1,554 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include "options.h" +#include "ivas_cnst.h" +#include "prot.h" +#include "ivas_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +#ifdef DISCRETE_ISM_DTX_CNG +/*-----------------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------------*/ + +#define MD_MAX_DIFF_AZIMUTH 10 +#define MD_MAX_DIFF_ELEVATION 10 +#endif + + +/*-------------------------------------------------------------------* + * ivas_ism_dtx_open() + * + * Open ISM DTX handle + *-------------------------------------------------------------------*/ + +ivas_error ivas_ism_dtx_open( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + ivas_error error; + ISM_DTX_HANDLE hISMDTX; + int16_t i; + + error = IVAS_ERR_OK; + + /* Assign memory to DirAC handle */ + if ( ( hISMDTX = (ISM_DTX_HANDLE) malloc( sizeof( ISM_DTX_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM DTX Handle \n" ) ); + } + + hISMDTX->dtx_flag = 0; + hISMDTX->sce_id_dtx = 0; +#ifdef DISCRETE_ISM_DTX_CNG + hISMDTX->cnt_SID_ISM = -1; +#else + set_s( hISMDTX->dtx_speech_buffer_enc, 0, PARAM_ISM_HYS_BUF_SIZE ); +#endif + + for ( i = 0; i < MAX_NUM_OBJECTS; i++ ) + { + set_f( hISMDTX->long_term_energy_stereo_dmx_enc[i], 0.0f, PARAM_ISM_HYS_BUF_SIZE ); + } + + set_f( hISMDTX->coh, 0.0f, MAX_NUM_OBJECTS ); + + st_ivas->hISMDTX = hISMDTX; + + return error; +} + + +#ifdef DISCRETE_ISM_DTX_CNG +/*-------------------------------------------------------------------* + * ivas_ism_get_dtx_enc() + * + * Analysis and decision about DTX in ISM format + *-------------------------------------------------------------------*/ + +/*! r: indication of DTX frame */ +int16_t ivas_ism_dtx_enc( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + SCE_ENC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t nchan_transport, /* i : number of transport channels */ + int16_t vad_flag[MAX_NUM_OBJECTS], /* i : VAD flag */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + int16_t md_diff_flag[], /* o : metadata differential flag */ + int16_t *sid_flag /* o : indication of SID frame */ +) +{ + int16_t ch, dtx_flag; + int16_t nBits, nBits_MD_max; + int16_t nBits_azimuth, nBits_elevation, nBits_coh, nBits_sce_id; + float lp_noise[MAX_NUM_OBJECTS], lp_noise_variation, lp_noise_mean; + float lp_noise_max; + float tmp1, tmp2; + + /* initialization */ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + hSCE[ch]->hCoreCoder[0]->low_rate_mode = 0; + } + + /*------------------------------------------------------------------* + * compute global ISM DTX flag + *-----------------------------------------------------------------*/ + + /* compute global ISM based on localVAD */ + dtx_flag = 1; + for ( ch = 0; ch < nchan_transport; ch++ ) + { + dtx_flag &= !vad_flag[ch]; + } + + /* compute global ISM based on long-term background noise */ + /* one of the channels is active -> no DTX */ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + lp_noise[ch] = hSCE[ch]->hCoreCoder[0]->lp_noise; + } + + lp_noise_variation = var( lp_noise, nchan_transport ); + lp_noise_mean = mean( lp_noise, nchan_transport ); + + if ( lp_noise_mean > 50 || ( lp_noise_mean > 25 && lp_noise_variation > 32 ) ) + { + dtx_flag = 0; + } + + + /* default DTX is applied at lower bitrates; otherwise DTX is applied only in silence */ + maximum( lp_noise, nchan_transport, &lp_noise_max ); + + if ( !( ( nchan_ism == 1 && ivas_total_brate <= IVAS_24k4 ) || + ( nchan_ism == 2 && ivas_total_brate <= IVAS_48k ) || + ( nchan_ism == 3 && ivas_total_brate <= IVAS_80k ) || + ( nchan_ism == 4 && ivas_total_brate <= IVAS_96k ) || + lp_noise_max < 15 ) ) + { + dtx_flag = 0; + } + + /*------------------------------------------------------------------* + * Reset the bitstream + *-----------------------------------------------------------------*/ + + if ( dtx_flag ) + { + /* reset the bitstream (IVAS format signaling was already written) */ + reset_indices_enc( hSCE[0]->hCoreCoder[0]->hBstr, MAX_NUM_INDICES ); + } + + /*------------------------------------------------------------------* + * decide about SID metadata to be sent or not (per object) + * estimate the MD bit-budget consumption + *-----------------------------------------------------------------*/ + + if ( dtx_flag ) + { + ivas_get_ism_sid_quan_bitbudget( nchan_ism, &nBits_azimuth, &nBits_elevation, &tmp1, &tmp2, &nBits_coh, &nBits_sce_id ); + + nBits = 0; + for ( ch = 0; ch < nchan_ism; ch++ ) + { + /* check difference between current and last metadata */ + md_diff_flag[ch] = 0; + if ( fabsf( hIsmMeta[ch]->azimuth - hIsmMeta[ch]->last_azimuth ) > MD_MAX_DIFF_AZIMUTH ) + { + md_diff_flag[ch] = 1; + } + + if ( fabsf( hIsmMeta[ch]->elevation - hIsmMeta[ch]->last_elevation ) > MD_MAX_DIFF_ELEVATION ) + { + md_diff_flag[ch] = 1; + } + + /* estimate SID metadata bit-budget */ + nBits++; /* number of objects */ + nBits++; /* SID metadata flag */ + if ( md_diff_flag[ch] == 1 ) + { + nBits += nBits_azimuth; + nBits += nBits_elevation; + } + } + + /* calculate maximum available MD bit-budget */ + nBits_MD_max = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; + nBits_MD_max -= SID_FORMAT_NBITS; + if ( nchan_transport > 1 ) + { + nBits_MD_max -= nBits_sce_id; + } + + for ( ch = 0; ch < nchan_transport - 1; ch++ ) + { + nBits_MD_max -= nBits_coh; /* coherence */ + } + + if ( nchan_ism > 3 ) + { + nBits_MD_max--; /* ism_mode flag */ + } + + /* too many metadata bits -> switch to active coding */ + if ( nBits > nBits_MD_max ) + { + dtx_flag = 0; + } + } + + /*------------------------------------------------------------------* + * set core_brate for all channels + * get 'sid_flag' value + *-----------------------------------------------------------------*/ + + *sid_flag = 0; + + if ( !dtx_flag ) + { + /* at least one of the channels is active -> no DTX */ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + hSCE[ch]->hCoreCoder[0]->core_brate = -1; + set_bw( IVAS_SCE, hSCE[ch]->element_brate, hSCE[ch]->hCoreCoder[0], MODE1 ); + } + + hISMDTX->cnt_SID_ISM = -1; + + /* IVAS format signaling was erased in dtx() */ + if ( hSCE[0]->hCoreCoder[0]->hBstr->nb_bits_tot == 0 ) + { + /* replicate ivas_write_format() */ + push_indice( hSCE[0]->hCoreCoder[0]->hBstr, IND_IVAS_FORMAT, 2 /* == ISM format */, IVAS_FORMAT_SIGNALING_NBITS ); + } + } + else /* ism_dtx_flag == 1 */ + { + for ( ch = 0; ch < nchan_transport; ch++ ) + { + hSCE[ch]->hCoreCoder[0]->cng_type = FD_CNG; + } + + /* * update the global SID counter */ + hISMDTX->cnt_SID_ISM++; + if ( hISMDTX->cnt_SID_ISM >= hSCE[0]->hCoreCoder[0]->hDtxEnc->max_SID ) + { + /* adaptive SID update interval */ + hSCE[0]->hCoreCoder[0]->hDtxEnc->max_SID = hSCE[0]->hCoreCoder[0]->hDtxEnc->interval_SID; + hISMDTX->cnt_SID_ISM = 0; + } + + /* encode SID in one channel only */ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + hSCE[ch]->hCoreCoder[0]->core_brate = FRAME_NO_DATA; + } + + if ( hISMDTX->cnt_SID_ISM == 0 ) + { + hSCE[hISMDTX->sce_id_dtx]->hCoreCoder[0]->core_brate = SID_2k40; + *sid_flag = 1; + } + } + + if ( dtx_flag == 1 && *sid_flag == 0 ) + { + set_s( md_diff_flag, 0, nchan_transport ); + } + + return dtx_flag; +} +#else +/*-------------------------------------------------------------------* + * ivas_ism_dtx_enc() + * + * Analysis and decision about DTX in ISM format + *-------------------------------------------------------------------*/ + +/*! r: indication of DTX frame */ +int16_t ivas_ism_dtx_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + int16_t *sid_flag /* o : indication of SID frame */ +) +{ + int16_t i, val, dtx_flag; + + dtx_flag = 0; + *sid_flag = 0; + + /* Move the DTX/CNG speech buffer */ + for ( i = 0; i < ( PARAM_ISM_HYS_BUF_SIZE - 1 ); i++ ) + { + st_ivas->hISMDTX->dtx_speech_buffer_enc[i] = st_ivas->hISMDTX->dtx_speech_buffer_enc[i + 1]; + } + + /* If both TCs are active frame, do not do any post processing */ + if ( !( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == -1 && st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == -1 ) ) + { + /* covers 3 cases + * case 1: ch0 -> Inactive Frame, ch 1 -> Inactive Frame -> do not do any post-processing (Activate DTX) + * case 2: ch0 -> Inactive Frame, ch 1 -> Active Frame + * case 3: ch0 -> Active Frame, ch 1 -> Inactive Frame + */ + + /* case 2 -> ch 0 is inactive, set it to active */ + if ( st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == -1 && ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) ) + { + st_ivas->hISMDTX->dtx_speech_buffer_enc[i] = 0; + } + + /* case 3 -> ch 1 is inactive, set it to active */ + if ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == -1 && ( st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) ) + { + st_ivas->hISMDTX->dtx_speech_buffer_enc[i] = 0; + } + + /* case 1: both TCs are inactive */ + if ( ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) && ( st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) ) + { + st_ivas->hISMDTX->dtx_speech_buffer_enc[i] = 1; + } + } + else + { + st_ivas->hISMDTX->dtx_speech_buffer_enc[i] = 0; + } + + /* Do a decision based on hysteresis */ + st_ivas->hISMDTX->dtx_flag = 1; + + for ( i = 1; i < ( PARAM_ISM_HYS_BUF_SIZE - 1 ); i++ ) + { + if ( ( st_ivas->hISMDTX->dtx_speech_buffer_enc[i + 1] == 1 ) && ( st_ivas->hISMDTX->dtx_speech_buffer_enc[i - 1] == 1 ) && ( st_ivas->hISMDTX->dtx_speech_buffer_enc[i] == 0 ) ) + { + st_ivas->hISMDTX->dtx_speech_buffer_enc[i] = 1; + } + } + + val = sum_s( st_ivas->hISMDTX->dtx_speech_buffer_enc, PARAM_ISM_HYS_BUF_SIZE ); + + if ( val < 7 ) + { + for ( i = 0; i < PARAM_ISM_HYS_BUF_SIZE; i++ ) + { + st_ivas->hISMDTX->dtx_flag = st_ivas->hISMDTX->dtx_flag && st_ivas->hISMDTX->dtx_speech_buffer_enc[i]; + } + } + + if ( st_ivas->hISMDTX->dtx_flag ) + { + /* case 1 */ + /* force FD-CNG */ + st_ivas->hSCE[0]->hCoreCoder[0]->cng_type = FD_CNG; + st_ivas->hSCE[1]->hCoreCoder[0]->cng_type = FD_CNG; + + /* synchronize the core bitrate */ + if ( ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == -1 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->last_core_brate == SID_2k40 || st_ivas->hSCE[0]->hCoreCoder[0]->last_core_brate == FRAME_NO_DATA ) ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->core_brate = st_ivas->hSCE[0]->hCoreCoder[0]->last_core_brate; + reset_indices_enc( st_ivas->hSCE[0]->hCoreCoder[0]->hBstr, MAX_NUM_INDICES ); + } + + st_ivas->hSCE[1]->hCoreCoder[0]->core_brate = st_ivas->hSCE[0]->hCoreCoder[0]->core_brate; + } + else + { + if ( ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) && ( st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->core_brate = -1; + st_ivas->hSCE[1]->hCoreCoder[0]->core_brate = -1; + + /* since ch0 is detected as inactive frame and we are setting it as active frame, + we need to reset bitstream pointer and write the ivas_format once more */ + ivas_write_format( st_ivas ); + } + + /* case 3 -> ch 1 is inactive, set it to active */ + if ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == -1 && ( st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) ) + { + st_ivas->hSCE[1]->hCoreCoder[0]->core_brate = -1; + } + + /* case 2 -> ch 0 is inactive, set it to active */ + if ( st_ivas->hSCE[1]->hCoreCoder[0]->core_brate == -1 && ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->core_brate = -1; + + /* since ch0 is detected as inactive frame and we are setting it as active frame, + we need to reset bitstream pointer and write the ivas_format once more */ + ivas_write_format( st_ivas ); + } + } + + if ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) + { + *sid_flag = 1; + dtx_flag = 1; + } + + if ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) + { + dtx_flag = 1; + } + + return dtx_flag; +} +#endif + +/*-------------------------------------------------------------------* + * ivas_ism_get_sce_id_dtx() + * + * + *-------------------------------------------------------------------*/ + +void ivas_ism_get_sce_id_dtx( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + SCE_ENC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t input_frame /* i : input frame length per channel */ + +) +{ + float tmp_energy[MAX_NUM_OBJECTS]; + int16_t i, j; + + if ( nchan_transport == 1 ) + { + hISMDTX->sce_id_dtx = 0; + + return; + } + + /* Initialize*/ + set_f( tmp_energy, 0.0f, MAX_NUM_OBJECTS ); + + /* compute long term energy parameter */ + for ( j = 0; j < nchan_transport; j++ ) + { + for ( i = 0; i < ( PARAM_ISM_HYS_BUF_SIZE - 1 ); i++ ) + { + hISMDTX->long_term_energy_stereo_dmx_enc[j][i] = hISMDTX->long_term_energy_stereo_dmx_enc[j][i + 1]; + } + + hISMDTX->long_term_energy_stereo_dmx_enc[j][PARAM_ISM_HYS_BUF_SIZE - 1] = sum2_f( hSCE[j]->hCoreCoder[0]->input, input_frame ); + + tmp_energy[j] = sum_f( hISMDTX->long_term_energy_stereo_dmx_enc[j], PARAM_ISM_HYS_BUF_SIZE ); + } + + /* determine the sce_id */ + hISMDTX->sce_id_dtx = 0; + for ( j = 1; j < nchan_transport; j++ ) + { + if ( tmp_energy[j] > tmp_energy[hISMDTX->sce_id_dtx] ) + { + hISMDTX->sce_id_dtx = j; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_ism_coh_estim_dtx_enc() + * + * + *-------------------------------------------------------------------*/ + +void ivas_ism_coh_estim_dtx_enc( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + SCE_ENC_HANDLE hSCE[MAX_SCE], /* i/o: SCE encoder structure */ + const int16_t nchan_transport, /* i : number of transport channels */ + const int16_t input_frame /* i : input frame length */ + +) +{ + Encoder_State *st, *st_id0; + int16_t sce_id, i; +#ifdef DISCRETE_ISM_DTX_CNG + float acorr_ene[MAX_NUM_OBJECTS], xcorr_ene; +#else + float acorr_ene[PARAM_ISM_MAX_DMX], xcorr_ene; +#endif + + if ( nchan_transport == 1 ) + { + hISMDTX->coh[0] = 0.f; + return; + } + + /* Compute Coherence */ + acorr_ene[hISMDTX->sce_id_dtx] = 0.0f; + st_id0 = hSCE[hISMDTX->sce_id_dtx]->hCoreCoder[0]; + + for ( i = 0; i < input_frame; i++ ) + { + acorr_ene[hISMDTX->sce_id_dtx] += st_id0->input[i] * st_id0->input[i]; + } + + for ( sce_id = 0; sce_id < nchan_transport; sce_id++ ) + { + if ( sce_id == hISMDTX->sce_id_dtx ) + { + hISMDTX->coh[sce_id] = 1.0f; + continue; + } + + st = hSCE[sce_id]->hCoreCoder[0]; + + acorr_ene[sce_id] = 0.0f; + xcorr_ene = 0.0f; + + for ( i = 0; i < input_frame; i++ ) + { + acorr_ene[sce_id] += st->input[i] * st->input[i]; + xcorr_ene += st_id0->input[i] * st->input[i]; + } + + hISMDTX->coh[sce_id] = fabsf( xcorr_ene ) / ( sqrtf( ( acorr_ene[hISMDTX->sce_id_dtx] * acorr_ene[sce_id] ) + EPSILON ) ); + + /* ensure value of coherence is between [0,1] */ + hISMDTX->coh[sce_id] = check_bounds( hISMDTX->coh[sce_id], 0.0f, 1.0f ); + } + + return; +} diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index e363b7f9c3cf6785e99685cf981117e36b28b290..f073609b8ab9c877cba22099bca0abc17ee8eb32 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -61,7 +61,6 @@ ivas_error ivas_ism_enc( float old_inp_12k8[MAX_NUM_OBJECTS][1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ float old_inp_16k[MAX_NUM_OBJECTS][1][L_INP]; /* buffer of input signal @ 16kHz */ int16_t vad_flag[MAX_NUM_OBJECTS]; /* VAD flag */ - float Etot[MAX_NUM_OBJECTS][1]; /* total energy; correlation shift */ float ener[MAX_NUM_OBJECTS][1]; /* residual energy from Levinson-Durbin */ float relE[MAX_NUM_OBJECTS][1]; /* frame relative energy */ float A[MAX_NUM_OBJECTS][1][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ @@ -86,12 +85,48 @@ ivas_error ivas_ism_enc( float Etot_LR[1]; /* total energy; correlation shift */ float lf_E[1][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ int16_t localVAD_HE_SAD[1]; /* local HE VAD */ +#ifdef DISCRETE_ISM_DTX_CNG + int16_t nchan_ism, dtx_flag, sid_flag, flag_noisy_speech; + int16_t md_diff_flag[MAX_NUM_OBJECTS]; +#else +#ifdef NCHAN_ISM_PARAMETER + int16_t nchan_ism, dtx_flag, sid_flag; +#else + int16_t dtx_flag, sid_flag, flag_noisy_speech; +#endif int16_t i, nBits; +#endif ivas_error error; + push_wmops( "ivas_ism_enc" ); + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + error = IVAS_ERR_OK; - wmops_sub_start( "ivas_ism_enc" ); + dtx_flag = 0; + sid_flag = 0; +#if ( !defined NCHAN_ISM_PARAMETER || defined DISCRETE_ISM_DTX_CNG ) + flag_noisy_speech = 0; +#endif + +#ifdef NCHAN_ISM_PARAMETER + nchan_ism = st_ivas->hEncoderConfig->nchan_ism; +#else +#ifdef DISCRETE_ISM_DTX_CNG + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + nchan_ism = st_ivas->hDirAC->hParamIsm->num_obj; + } + else /* ism_mode == ISM_MODE_DISC */ + { + nchan_ism = st_ivas->nchan_transport; + } +#endif +#endif + set_s( md_diff_flag, 1, nchan_ism ); /*------------------------------------------------------------------* * Preprocesing @@ -148,79 +183,139 @@ ivas_error ivas_ism_enc( *----------------------------------------------------------------*/ error = pre_proc_front_ivas( hSCE, NULL, hSCE->element_brate, nb_bits_metadata[sce_id], input_frame, 0, old_inp_12k8[sce_id][0], old_inp_16k[sce_id][0], - &Etot[sce_id][0], &ener[sce_id][0], &relE[sce_id][0], A[sce_id][0], Aw[sce_id][0], epsP[sce_id][0], lsp_new[sce_id][0], lsp_mid[sce_id][0], + &ener[sce_id][0], &relE[sce_id][0], A[sce_id][0], Aw[sce_id][0], epsP[sce_id][0], lsp_new[sce_id][0], lsp_mid[sce_id][0], &vad_hover_flag[sce_id][0], &attack_flag[sce_id][0], realBuffer[sce_id][0], imagBuffer[sce_id][0], old_wsp[sce_id][0], pitch_fr[sce_id][0], voicing_fr[sce_id][0], &loc_harm[sce_id][0], &cor_map_sum[sce_id][0], &vad_flag_dtx[sce_id][0], enerBuffer[sce_id][0], - fft_buff[sce_id][0], A[sce_id][0], lsp_new[sce_id][0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, 0, 0, 0, 0 ); + fft_buff[sce_id][0], A[sce_id][0], lsp_new[sce_id][0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, 0, 0, 0, 0, + st_ivas->hEncoderConfig->ivas_total_brate ); if ( error != IVAS_ERR_OK ) { return error; } - vad_flag[sce_id] = st->vad_flag; +#ifdef DISCRETE_ISM_DTX_CNG + if ( st_ivas->hEncoderConfig->Opt_DTX_ON ) + { + vad_flag[sce_id] = vad_flag_dtx[sce_id][0]; + } + else +#endif + { + vad_flag[sce_id] = st->vad_flag; + } } /*------------------------------------------------------------------* - * Analysis of objects, configuration and decision about bitrates per channel + * DTX analysis *-----------------------------------------------------------------*/ - /* Metadata encoding */ - if ( st_ivas->ism_mode == ISM_MODE_PARAM ) +#ifdef DISCRETE_ISM_DTX_CNG + if ( st_ivas->hEncoderConfig->Opt_DTX_ON ) +#else + if ( st_ivas->hEncoderConfig->Opt_DTX_ON && st_ivas->ism_mode == ISM_MODE_PARAM ) +#endif { - /* Move the Noisy speech buffer */ - for ( i = 0; i < ( PARAM_ISM_HYS_BUF_SIZE - 1 ); i++ ) - { - st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i + 1]; - } + /* compute the dominant sce_id using long term energy */ + ivas_ism_get_sce_id_dtx( st_ivas->hISMDTX, st_ivas->hSCE, st_ivas->nchan_transport, input_frame ); + + /* analysis and decision about DTX */ +#ifdef DISCRETE_ISM_DTX_CNG + dtx_flag = ivas_ism_dtx_enc( st_ivas->hISMDTX, st_ivas->hSCE, st_ivas->hEncoderConfig->ivas_total_brate, nchan_ism, st_ivas->nchan_transport, vad_flag, st_ivas->hIsmMetaData, md_diff_flag, &sid_flag ); +#else + dtx_flag = ivas_ism_dtx_enc( st_ivas, &sid_flag ); +#endif - /* For the current frame, make a decision based on some core-coder flags */ - if ( st_ivas->hSCE[0]->hCoreCoder[0]->flag_noisy_speech_snr && st_ivas->hSCE[1]->hCoreCoder[0]->flag_noisy_speech_snr ) - { - if ( st_ivas->hSCE[0]->hCoreCoder[0]->vad_flag && st_ivas->hSCE[1]->hCoreCoder[0]->vad_flag ) - { - st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = 0; - } - else - { - st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = 1; - } - } - else + if ( sid_flag ) { - st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = 0; + /* estimate coherence between objects */ + ivas_ism_coh_estim_dtx_enc( st_ivas->hISMDTX, st_ivas->hSCE, st_ivas->nchan_transport, input_frame ); } - /* Do a decision based on hysterisis */ - st_ivas->hDirAC->hParamIsm->flag_noisy_speech = 1; - for ( i = 0; i < PARAM_ISM_HYS_BUF_SIZE; i++ ) +#ifdef DEBUG_MODE_PARAM_ISM + if ( st_ivas->hDirAC != NULL ) + dbgwrite( &( st_ivas->hDirAC->hParamIsm->flag_noisy_speech ), sizeof( int16_t ), 1, 1, "./res/ParamISM_noisy_speech_flag_enc.dat" ); + dbgwrite( &( st_ivas->hISMDTX->dtx_flag ), sizeof( int16_t ), 1, 1, "./res/ParamISM_DTX_CNG_flag_enc.dat" ); + dbgwrite( &( st_ivas->hISMDTX->sce_id_dtx ), sizeof( int16_t ), 1, input_frame, "./res/sce_id_dtx" ); + dbgwrite( &( dtx_flag ), sizeof( int16_t ), 1, input_frame, "./res/dtx_flag" ); +#endif + } + + /*------------------------------------------------------------------* + * Analysis of objects, configuration and decision about bitrates per channel + * Metadata quantization and encoding + *-----------------------------------------------------------------*/ + + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + ivas_param_ism_compute_noisy_speech_flag( st_ivas ); +#ifdef DISCRETE_ISM_DTX_CNG + flag_noisy_speech = st_ivas->hDirAC->hParamIsm->flag_noisy_speech; +#endif + } + + if ( dtx_flag ) + { +#ifdef DISCRETE_ISM_DTX_CNG + ivas_ism_metadata_sid_enc( st_ivas->hISMDTX, flag_noisy_speech, nchan_ism, st_ivas->nchan_transport, st_ivas->ism_mode, st_ivas->hIsmMetaData, sid_flag, md_diff_flag, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata ); +#else + if ( sid_flag ) { - st_ivas->hDirAC->hParamIsm->flag_noisy_speech = st_ivas->hDirAC->hParamIsm->flag_noisy_speech && st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i]; +#ifdef NCHAN_ISM_PARAMETER + ivas_param_ism_metadata_dtx_enc( st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, st_ivas->hIsmMetaData, st_ivas->hISMDTX, st_ivas->hDirAC->hParamIsm, nchan_ism ); +#else + ivas_param_ism_metadata_dtx_enc( st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, st_ivas->hIsmMetaData, st_ivas->hISMDTX, st_ivas->hDirAC->hParamIsm ); +#endif } - - ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm ); +#endif + } + else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + // VE: call ivas_ism_metadata_enc() with 'st_ivas' - TBD + ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, +#ifdef NCHAN_ISM_PARAMETER + nchan_ism, +#endif + st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hDirAC->hParamIsm, st_ivas->hEncoderConfig->ism_extended_metadata_flag ); } else /* ISM_MODE_DISC */ { - ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL ); + ivas_ism_metadata_enc( st_ivas->hEncoderConfig->ivas_total_brate, +#ifdef NCHAN_ISM_PARAMETER + nchan_ism, +#endif + st_ivas->nchan_transport, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL, st_ivas->hEncoderConfig->ism_extended_metadata_flag ); } +#ifdef DISCRETE_ISM_DTX_CNG + update_last_metadata( nchan_ism, st_ivas->hIsmMetaData, md_diff_flag ); +#endif + /*----------------------------------------------------------------* - * Write IVAS format signalling in SID frames + * Write IVAS format signaling in SID frames *----------------------------------------------------------------*/ st = st_ivas->hSCE[0]->hCoreCoder[0]; +#ifdef DISCRETE_ISM_DTX_CNG + if ( sid_flag ) +#else if ( st->core_brate == SID_2k40 ) +#endif { ivas_write_format_sid( st_ivas->hEncoderConfig->ivas_format, IVAS_SCE, st->hBstr ); - /* write unused bits */ - nBits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; - while ( nBits > 0 ) +#ifndef DISCRETE_ISM_DTX_CNG + if ( st_ivas->ism_mode != ISM_MODE_PARAM ) { - i = min( nBits, 16 ); - push_indice( st->hBstr, IND_UNUSED, 0, i ); - nBits -= i; + /* write unused bits */ + nBits = ( IVAS_SID_5k2 - SID_2k40 ) / 50 - SID_FORMAT_NBITS; + while ( nBits > 0 ) + { + i = min( nBits, 16 ); + push_indice( st->hBstr, IND_UNUSED, 0, i ); + nBits -= i; + } } +#endif } /*------------------------------------------------------------------* @@ -262,9 +357,12 @@ ivas_error ivas_ism_enc( * Encoder *----------------------------------------------------------------*/ - if ( ( error = ivas_core_enc( hSCE, NULL, NULL, 1, old_inp_12k8[sce_id], old_inp_16k[sce_id], Etot[sce_id], ener[sce_id], A[sce_id], Aw[sce_id], epsP[sce_id], lsp_new[sce_id], lsp_mid[sce_id], vad_hover_flag[sce_id], attack_flag[sce_id], realBuffer[sce_id], imagBuffer[sce_id], old_wsp[sce_id], loc_harm[sce_id], cor_map_sum[sce_id], vad_flag_dtx[sce_id], enerBuffer[sce_id], fft_buff[sce_id], 0, 0 ) ) != IVAS_ERR_OK ) + if ( !dtx_flag || ( dtx_flag && sce_id == st_ivas->hISMDTX->sce_id_dtx ) ) { - return error; + if ( ( error = ivas_core_enc( hSCE, NULL, NULL, 1, old_inp_12k8[sce_id], old_inp_16k[sce_id], ener[sce_id], A[sce_id], Aw[sce_id], epsP[sce_id], lsp_new[sce_id], lsp_mid[sce_id], vad_hover_flag[sce_id], attack_flag[sce_id], realBuffer[sce_id], imagBuffer[sce_id], old_wsp[sce_id], loc_harm[sce_id], cor_map_sum[sce_id], vad_flag_dtx[sce_id], enerBuffer[sce_id], fft_buff[sce_id], 0, ISM_FORMAT, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } } /*----------------------------------------------------------------* @@ -273,9 +371,135 @@ ivas_error ivas_ism_enc( /* update input samples buffer */ mvr2r( st->input, st->old_input_signal, input_frame ); + + /* Store previous attack detection flag */ + st->hTranDet->transientDetector.prev_bIsAttackPresent = st->hTranDet->transientDetector.bIsAttackPresent; + } + + if ( dtx_flag ) + { + for ( sce_id = 0; sce_id < st_ivas->nchan_transport; sce_id++ ) + { + if ( sce_id != st_ivas->hISMDTX->sce_id_dtx ) + { + st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_core = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->last_core; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_core_brate = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->core_brate; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_L_frame = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->last_L_frame; + } + } + } + +#ifdef DISCRETE_ISM_DTX_CNG +#ifdef DEBUG_MODE_INFO + if ( dtx_flag ) + { + float tmpF; + int16_t id, n; + + n = 0; + for ( sce_id = 0; sce_id < st_ivas->nchan_transport; sce_id++ ) + { + if ( sce_id != st_ivas->hISMDTX->sce_id_dtx ) + { + st = st_ivas->hSCE[sce_id]->hCoreCoder[0]; + id = st->id_element; + + dbgwrite( &st->core, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "core", n, id, ENC ) ); + dbgwrite( &st->extl, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "extl", n, id, ENC ) ); + dbgwrite( &st->bwidth, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "bwidth", n, id, ENC ) ); + tmpF = st->total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "total_brate", n, id, ENC ) ); + tmpF = st->core_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "core_brate", n, id, ENC ) ); + tmpF = st->extl_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "extl_brate", n, id, ENC ) ); + + dbgwrite( &st->coder_type, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type", n, id, ENC ) ); + dbgwrite( &st->coder_type_raw, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type_raw", n, id, ENC ) ); + dbgwrite( &st->vad_flag, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "vad_flag", n, id, ENC ) ); + dbgwrite( &st->localVAD, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "localVAD", n, id, ENC ) ); + + dbgwrite( &st->lp_noise, sizeof( float ), 1, input_frame, fname( debug_dir, "lp_noise", n, id, ENC ) ); + } + } } +#endif +#endif + pop_wmops(); + + return error; +} + + +/*------------------------------------------------------------------------- + * ivas_ism_enc_config() + * + * - select ISM format mode + * - reconfigure the ISM format encoder + *-------------------------------------------------------------------------*/ + +ivas_error ivas_ism_enc_config( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + ivas_error error; + ISM_MODE last_ism_mode; + int16_t nchan_transport_old; + int16_t nSCE_old, nCPE_old; + + error = IVAS_ERR_OK; + last_ism_mode = st_ivas->ism_mode; + + /* select ISM format mode */ + st_ivas->ism_mode = ivas_ism_mode_select( st_ivas->hEncoderConfig->nchan_inp, st_ivas->hEncoderConfig->ivas_total_brate ); + + /* ISM bit-rate switching */ + if ( ( st_ivas->ism_mode != last_ism_mode ) || ( st_ivas->hEncoderConfig->ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + int32_t element_brate_tmp[MAX_NUM_OBJECTS]; + + nchan_transport_old = st_ivas->nchan_transport; + + /* Reset and Initialize */ + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + st_ivas->nchan_transport = MAX_PARAM_ISM_WAVE; + } + else + { + st_ivas->nchan_transport = st_ivas->hEncoderConfig->nchan_inp; + } + + nCPE_old = st_ivas->nCPE; + nSCE_old = st_ivas->nSCE; + st_ivas->nSCE = st_ivas->nchan_transport; + st_ivas->nCPE = 0; + + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hEncoderConfig->nchan_inp, NULL, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport, ( st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS, MC_MODE_NONE ) ) != IVAS_ERR_OK ) + { + return error; + } - wmops_sub_end(); + if ( st_ivas->ism_mode == ISM_MODE_PARAM && last_ism_mode == ISM_MODE_DISC ) + { + /* Allocate and Initialize the memory used by ParamISM when switch from Discrete ISM */ + if ( ( error = ivas_param_ism_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->ism_mode == ISM_MODE_DISC && last_ism_mode == ISM_MODE_PARAM ) + { + /* Deallocate the memory used by ParamISM when switch to Discrete ISM */ + ivas_param_ism_enc_close( &( st_ivas->hDirAC ), st_ivas->hEncoderConfig->input_Fs ); + } + } return error; } diff --git a/lib_enc/ivas_ism_metadata_enc.c b/lib_enc/ivas_ism_metadata_enc.c index a3bfac4ba25d8649ee4083311d7015ac5647fcb5..d34479ad2dfe3ea691a743bc24567febbae7fd06 100644 --- a/lib_enc/ivas_ism_metadata_enc.c +++ b/lib_enc/ivas_ism_metadata_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,34 +42,51 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * Local constants *-----------------------------------------------------------------------*/ -#define ISM_NUM_PARAM 2 /* number of coded metadata parameters */ +#define ISM_NUM_PARAM 5 /* number of coded metadata parameters */ #define ISM_MAX_AZIMUTH_DIFF_IDX ( ISM_AZIMUTH_NBITS - 1 /*zero*/ - 1 /*sign*/ ) #define ISM_MAX_ELEVATION_DIFF_IDX ( ISM_ELEVATION_NBITS - 1 /*zero*/ - 1 /*sign*/ ) +#define ISM_MAX_RADIUS_DIFF_IDX ( ISM_RADIUS_NBITS - 1 /*zero*/ - 1 /*sign*/ ) #define ISM_FEC_MAX 10 #define INTER_OBJECT_PARAM_CHECK ( ( ISM_FEC_MAX / 2 ) - 2 ) /* note: constant must be less than (ISM_FEC_MAX / number of coded parameters) */ +/*-----------------------------------------------------------------------* + * Local function declarations + *-----------------------------------------------------------------------*/ + +#ifdef FIX_379_ANGLE +static void encode_angle_indices( BSTR_ENC_HANDLE hBstr, ISM_METADATA_ANGLE_HANDLE angle, const int16_t last_ism_metadata_flag, const int16_t ini_frame, const int16_t idx_angle1_abs, const int16_t idx_angle2_abs, int16_t *flag_abs_angle1, int16_t *flag_abs_angle2 ); +#else +static void encode_angle_indices( BSTR_ENC_HANDLE hBstr, ISM_METADATA_ANGLE_HANDLE angle, const int16_t last_ism_metadata_flag, const int16_t ini_frame, const int16_t idx_azimuth_abs, const int16_t idx_elevation_abs, int16_t *flag_abs_azimuth, int16_t *flag_abs_elevation ); +#endif + +static void encode_radius( BSTR_ENC_HANDLE hBstr, int16_t *last_radius_idx, int16_t *radius_diff_cnt, const int16_t last_ism_metadata_flag, const int16_t idx_radius_abs, int16_t *flag_abs_radius ); + + /*-------------------------------------------------------------------------* - * set_ism_metadata() + * ivas_set_ism_metadata() * - * Set metadata of for one ISM + * Set metadata of one ISM MD handle *-------------------------------------------------------------------------*/ -/*! r: 0 if success */ -ivas_error set_ism_metadata( - ISM_METADATA_HANDLE hIsmMeta, - float azimuth, - float elevation ) +ivas_error ivas_set_ism_metadata( + ISM_METADATA_HANDLE hIsmMeta, /* o : ISM metadata handle */ + const float azimuth, /* i : azimuth value */ + const float elevation, /* i : elevation */ + const float radius_meta, /* i : radius */ + const float yaw, /* i : yaw */ + const float pitch /* i : pitch */ +) { if ( hIsmMeta == NULL ) { @@ -81,6 +98,9 @@ ivas_error set_ism_metadata( /* save read metadata parameters to the internal codec structure */ hIsmMeta->azimuth = azimuth; hIsmMeta->elevation = elevation; + hIsmMeta->radius = radius_meta; + hIsmMeta->yaw = yaw; + hIsmMeta->pitch = pitch; return IVAS_ERR_OK; } @@ -89,7 +109,7 @@ ivas_error set_ism_metadata( /*-------------------------------------------------------------------------* * rate_ism_importance() * - * Rate importance of particular ISm streams + * Rate importance of particular ISM streams *-------------------------------------------------------------------------*/ static void rate_ism_importance( @@ -105,6 +125,18 @@ static void rate_ism_importance( { ctype = hSCE[ch]->hCoreCoder[0]->coder_type_raw; + if ( hSCE[ch]->hCoreCoder[0]->tcxonly ) + { + if ( hSCE[ch]->hCoreCoder[0]->localVAD == 0 ) + { + ctype = INACTIVE; + } + else if ( ctype == UNVOICED ) + { + ctype = GENERIC; + } + } + if ( hIsmMeta[ch]->ism_metadata_flag == 0 ) { ism_imp[ch] = ISM_NO_META; @@ -126,6 +158,7 @@ static void rate_ism_importance( return; } + /*-------------------------------------------------------------------------* * ivas_ism_metadata_enc() * @@ -133,64 +166,94 @@ static void rate_ism_importance( *-------------------------------------------------------------------------*/ ivas_error ivas_ism_metadata_enc( - const int32_t ism_total_brate, /* i : ISms total bitrate */ - const int16_t nchan_transport, /* i : number of transport channels */ - ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ - SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */ - BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ - int16_t nb_bits_metadata[], /* o : number of metadata bits */ - const int16_t localVAD[], /* i : VAD flag */ - const int16_t ism_mode, /* i : ISM mode */ - const PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Enc Handle */ + const int32_t ism_total_brate, /* i : ISM total bitrate */ +#ifdef NCHAN_ISM_PARAMETER + const int16_t nchan_ism, /* i : number of ISM channels */ +#endif + const int16_t nchan_transport, /* i : number of transport channels */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + SCE_ENC_HANDLE hSCE[], /* i/o: SCE encoder handles */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + int16_t nb_bits_metadata[], /* o : number of metadata bits */ + const int16_t localVAD[], /* i : VAD flag */ + const int16_t ism_mode, /* i : ISM mode */ + const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i : Param ISM Enc Handle */ + const int16_t ism_extended_metadata_flag /* i : Extended metadata flag */ ) { - int16_t i, ch, nb_bits_start = 0, diff; - int16_t idx_azimuth, idx_azimuth_abs = 0, flag_abs_azimuth[MAX_NUM_OBJECTS], nbits_diff_azimuth; - int16_t idx_elevation, idx_elevation_abs = 0, flag_abs_elevation[MAX_NUM_OBJECTS], nbits_diff_elevation; + int16_t i, ch, nb_bits_start = 0; +#ifdef FIX_379_ANGLE + int16_t flag_abs_azimuth[MAX_NUM_OBJECTS]; + int16_t flag_abs_elevation[MAX_NUM_OBJECTS]; + int16_t idx_angle1_abs = 0; + int16_t idx_angle2_abs = 0; + int16_t flag_abs_yaw[MAX_NUM_OBJECTS]; + int16_t flag_abs_pitch[MAX_NUM_OBJECTS]; +#else + int16_t idx_azimuth_abs = 0, flag_abs_azimuth[MAX_NUM_OBJECTS]; + int16_t idx_elevation_abs = 0, flag_abs_elevation[MAX_NUM_OBJECTS]; + int16_t flag_abs_azimuth_orientation[MAX_NUM_OBJECTS]; +#endif + int16_t idx_radius_abs = 0, flag_abs_radius[MAX_NUM_OBJECTS]; float valQ; ISM_METADATA_HANDLE hIsmMetaData; int32_t element_brate[MAX_NUM_OBJECTS], total_brate[MAX_NUM_OBJECTS]; int16_t ism_metadata_flag_global; int16_t ism_imp[MAX_NUM_OBJECTS]; - int16_t num_obj, nbands, nblocks; +#ifdef NCHAN_ISM_PARAMETER + int16_t nbands, nblocks; +#else + int16_t nchan_ism, nbands, nblocks; +#endif ivas_error error; error = IVAS_ERR_OK; - wmops_sub_start( "ism_meta_enc" ); + push_wmops( "ism_meta_enc" ); +#ifndef NCHAN_ISM_PARAMETER if ( ism_mode == ISM_MODE_PARAM ) { - num_obj = hParamIsm->num_obj; + nchan_ism = hParamIsm->num_obj; } else if ( ism_mode == ISM_MODE_DISC ) { - num_obj = nchan_transport; + nchan_ism = nchan_transport; } else { return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: incorrect ISM mode" ); } +#endif - if ( num_obj == 1 && ( hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 || hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) && ( ism_mode == ISM_MODE_DISC ) ) +#ifndef DISCRETE_ISM_DTX_CNG + if ( nchan_ism == 1 && ( hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 || hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA ) && ism_mode == ISM_MODE_DISC ) { /* no metadata encoding in CNG */ - wmops_sub_end(); + pop_wmops(); return error; } +#endif /* initialization */ ism_metadata_flag_global = 0; set_s( nb_bits_metadata, 0, nchan_transport ); - set_s( flag_abs_azimuth, 0, num_obj ); - set_s( flag_abs_elevation, 0, num_obj ); + set_s( flag_abs_azimuth, 0, nchan_ism ); + set_s( flag_abs_elevation, 0, nchan_ism ); +#ifdef FIX_379_ANGLE + set_s( flag_abs_yaw, 0, nchan_ism ); + set_s( flag_abs_pitch, 0, nchan_ism ); +#else + set_s( flag_abs_azimuth_orientation, 0, nchan_ism ); +#endif + set_s( flag_abs_radius, 0, nchan_ism ); /*----------------------------------------------------------------* * Set Metadata presence / importance flag *----------------------------------------------------------------*/ - for ( ch = 0; ch < num_obj; ch++ ) + for ( ch = 0; ch < nchan_ism; ch++ ) { if ( ism_mode == ISM_MODE_PARAM ) { @@ -198,72 +261,49 @@ ivas_error ivas_ism_metadata_enc( } else if ( ism_mode == ISM_MODE_DISC ) { - hIsmMeta[ch]->ism_metadata_flag = localVAD[ch]; - - if ( hIsmMeta[ch]->ism_metadata_flag == 0 ) +#ifdef DISCRETE_ISM_DTX_CNG + hIsmMeta[ch]->ism_metadata_flag = localVAD[ch] || hSCE[ch]->hCoreCoder[0]->lp_noise > 10; +#else + /* In case of low level noise for low bitrate inactive frames, do not sent metadata */ + if ( localVAD[ch] == 0 && !( hSCE[ch]->hCoreCoder[0]->tcxonly ) && ( hSCE[ch]->hCoreCoder[0]->lp_noise <= 10 ) ) { - /* send metadata even in inactive segments when noise is audible and metadata are changing */ - diff = (int16_t) fabsf( hIsmMeta[ch]->azimuth - ism_dequant_meta( hIsmMeta[ch]->last_azimuth_idx, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ) ); - diff = max( diff, (int16_t) fabsf( hIsmMeta[ch]->elevation - ism_dequant_meta( hIsmMeta[ch]->last_elevation_idx, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ) ) ); - - if ( hSCE[ch]->hCoreCoder[0]->lp_noise > 15 && diff >= 10 ) - { - hIsmMeta[ch]->ism_metadata_flag = 1; - } - } - - if ( hSCE[ch]->hCoreCoder[0]->tcxonly ) - { - /* at highest bitrates (with TCX core only) metadata are sent in every frame */ - hIsmMeta[ch]->ism_metadata_flag = 1; + hIsmMeta[ch]->ism_metadata_flag = 0; } +#endif } } /*----------------------------------------------------------------* - * Rate importance of particular ISm streams + * Rate importance of particular ISM streams *----------------------------------------------------------------*/ rate_ism_importance( nchan_transport, hIsmMeta, hSCE, ism_imp ); - /* relax the importance decision in "stereo" coding for noisy audio */ - if ( ism_mode == ISM_MODE_DISC && num_obj == 2 ) - { - float diff_F; - - if ( hIsmMeta[0]->ism_metadata_flag ^ hIsmMeta[1]->ism_metadata_flag ) - { - for ( ch = 0; ch < num_obj; ch++ ) - { - diff_F = hSCE[ch]->hCoreCoder[0]->lp_speech - hSCE[ch]->hCoreCoder[0]->lp_noise; - - if ( hIsmMeta[ch]->ism_metadata_flag == 0 && diff_F < 25.0f ) - { - hIsmMeta[ch]->ism_metadata_flag = 1; - ism_imp[ch] = ISM_LOW_IMP; - } - } - } - } /*----------------------------------------------------------------* - * Write ISm common signalling + * Write ISM common signaling *----------------------------------------------------------------*/ /* write number of objects - unary coding */ - for ( ch = 1; ch < num_obj; ch++ ) + for ( ch = 1; ch < nchan_ism; ch++ ) { push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 ); } push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 ); - /* write ISm metadata flag (one per object) */ + /* write extended metadata presence flag */ + if ( ism_total_brate >= ISM_EXTENDED_METADATA_BRATE ) + { + push_indice( hBstr, IND_ISM_EXTENDED_FLAG, ism_extended_metadata_flag, ISM_EXTENDED_METADATA_BITS ); + } + + /* write ISM metadata flag (one per object) */ for ( ch = 0; ch < nchan_transport; ch++ ) { push_indice( hBstr, IND_ISM_METADATA_FLAG, ism_imp[ch], ISM_METADATA_FLAG_BITS ); } - for ( ch = 0; ch < num_obj; ch++ ) + for ( ch = 0; ch < nchan_ism; ch++ ) { ism_metadata_flag_global |= hIsmMeta[ch]->ism_metadata_flag; } @@ -295,7 +335,7 @@ ivas_error ivas_ism_metadata_enc( nb_bits_start = hBstr->nb_bits_tot; } - for ( ch = 0; ch < num_obj; ch++ ) + for ( ch = 0; ch < nchan_ism; ch++ ) { hIsmMetaData = hIsmMeta[ch]; if ( ism_mode == ISM_MODE_DISC ) @@ -306,244 +346,56 @@ ivas_error ivas_ism_metadata_enc( if ( hIsmMeta[ch]->ism_metadata_flag ) { /*----------------------------------------------------------------* - * Azimuth quantization and encoding + * Quantize and encode azimuth and elevation *----------------------------------------------------------------*/ - /* Azimuth quantization (quantize azimuth to the AZIMUTH_NBITS-bit index */ if ( ism_mode == ISM_MODE_DISC ) { - idx_azimuth_abs = ism_quant_meta( hIsmMetaData->azimuth, &valQ, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); +#ifdef FIX_379_ANGLE + idx_angle1_abs = ism_quant_meta( hIsmMetaData->azimuth, &valQ, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + idx_angle2_abs = ism_quant_meta( hIsmMetaData->elevation, &valQ, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#else + idx_azimuth_abs = ism_quant_meta( hIsmMetaData->azimuth, &valQ, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + idx_elevation_abs = ism_quant_meta( hIsmMetaData->elevation, &valQ, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#endif } - else if ( ism_mode == ISM_MODE_PARAM ) + else /* ISM_MODE_PARAM */ { +#ifdef FIX_379_ANGLE + idx_angle1_abs = hParamIsm->azi_index[ch]; + idx_angle2_abs = hParamIsm->ele_index[ch]; +#else idx_azimuth_abs = hParamIsm->azi_index[ch]; + idx_elevation_abs = hParamIsm->ele_index[ch]; +#endif } - idx_azimuth = idx_azimuth_abs; - - nbits_diff_azimuth = 0; - - flag_abs_azimuth[ch] = 0; /* differential coding by default */ - if ( hIsmMetaData->azimuth_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ - || hIsmMetaData->last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ - ) - { - flag_abs_azimuth[ch] = 1; - } - - /* try differential coding */ - if ( flag_abs_azimuth[ch] == 0 ) - { - diff = idx_azimuth_abs - hIsmMetaData->last_azimuth_idx; - - /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ - if ( abs( diff ) > ( ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - ISM_MAX_AZIMUTH_DIFF_IDX ) - { - if ( diff > 0 ) - { - diff -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; - } - else - { - diff += ( 1 << ISM_AZIMUTH_NBITS ) - 1; - } - } - - if ( diff == 0 ) - { - idx_azimuth = 0; - nbits_diff_azimuth = 1; - } - else if ( ABSVAL( diff ) < ISM_MAX_AZIMUTH_DIFF_IDX ) /* when diff bits >= abs bits, prefer abs */ - { - idx_azimuth = 1 << 1; - nbits_diff_azimuth = 1; - - if ( diff < 0 ) - { - idx_azimuth += 1; /* negative sign */ - diff *= -1; - } - else - { - idx_azimuth += 0; /* positive sign */ - } - - idx_azimuth = idx_azimuth << diff; - nbits_diff_azimuth++; - - /* unary coding of "diff */ - idx_azimuth += ( ( 1 << diff ) - 1 ); - nbits_diff_azimuth += diff; - - if ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) - { - /* add stop bit - only for codewords shorter than ISM_AZIMUTH_NBITS */ - idx_azimuth = idx_azimuth << 1; - nbits_diff_azimuth++; - } - } - else - { - flag_abs_azimuth[ch] = 1; - } - } - - /* update counter */ - if ( flag_abs_azimuth[ch] == 0 ) - { - hIsmMetaData->azimuth_diff_cnt++; - hIsmMetaData->elevation_diff_cnt = min( hIsmMetaData->elevation_diff_cnt, ISM_FEC_MAX ); - } - else - { - hIsmMetaData->azimuth_diff_cnt = 0; - } - - /* Write azimuth */ - push_indice( hBstr, IND_ISM_AZIMUTH_DIFF_FLAG, flag_abs_azimuth[ch], 1 ); - - if ( flag_abs_azimuth[ch] ) - { - push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, ISM_AZIMUTH_NBITS ); - } - else - { - push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, nbits_diff_azimuth ); - } - +#ifdef FIX_379_ANGLE + encode_angle_indices( hBstr, &( hIsmMetaData->position_angle ), hIsmMetaData->last_ism_metadata_flag, hSCE[0]->hCoreCoder[0]->ini_frame, idx_angle1_abs, idx_angle2_abs, &flag_abs_azimuth[ch], &flag_abs_elevation[ch] ); +#else + encode_angle_indices( hBstr, &( hIsmMetaData->angle[0] ), hIsmMetaData->last_ism_metadata_flag, hSCE[0]->hCoreCoder[0]->ini_frame, idx_azimuth_abs, idx_elevation_abs, &flag_abs_azimuth[ch], &flag_abs_elevation[ch] ); +#endif /*----------------------------------------------------------------* - * Elevation quantization and encoding + * Quantize and encode radius, yaw, and pitch *----------------------------------------------------------------*/ - /* Elevation quantization (quantize azimuth to the ELEVATION_NBITS-bit index */ - if ( ism_mode == ISM_MODE_DISC ) - { - idx_elevation_abs = ism_quant_meta( hIsmMetaData->elevation, &valQ, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); - } - else /* ISM_MODE_PARAM */ - { - idx_elevation_abs = hParamIsm->ele_index[ch]; - } - idx_elevation = idx_elevation_abs; - - nbits_diff_elevation = 0; - - flag_abs_elevation[ch] = 0; /* differential coding by default */ - if ( hIsmMetaData->elevation_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ - || hIsmMetaData->last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ - ) - { - flag_abs_elevation[ch] = 1; - } - - /* note: elevation is coded starting from the second frame only (it is meaningless in the init_frame) */ - if ( hSCE[0]->hCoreCoder[0]->ini_frame == 0 ) - { - flag_abs_elevation[ch] = 1; - hIsmMetaData->last_elevation_idx = idx_elevation_abs; - } - - diff = idx_elevation_abs - hIsmMetaData->last_elevation_idx; - - /* avoid absolute coding of elevation if absolute coding was already used for azimuth */ - if ( flag_abs_azimuth[ch] == 1 ) - { - int16_t diff_orig = diff; - - flag_abs_elevation[ch] = 0; - - - if ( diff >= 0 ) - { - diff = min( diff, ISM_MAX_ELEVATION_DIFF_IDX ); - } - else - { - diff = -1 * min( -diff, ISM_MAX_ELEVATION_DIFF_IDX ); - } - - if ( hIsmMetaData->last_ism_metadata_flag == 0 || abs( diff_orig - diff ) > ISM_MAX_ELEVATION_DIFF_IDX ) - { - hIsmMetaData->elevation_diff_cnt = ISM_FEC_MAX - 1; - } - } - - /* try differential coding */ - if ( flag_abs_elevation[ch] == 0 ) - { - if ( diff == 0 ) - { - idx_elevation = 0; - nbits_diff_elevation = 1; - } - else if ( ABSVAL( diff ) <= ISM_MAX_ELEVATION_DIFF_IDX ) - { - idx_elevation = 1 << 1; - nbits_diff_elevation = 1; - - if ( diff < 0 ) - { - idx_elevation += 1; /* negative sign */ - diff *= -1; - } - else - { - idx_elevation += 0; /* positive sign */ - } - - idx_elevation = idx_elevation << diff; - nbits_diff_elevation++; - - /* unary coding of "diff */ - idx_elevation += ( ( 1 << diff ) - 1 ); - nbits_diff_elevation += diff; - - if ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) - { - /* add stop bit */ - idx_elevation = idx_elevation << 1; - nbits_diff_elevation++; - } - } - else - { - flag_abs_elevation[ch] = 1; - } - } - - /* update counter */ - if ( flag_abs_elevation[ch] == 0 ) - { - hIsmMetaData->elevation_diff_cnt++; - hIsmMetaData->elevation_diff_cnt = min( hIsmMetaData->elevation_diff_cnt, ISM_FEC_MAX ); - } - else - { - hIsmMetaData->elevation_diff_cnt = 0; - } - - /* Write elevation */ - if ( flag_abs_azimuth[ch] == 0 ) /* do not write "flag_abs_elevation" if "flag_abs_azimuth == 1" */ - { - push_indice( hBstr, IND_ISM_ELEVATION_DIFF_FLAG, flag_abs_elevation[ch], 1 ); - } - - if ( flag_abs_elevation[ch] ) - { - push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, ISM_ELEVATION_NBITS ); - } - else + if ( ism_mode == ISM_MODE_DISC && ism_extended_metadata_flag ) { - push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, nbits_diff_elevation ); +#ifdef FIX_379_ANGLE + idx_angle1_abs = ism_quant_meta( hIsmMetaData->yaw, &valQ, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + idx_angle2_abs = ism_quant_meta( hIsmMetaData->pitch, &valQ, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#else + idx_azimuth_abs = ism_quant_meta( hIsmMetaData->yaw, &valQ, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); + idx_elevation_abs = ism_quant_meta( hIsmMetaData->pitch, &valQ, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); +#endif + idx_radius_abs = usquant( hIsmMetaData->radius, &valQ, ISM_RADIUS_MIN, ISM_RADIUS_DELTA, 1 << ISM_RADIUS_NBITS ); +#ifdef FIX_379_ANGLE + encode_angle_indices( hBstr, &( hIsmMetaData->orientation_angle ), hIsmMetaData->last_ism_metadata_flag, hSCE[0]->hCoreCoder[0]->ini_frame, idx_angle1_abs, idx_angle2_abs, &flag_abs_yaw[ch], &flag_abs_pitch[ch] ); +#else + encode_angle_indices( hBstr, &( hIsmMetaData->angle[1] ), hIsmMetaData->last_ism_metadata_flag, hSCE[0]->hCoreCoder[0]->ini_frame, idx_azimuth_abs, idx_elevation_abs, &flag_abs_azimuth_orientation[ch], &flag_abs_elevation[ch] ); +#endif + encode_radius( hBstr, &hIsmMetaData->last_radius_idx, &hIsmMetaData->radius_diff_cnt, hIsmMetaData->last_ism_metadata_flag, idx_radius_abs, &flag_abs_radius[ch] ); } - /*----------------------------------------------------------------* - * Updates - *----------------------------------------------------------------*/ - - hIsmMetaData->last_azimuth_idx = idx_azimuth_abs; - hIsmMetaData->last_elevation_idx = idx_elevation_abs; - /* save number of metadata bits written */ if ( ism_mode == ISM_MODE_DISC ) { @@ -558,12 +410,12 @@ ivas_error ivas_ism_metadata_enc( *----------------------------------------------------------------*/ i = 0; - while ( i == 0 || i < num_obj / INTER_OBJECT_PARAM_CHECK ) + while ( i == 0 || i < nchan_ism / INTER_OBJECT_PARAM_CHECK ) { int16_t num, abs_num, abs_first, abs_next, pos_zero; - int16_t abs_matrice[INTER_OBJECT_PARAM_CHECK * 2]; + int16_t abs_matrice[INTER_OBJECT_PARAM_CHECK * ISM_NUM_PARAM]; - num = min( INTER_OBJECT_PARAM_CHECK, num_obj - i * INTER_OBJECT_PARAM_CHECK ); + num = min( INTER_OBJECT_PARAM_CHECK, nchan_ism - i * INTER_OBJECT_PARAM_CHECK ); i++; set_s( abs_matrice, 0, INTER_OBJECT_PARAM_CHECK * ISM_NUM_PARAM ); @@ -609,12 +461,20 @@ ivas_error ivas_ism_metadata_enc( if ( abs_next % ISM_NUM_PARAM == 0 ) { - hIsmMeta[ch]->azimuth_diff_cnt = abs_num - 1; +#ifdef FIX_379_ANGLE + hIsmMeta[ch]->position_angle.angle1_diff_cnt = abs_num - 1; +#else + hIsmMeta[ch]->angle[0].azimuth_diff_cnt = abs_num - 1; +#endif } if ( abs_next % ISM_NUM_PARAM == 1 ) { - hIsmMeta[ch]->elevation_diff_cnt = abs_num - 1; +#ifdef FIX_379_ANGLE + hIsmMeta[ch]->position_angle.angle2_diff_cnt = abs_num - 1; +#else + hIsmMeta[ch]->angle[0].elevation_diff_cnt = abs_num - 1; +#endif /*hIsmMeta[ch]->elevation_diff_cnt = min( hIsmMeta[ch]->elevation_diff_cnt, ISM_FEC_MAX );*/ } @@ -677,9 +537,12 @@ ivas_error ivas_ism_metadata_enc( * Configuration and decision about bitrates per channel *----------------------------------------------------------------*/ - ivas_ism_config( ism_total_brate, nchan_transport, num_obj, hIsmMeta, localVAD, ism_imp, element_brate, total_brate, nb_bits_metadata ); + if ( ( error = ivas_ism_config( ism_total_brate, nchan_transport, nchan_ism, hIsmMeta, localVAD, ism_imp, element_brate, total_brate, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } - for ( ch = 0; ch < num_obj; ch++ ) + for ( ch = 0; ch < nchan_ism; ch++ ) { hIsmMeta[ch]->last_ism_metadata_flag = hIsmMeta[ch]->ism_metadata_flag; } @@ -705,28 +568,30 @@ ivas_error ivas_ism_metadata_enc( } } - wmops_sub_end(); + pop_wmops(); return error; } + /*------------------------------------------------------------------------- - * create_ism_metadata_enc() + * ivas_ism_metadata_enc_create() * - * Create, allocate, initialize and configure IVAS encoder ISM handles + * Create, allocate, initialize and configure IVAS encoder ISM metadata handles *-------------------------------------------------------------------------*/ -ivas_error create_ism_metadata_enc( +ivas_error ivas_ism_metadata_enc_create( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const int16_t n_ISms, /* i : number of objects */ int32_t element_brate_tmp[] /* o : element bitrate per object */ ) { int16_t ch, nchan_transport; + ivas_error error; if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { - nchan_transport = 2; + nchan_transport = MAX_PARAM_ISM_WAVE; } else { @@ -737,24 +602,789 @@ ivas_error create_ism_metadata_enc( st_ivas->nSCE = nchan_transport; st_ivas->nCPE = 0; - /* allocate ISm metadata handles */ + /* allocate ISM metadata handles */ for ( ch = 0; ch < n_ISms; ch++ ) { - if ( ( st_ivas->hIsmMetaData[ch] = (ISM_METADATA_HANDLE) count_malloc( sizeof( ISM_METADATA_FRAME ) ) ) == NULL ) + if ( ( st_ivas->hIsmMetaData[ch] = (ISM_METADATA_HANDLE) malloc( sizeof( ISM_METADATA_FRAME ) ) ) == NULL ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISm MetaData\n" ) ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM MetaData\n" ) ); } - - st_ivas->hIsmMetaData[ch]->last_azimuth_idx = 0; - st_ivas->hIsmMetaData[ch]->azimuth_diff_cnt = ISM_FEC_MAX; - st_ivas->hIsmMetaData[ch]->last_elevation_idx = 0; - st_ivas->hIsmMetaData[ch]->elevation_diff_cnt = ISM_FEC_MAX - 1; +#ifdef FIX_379_ANGLE + st_ivas->hIsmMetaData[ch]->position_angle.last_angle1_idx = 0; + st_ivas->hIsmMetaData[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX; + st_ivas->hIsmMetaData[ch]->position_angle.last_angle2_idx = 0; + st_ivas->hIsmMetaData[ch]->position_angle.angle2_diff_cnt = ISM_FEC_MAX - 1; + st_ivas->hIsmMetaData[ch]->orientation_angle.last_angle1_idx = 0; + st_ivas->hIsmMetaData[ch]->orientation_angle.angle1_diff_cnt = ISM_FEC_MAX - 2; + st_ivas->hIsmMetaData[ch]->orientation_angle.last_angle2_idx = 0; + st_ivas->hIsmMetaData[ch]->orientation_angle.angle2_diff_cnt = ISM_FEC_MAX - 2; +#else + st_ivas->hIsmMetaData[ch]->angle[0].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[0].azimuth_diff_cnt = ISM_FEC_MAX; + st_ivas->hIsmMetaData[ch]->angle[0].last_elevation_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[0].elevation_diff_cnt = ISM_FEC_MAX - 1; + st_ivas->hIsmMetaData[ch]->angle[1].last_azimuth_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[1].azimuth_diff_cnt = ISM_FEC_MAX - 2; + st_ivas->hIsmMetaData[ch]->angle[1].last_elevation_idx = 0; + st_ivas->hIsmMetaData[ch]->angle[1].elevation_diff_cnt = ISM_FEC_MAX - 2; +#endif + st_ivas->hIsmMetaData[ch]->last_radius_idx = 0; + st_ivas->hIsmMetaData[ch]->radius_diff_cnt = ISM_FEC_MAX - 2; st_ivas->hIsmMetaData[ch]->last_ism_metadata_flag = 0; ivas_ism_reset_metadata( st_ivas->hIsmMetaData[ch] ); + +#ifdef DISCRETE_ISM_DTX_CNG + st_ivas->hIsmMetaData[ch]->last_azimuth = 0.0f; + st_ivas->hIsmMetaData[ch]->last_elevation = 0.0f; +#endif } - ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, n_ISms, NULL, NULL, NULL, element_brate_tmp, NULL, NULL ); + if ( ( error = ivas_ism_config( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, n_ISms, NULL, NULL, NULL, element_brate_tmp, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } return IVAS_ERR_OK; } + + +/*------------------------------------------------------------------------- + * encode_radius() + * + * Radius index encoding + *-------------------------------------------------------------------------*/ + +static void encode_radius( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + int16_t *last_radius_idx, /* i/o: last radius index */ + int16_t *radius_diff_cnt, /* i/o: radius diff coding counter */ + const int16_t last_ism_metadata_flag, /* last frame ism_metadata_flag */ + const int16_t idx_radius_abs, /* i : Azimuth index */ + int16_t *flag_abs_radius /* o : Radius encoding mode */ +) +{ + int16_t idx_radius, nbits_diff_radius, diff; + + idx_radius = idx_radius_abs; + nbits_diff_radius = 0; + *flag_abs_radius = 0; /* differential coding by default */ + + if ( *radius_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_radius = 1; + } + + diff = idx_radius_abs - *last_radius_idx; + + /* try differential coding */ + if ( *flag_abs_radius == 0 ) + { + if ( diff == 0 ) + { + idx_radius = 0; + nbits_diff_radius = 1; + } + else if ( ABSVAL( diff ) <= ISM_MAX_RADIUS_DIFF_IDX ) + { + idx_radius = 1 << 1; + nbits_diff_radius = 1; + + if ( diff < 0 ) + { + idx_radius += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_radius += 0; /* positive sign */ + } + + idx_radius = idx_radius << diff; + nbits_diff_radius++; + + /* unary coding of "diff */ + idx_radius += ( ( 1 << diff ) - 1 ); + nbits_diff_radius += diff; + + if ( nbits_diff_radius < ISM_RADIUS_NBITS ) + { + /* add stop bit */ + idx_radius = idx_radius << 1; + nbits_diff_radius++; + } + } + else + { + *flag_abs_radius = 1; + } + } + + /* update counter */ + if ( *flag_abs_radius == 0 ) + { + ( *radius_diff_cnt )++; + *radius_diff_cnt = min( *radius_diff_cnt, ISM_FEC_MAX ); + } + else + { + *radius_diff_cnt = 0; + } + + /* Write radius */ + push_indice( hBstr, IND_ISM_RADIUS_DIFF_FLAG, *flag_abs_radius, 1 ); + + if ( *flag_abs_radius ) + { + push_indice( hBstr, IND_ISM_RADIUS, idx_radius, ISM_RADIUS_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_RADIUS, idx_radius, nbits_diff_radius ); + } + + /* Updates */ + *last_radius_idx = idx_radius_abs; + + return; +} + + +/*----------------------------------------------------------------* + * encode_angle_indices() + * + * Encoding of an angle + *----------------------------------------------------------------*/ +#ifdef FIX_379_ANGLE +static void encode_angle_indices( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + ISM_METADATA_ANGLE_HANDLE angle, /* i/o: angle handle */ + const int16_t last_ism_metadata_flag, /* i : last frame ism_metadata_flag */ + const int16_t ini_frame, /* i : initialization frames counter */ + const int16_t idx_angle1_abs, /* i : Azimuth index */ + const int16_t idx_angle2_abs, /* i : Elevation index */ + int16_t *flag_abs_angle1, /* o : Azimuth/yaw encoding mode */ + int16_t *flag_abs_angle2 /* o : Elevation/pitch encoding mode */ +) +{ + int16_t idx_angle1, nbits_diff_angle1, diff; + int16_t idx_angle2, nbits_diff_angle2; + + /*----------------------------------------------------------------* + * Azimuth/yaw index encoding + *----------------------------------------------------------------*/ + + idx_angle1 = idx_angle1_abs; + + nbits_diff_angle1 = 0; + + *flag_abs_angle1 = 0; /* differential coding by default */ + if ( angle->angle1_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_angle1 = 1; + } + + /* try differential coding */ + if ( *flag_abs_angle1 == 0 ) + { + diff = idx_angle1_abs - angle->last_angle1_idx; + + /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ + if ( abs( diff ) > ( ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - ISM_MAX_AZIMUTH_DIFF_IDX ) + { + if ( diff > 0 ) + { + diff -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; + } + else + { + diff += ( 1 << ISM_AZIMUTH_NBITS ) - 1; + } + } + + if ( diff == 0 ) + { + idx_angle1 = 0; + nbits_diff_angle1 = 1; + } + else if ( ABSVAL( diff ) < ISM_MAX_AZIMUTH_DIFF_IDX ) /* when diff bits >= abs bits, prefer abs */ + { + idx_angle1 = 1 << 1; + nbits_diff_angle1 = 1; + + if ( diff < 0 ) + { + idx_angle1 += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_angle1 += 0; /* positive sign */ + } + + idx_angle1 = idx_angle1 << diff; + nbits_diff_angle1++; + + /* unary coding of "diff */ + idx_angle1 += ( ( 1 << diff ) - 1 ); + nbits_diff_angle1 += diff; + + if ( nbits_diff_angle1 < ISM_AZIMUTH_NBITS - 1 ) + { + /* add stop bit - only for codewords shorter than ISM_AZIMUTH_NBITS */ + idx_angle1 = idx_angle1 << 1; + nbits_diff_angle1++; + } + } + else + { + *flag_abs_angle1 = 1; + } + } + + /* update counter */ + if ( *flag_abs_angle1 == 0 ) + { + angle->angle1_diff_cnt++; + angle->angle2_diff_cnt = min( angle->angle2_diff_cnt, ISM_FEC_MAX ); + } + else + { + angle->angle1_diff_cnt = 0; + } + + /* Write azimuth/yaw */ + push_indice( hBstr, IND_ISM_AZIMUTH_DIFF_FLAG, *flag_abs_angle1, 1 ); + + if ( *flag_abs_angle1 ) + { + push_indice( hBstr, IND_ISM_AZIMUTH, idx_angle1, ISM_AZIMUTH_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_AZIMUTH, idx_angle1, nbits_diff_angle1 ); + } + + /*----------------------------------------------------------------* + * Elevation/pitch index encoding + *----------------------------------------------------------------*/ + + idx_angle2 = idx_angle2_abs; + nbits_diff_angle2 = 0; + *flag_abs_angle2 = 0; /* differential coding by default */ + if ( angle->angle2_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_angle2 = 1; + } + + /* note: elevation/pitch is coded starting from the second frame only (it is meaningless in the init_frame) */ + if ( ini_frame == 0 ) + { + *flag_abs_angle2 = 1; + angle->last_angle2_idx = idx_angle2_abs; + } + + diff = idx_angle2_abs - angle->last_angle2_idx; + + /* avoid absolute coding of elevation/pitch if absolute coding was already used for azimuth/yaw */ + if ( *flag_abs_angle1 == 1 ) + { + int16_t diff_orig = diff; + + *flag_abs_angle2 = 0; + + + if ( diff >= 0 ) + { + diff = min( diff, ISM_MAX_ELEVATION_DIFF_IDX ); + } + else + { + diff = -1 * min( -diff, ISM_MAX_ELEVATION_DIFF_IDX ); + } + + if ( last_ism_metadata_flag == 0 || abs( diff_orig - diff ) > ISM_MAX_ELEVATION_DIFF_IDX ) + { + angle->angle2_diff_cnt = ISM_FEC_MAX - 1; + } + } + + /* try differential coding */ + if ( *flag_abs_angle2 == 0 ) + { + if ( diff == 0 ) + { + idx_angle2 = 0; + nbits_diff_angle2 = 1; + } + else if ( ABSVAL( diff ) <= ISM_MAX_ELEVATION_DIFF_IDX ) + { + idx_angle2 = 1 << 1; + nbits_diff_angle2 = 1; + + if ( diff < 0 ) + { + idx_angle2 += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_angle2 += 0; /* positive sign */ + } + + idx_angle2 = idx_angle2 << diff; + nbits_diff_angle2++; + + /* unary coding of "diff */ + idx_angle2 += ( ( 1 << diff ) - 1 ); + nbits_diff_angle2 += diff; + + if ( nbits_diff_angle2 < ISM_ELEVATION_NBITS ) + { + /* add stop bit */ + idx_angle2 = idx_angle2 << 1; + nbits_diff_angle2++; + } + } + else + { + *flag_abs_angle2 = 1; + } + } + + /* update counter */ + if ( *flag_abs_angle2 == 0 ) + { + angle->angle2_diff_cnt++; + angle->angle2_diff_cnt = min( angle->angle2_diff_cnt, ISM_FEC_MAX ); + } + else + { + angle->angle2_diff_cnt = 0; + } + + /* Write elevation */ + if ( *flag_abs_angle1 == 0 ) /* do not write "flag_abs_elevation/pitch" if "flag_abs_azimuth/yaw == 1" */ + { + push_indice( hBstr, IND_ISM_ELEVATION_DIFF_FLAG, *flag_abs_angle2, 1 ); + } + + if ( *flag_abs_angle2 ) + { + push_indice( hBstr, IND_ISM_ELEVATION, idx_angle2, ISM_ELEVATION_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_ELEVATION, idx_angle2, nbits_diff_angle2 ); + } + + /*----------------------------------------------------------------* + * Updates + *----------------------------------------------------------------*/ + + angle->last_angle1_idx = idx_angle1_abs; + angle->last_angle2_idx = idx_angle2_abs; + + return; +} + +#else + +static void encode_angle_indices( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + ISM_METADATA_ANGLE_HANDLE angle, /* i/o: angle handle */ + const int16_t last_ism_metadata_flag, /* i : last frame ism_metadata_flag */ + const int16_t ini_frame, /* i : initialization frames counter */ + const int16_t idx_azimuth_abs, /* i : Azimuth index */ + const int16_t idx_elevation_abs, /* i : Elevation index */ + int16_t *flag_abs_azimuth, /* o : Azimuth encoding mode */ + int16_t *flag_abs_elevation /* o : Elevation encoding mode */ +) +{ + int16_t idx_azimuth, nbits_diff_azimuth, diff; + int16_t idx_elevation, nbits_diff_elevation; + + /*----------------------------------------------------------------* + * Azimuth index encoding + *----------------------------------------------------------------*/ + + idx_azimuth = idx_azimuth_abs; + + nbits_diff_azimuth = 0; + + *flag_abs_azimuth = 0; /* differential coding by default */ + if ( angle->azimuth_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_azimuth = 1; + } + + /* try differential coding */ + if ( *flag_abs_azimuth == 0 ) + { + diff = idx_azimuth_abs - angle->last_azimuth_idx; + + /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */ + if ( abs( diff ) > ( ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - ISM_MAX_AZIMUTH_DIFF_IDX ) + { + if ( diff > 0 ) + { + diff -= ( 1 << ISM_AZIMUTH_NBITS ) - 1; + } + else + { + diff += ( 1 << ISM_AZIMUTH_NBITS ) - 1; + } + } + + if ( diff == 0 ) + { + idx_azimuth = 0; + nbits_diff_azimuth = 1; + } + else if ( ABSVAL( diff ) < ISM_MAX_AZIMUTH_DIFF_IDX ) /* when diff bits >= abs bits, prefer abs */ + { + idx_azimuth = 1 << 1; + nbits_diff_azimuth = 1; + + if ( diff < 0 ) + { + idx_azimuth += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_azimuth += 0; /* positive sign */ + } + + idx_azimuth = idx_azimuth << diff; + nbits_diff_azimuth++; + + /* unary coding of "diff */ + idx_azimuth += ( ( 1 << diff ) - 1 ); + nbits_diff_azimuth += diff; + + if ( nbits_diff_azimuth < ISM_AZIMUTH_NBITS - 1 ) + { + /* add stop bit - only for codewords shorter than ISM_AZIMUTH_NBITS */ + idx_azimuth = idx_azimuth << 1; + nbits_diff_azimuth++; + } + } + else + { + *flag_abs_azimuth = 1; + } + } + + /* update counter */ + if ( *flag_abs_azimuth == 0 ) + { + angle->azimuth_diff_cnt++; + angle->elevation_diff_cnt = min( angle->elevation_diff_cnt, ISM_FEC_MAX ); + } + else + { + angle->azimuth_diff_cnt = 0; + } + + /* Write azimuth */ + push_indice( hBstr, IND_ISM_AZIMUTH_DIFF_FLAG, *flag_abs_azimuth, 1 ); + + if ( *flag_abs_azimuth ) + { + push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, ISM_AZIMUTH_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, nbits_diff_azimuth ); + } + + /*----------------------------------------------------------------* + * Elevation index encoding + *----------------------------------------------------------------*/ + + idx_elevation = idx_elevation_abs; + nbits_diff_elevation = 0; + *flag_abs_elevation = 0; /* differential coding by default */ + if ( angle->elevation_diff_cnt == ISM_FEC_MAX /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */ + || last_ism_metadata_flag == 0 /* If last frame had no metadata coded, do not use differential coding */ + ) + { + *flag_abs_elevation = 1; + } + + /* note: elevation is coded starting from the second frame only (it is meaningless in the init_frame) */ + if ( ini_frame == 0 ) + { + *flag_abs_elevation = 1; + angle->last_elevation_idx = idx_elevation_abs; + } + + diff = idx_elevation_abs - angle->last_elevation_idx; + + /* avoid absolute coding of elevation if absolute coding was already used for azimuth */ + if ( *flag_abs_azimuth == 1 ) + { + int16_t diff_orig = diff; + + *flag_abs_elevation = 0; + + + if ( diff >= 0 ) + { + diff = min( diff, ISM_MAX_ELEVATION_DIFF_IDX ); + } + else + { + diff = -1 * min( -diff, ISM_MAX_ELEVATION_DIFF_IDX ); + } + + if ( last_ism_metadata_flag == 0 || abs( diff_orig - diff ) > ISM_MAX_ELEVATION_DIFF_IDX ) + { + angle->elevation_diff_cnt = ISM_FEC_MAX - 1; + } + } + + /* try differential coding */ + if ( *flag_abs_elevation == 0 ) + { + if ( diff == 0 ) + { + idx_elevation = 0; + nbits_diff_elevation = 1; + } + else if ( ABSVAL( diff ) <= ISM_MAX_ELEVATION_DIFF_IDX ) + { + idx_elevation = 1 << 1; + nbits_diff_elevation = 1; + + if ( diff < 0 ) + { + idx_elevation += 1; /* negative sign */ + diff *= -1; + } + else + { + idx_elevation += 0; /* positive sign */ + } + + idx_elevation = idx_elevation << diff; + nbits_diff_elevation++; + + /* unary coding of "diff */ + idx_elevation += ( ( 1 << diff ) - 1 ); + nbits_diff_elevation += diff; + + if ( nbits_diff_elevation < ISM_ELEVATION_NBITS ) + { + /* add stop bit */ + idx_elevation = idx_elevation << 1; + nbits_diff_elevation++; + } + } + else + { + *flag_abs_elevation = 1; + } + } + + /* update counter */ + if ( *flag_abs_elevation == 0 ) + { + angle->elevation_diff_cnt++; + angle->elevation_diff_cnt = min( angle->elevation_diff_cnt, ISM_FEC_MAX ); + } + else + { + angle->elevation_diff_cnt = 0; + } + + /* Write elevation */ + if ( *flag_abs_azimuth == 0 ) /* do not write "flag_abs_elevation" if "flag_abs_azimuth == 1" */ + { + push_indice( hBstr, IND_ISM_ELEVATION_DIFF_FLAG, *flag_abs_elevation, 1 ); + } + + if ( *flag_abs_elevation ) + { + push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, ISM_ELEVATION_NBITS ); + } + else + { + push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, nbits_diff_elevation ); + } + + /*----------------------------------------------------------------* + * Updates + *----------------------------------------------------------------*/ + + angle->last_azimuth_idx = idx_azimuth_abs; + angle->last_elevation_idx = idx_elevation_abs; + + return; +} +#endif + +#ifdef DISCRETE_ISM_DTX_CNG +/*-------------------------------------------------------------------* + * ivas_ism_metadata_sid_enc() + * + * Quantize and encode ISM metadata in SID frame + *-------------------------------------------------------------------*/ + +void ivas_ism_metadata_sid_enc( + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + const int16_t flag_noisy_speech, /* i : noisy speech flag */ + const int16_t nchan_ism, /* i : number of objects */ + const int16_t nchan_transport, /* i : number of transport channels */ + const ISM_MODE ism_mode, /* i : ISM mode */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ + const int16_t sid_flag, /* i : indication of SID frame */ + const int16_t md_diff_flag[], /* i : metadata differental flag */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + int16_t nb_bits_metadata[] /* o : number of metadata bits */ +) +{ + int16_t i, ch, nBits, nBits_start, nBits_unused; + float q_step, q_step_border; + int16_t idx, idx_azimuth, idx_elevation; + int16_t nBits_azimuth, nBits_elevation, nBits_coh, nBits_sce_id; + float valQ; + ISM_METADATA_HANDLE hIsmMetaData; + + if ( sid_flag ) + { + nBits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; + nBits -= SID_FORMAT_NBITS; + nBits_start = hBstr->nb_bits_tot; + + /*----------------------------------------------------------------* + * Write ISm common signaling + *----------------------------------------------------------------*/ + + /* write number of objects - unary coding */ + for ( ch = 1; ch < nchan_ism; ch++ ) + { + push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 ); + } + push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 ); + + /* write SID metadata flag (one per object) */ + for ( ch = 0; ch < nchan_ism; ch++ ) + { + push_indice( hBstr, IND_ISM_METADATA_FLAG, md_diff_flag[ch], 1 ); + } + + /*----------------------------------------------------------------* + * Set quantization bits based on the number of coded objects + *----------------------------------------------------------------*/ + + ivas_get_ism_sid_quan_bitbudget( nchan_ism, &nBits_azimuth, &nBits_elevation, &q_step, &q_step_border, &nBits_coh, &nBits_sce_id ); + + /*----------------------------------------------------------------* + * Spatial parameters, loop over TCs - 1 + *----------------------------------------------------------------*/ + + /* write ISM mode flag to explicitly signal number of spatial parameters */ + if ( nchan_ism > 2 ) + { + if ( ism_mode == ISM_MODE_DISC ) + { + push_indice( hBstr, IND_ISM_VAD_FLAG, 0, 1 ); + } + else + { + push_indice( hBstr, IND_ISM_VAD_FLAG, 1, 1 ); + } + + if ( ism_mode == ISM_MODE_PARAM ) + { + /* write noisy speech flag */ + push_indice( hBstr, IND_ISM_NOISY_SPEECH_FLAG, flag_noisy_speech, 1 ); + nBits_sce_id = 1; + } + } + + if ( nchan_transport > 1 ) + { + /* write sce id */ + push_indice( hBstr, IND_ISM_SCE_ID_DTX, hISMDTX->sce_id_dtx, nBits_sce_id ); + + /* quantize and write coherence */ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + if ( ch == hISMDTX->sce_id_dtx ) + { + continue; + } + + idx = (int16_t) ( hISMDTX->coh[ch] * ( ( 1 << nBits_coh ) - 1 ) + 0.5f ); + assert( ( idx >= 0 ) && ( idx <= ( ( 1 << nBits_coh ) - 1 ) ) ); + push_indice( hBstr, IND_ISM_DTX_COH_SCA, idx, nBits_coh ); + } + } + + /*----------------------------------------------------------------* + * Metadata quantization and coding, loop over all objects + *----------------------------------------------------------------*/ + + for ( ch = 0; ch < nchan_ism; ch++ ) + { + if ( md_diff_flag[ch] == 1 ) + { + hIsmMetaData = hIsmMeta[ch]; + + idx_azimuth = ism_quant_meta( hIsmMetaData->azimuth, &valQ, ism_azimuth_borders, q_step, q_step_border, 1 << nBits_azimuth ); + idx_elevation = ism_quant_meta( hIsmMetaData->elevation, &valQ, ism_elevation_borders, q_step, q_step_border, 1 << nBits_elevation ); + + push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, nBits_azimuth ); + push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, nBits_elevation ); + + /* update last indexes to correspond to active frames coding */ + if ( nBits_azimuth > ISM_AZIMUTH_NBITS ) + { +#ifdef FIX_379_ANGLE + hIsmMetaData->position_angle.last_angle1_idx = idx_azimuth >> ( nBits_azimuth - ISM_AZIMUTH_NBITS ); + hIsmMetaData->position_angle.last_angle2_idx = idx_elevation >> ( nBits_elevation - ISM_ELEVATION_NBITS ); + +#else + hIsmMetaData->angle[0].last_azimuth_idx = idx_azimuth >> ( nBits_azimuth - ISM_AZIMUTH_NBITS ); + hIsmMetaData->angle[0].last_elevation_idx = idx_elevation >> ( nBits_elevation - ISM_ELEVATION_NBITS ); +#endif + } + else + { +#ifdef FIX_379_ANGLE + hIsmMetaData->position_angle.last_angle1_idx = idx_azimuth << ( ISM_AZIMUTH_NBITS - nBits_azimuth ); + hIsmMetaData->position_angle.last_angle2_idx = idx_elevation << ( ISM_ELEVATION_NBITS - nBits_elevation ); +#else + hIsmMetaData->angle[0].last_azimuth_idx = idx_azimuth << ( ISM_AZIMUTH_NBITS - nBits_azimuth ); + hIsmMetaData->angle[0].last_elevation_idx = idx_elevation << ( ISM_ELEVATION_NBITS - nBits_elevation ); +#endif + } + } + } + + /* Write unused (padding) bits */ + nBits_unused = nBits - hBstr->nb_bits_tot; + while ( nBits_unused > 0 ) + { + i = min( nBits_unused, 16 ); + push_indice( hBstr, IND_UNUSED, 0, i ); + nBits_unused -= i; + } + + nb_bits_metadata[0] = hBstr->nb_bits_tot - nBits_start; + } + + return; +} +#endif diff --git a/lib_enc/ivas_ism_param_enc.c b/lib_enc/ivas_ism_param_enc.c index e515f7e204a4311457456a4b1bf68bb0ceaaf567..63c1fcea810af6c5d04f93a96e162cd5c0d94c7b 100644 --- a/lib_enc/ivas_ism_param_enc.c +++ b/lib_enc/ivas_ism_param_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,8 +39,7 @@ #include "cnst.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" -#include "wmops.h" - +#include "wmc_auto.h" /*------------------------------------------------------------------------- * Local function definitions @@ -48,16 +47,27 @@ static void ivas_param_ism_compute_obj_parameters( +#ifdef NCHAN_ISM_PARAMETER + const int16_t nchan_ism, /* i : number of ISM channels */ +#endif float reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX], /* i : Reference power */ PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: Param ISM Enc Handle */ ) { +#ifdef NCHAN_ISM_PARAMETER + int16_t i, b, m, br, mr; +#else int16_t i, b, m, br, mr, num_obj; +#endif int16_t brange_start, brange_end, mrange_start, mrange_end, time_merge_fac; float power_ratios_m[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS]; +#ifdef NCHAN_ISM_PARAMETER + assert( nchan_ism == 3 || nchan_ism == 4 ); +#else num_obj = hParamIsm->num_obj; assert( num_obj == 3 || num_obj == 4 ); +#endif for ( b = 0; b < hParamIsm->nbands; b++ ) { @@ -82,7 +92,11 @@ static void ivas_param_ism_compute_obj_parameters( /* for each object, sum up reference power within current T/F tile */ +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_ism; i++ ) +#else for ( i = 0; i < num_obj; i++ ) +#endif { for ( mr = mrange_start; mr < mrange_end; mr++ ) { @@ -104,7 +118,12 @@ static void ivas_param_ism_compute_obj_parameters( index_1 = 1; index_2 = 0; } - for ( i = 2; i < num_obj; i++ ) + +#ifdef NCHAN_ISM_PARAMETER + for ( i = MAX_PARAM_ISM_WAVE; i < nchan_ism; i++ ) +#else + for ( i = MAX_PARAM_ISM_WAVE; i < num_obj; i++ ) +#endif { if ( ref_power_local[i] > ref_power_local[index_1] ) { @@ -150,23 +169,36 @@ static void ivas_param_ism_compute_obj_parameters( static void ivas_param_ism_enc_quantize_DOA( +#ifdef NCHAN_ISM_PARAMETER + const int16_t nchan_ism, /* i : number of ISM channels */ +#endif ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i : ISM metadata */ PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: Param ISM encoder handle */ ) { +#ifdef NCHAN_ISM_PARAMETER + int16_t i, azi_idx, ele_idx; +#else int16_t i, azi_idx, ele_idx, num_obj; +#endif float valQ; +#ifndef NCHAN_ISM_PARAMETER num_obj = hParamIsm->num_obj; +#endif /* Loop over objects */ +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_ism; i++ ) +#else for ( i = 0; i < num_obj; i++ ) +#endif { /* Quantize the elevation and obtain quantized elevation value and index */ - ele_idx = ism_quant_meta( hIsmMetaData[i]->elevation, &valQ, ism_elevation_borders, 1 << ISM_ELEVATION_NBITS ); + ele_idx = ism_quant_meta( hIsmMetaData[i]->elevation, &valQ, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); /* Obtain the index of quantized azimuth values */ - azi_idx = ism_quant_meta( hIsmMetaData[i]->azimuth, &valQ, ism_azimuth_borders, 1 << ISM_AZIMUTH_NBITS ); + azi_idx = ism_quant_meta( hIsmMetaData[i]->azimuth, &valQ, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); /*Replace azimuth with quantized values */ hIsmMetaData[i]->azimuth = valQ; @@ -192,25 +224,35 @@ void ivas_param_ism_stereo_dmx( const int16_t input_frame /* i : Length of input frame */ ) { +#ifdef NCHAN_ISM_PARAMETER + int16_t i, j; +#else int16_t i, j, num_obj; +#endif float alpha, azi_shift, tmp, tmp_1; float cardioid_left[MAX_NUM_OBJECTS], cardioid_right[MAX_NUM_OBJECTS]; float stereo_dmx[2][L_FRAME48k]; ISM_METADATA_HANDLE hIsmMetaData; - wmops_sub_start( "ivas_param_ism_st_dmx" ); + push_wmops( "ivas_param_ism_st_dmx" ); /*Initialization*/ alpha = 0.5; azi_shift = 0; +#ifndef NCHAN_ISM_PARAMETER num_obj = st_ivas->hDirAC->hParamIsm->num_obj; +#endif /* Set the stereo dmx to zero */ set_zero( stereo_dmx[0], L_FRAME48k ); set_zero( stereo_dmx[1], L_FRAME48k ); /* Loop over all objects */ +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) +#else for ( i = 0; i < num_obj; i++ ) +#endif { hIsmMetaData = st_ivas->hIsmMetaData[i]; @@ -233,7 +275,7 @@ void ivas_param_ism_stereo_dmx( mvr2r( stereo_dmx[0], data[0], input_frame ); mvr2r( stereo_dmx[1], data[1], input_frame ); - wmops_sub_end(); + pop_wmops(); return; } @@ -259,21 +301,23 @@ ivas_error ivas_param_ism_enc_open( error = IVAS_ERR_OK; /* Assign memory to DirAC handle */ - if ( ( hDirAC = (DIRAC_ENC_HANDLE) count_malloc( sizeof( DIRAC_ENC_DATA ) ) ) == NULL ) + if ( ( hDirAC = (DIRAC_ENC_HANDLE) malloc( sizeof( DIRAC_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); } /* Assign memory to Param Object handle */ - if ( ( hDirAC->hParamIsm = (PARAM_ISM_CONFIG_HANDLE) count_malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL ) + if ( ( hDirAC->hParamIsm = (PARAM_ISM_CONFIG_HANDLE) malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM\n" ) ); } input_Fs = st_ivas->hEncoderConfig->input_Fs; +#ifndef NCHAN_ISM_PARAMETER /* Assign the number of objects */ hDirAC->hParamIsm->num_obj = st_ivas->hEncoderConfig->nchan_inp; +#endif /* set FB config. */ if ( ( error = ivas_fb_set_cfg( &fb_cfg, ISM_FORMAT, SBA_MODE_NONE, st_ivas->hEncoderConfig->nchan_inp, 0, 0, input_Fs ) ) != IVAS_ERR_OK ) @@ -282,14 +326,16 @@ ivas_error ivas_param_ism_enc_open( } /* Allocate and initialize FB mixer handle */ - if ( ( error = ivas_FB_mixer_open( &( hDirAC->hFbMixer ), input_Fs, fb_cfg ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_FB_mixer_open( &( hDirAC->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) { return error; } - +#ifdef NCHAN_ISM_PARAMETER + ivas_param_ism_config( hDirAC->hParamIsm, st_ivas->hEncoderConfig->nchan_inp ); +#else ivas_param_ism_config( hDirAC->hParamIsm ); - +#endif /* Assign memories for Band and Block grouping */ hDirAC->hParamIsm->nbands = MAX_PARAM_ISM_NBANDS; @@ -315,23 +361,29 @@ ivas_error ivas_param_ism_enc_open( /*-------------------------------------------------------------------------* * ivas_param_ism_enc_close() * - * Close Param ISM handle + * Close Param ISM encoder handle *-------------------------------------------------------------------------*/ void ivas_param_ism_enc_close( - DIRAC_ENC_HANDLE hDirAC, /* i/o: encoder DirAC handle */ - const int32_t input_Fs /* i : input sampling_rate */ + DIRAC_ENC_HANDLE *hDirAC, /* i/o: encoder DirAC handle */ + const int32_t input_Fs /* i : input sampling_rate */ ) { - ivas_FB_mixer_close( &hDirAC->hFbMixer, input_Fs ); + if ( hDirAC == NULL || *hDirAC == NULL ) + { + return; + } - if ( hDirAC->hParamIsm != NULL ) + ivas_FB_mixer_close( &( *hDirAC )->hFbMixer, input_Fs, 0 ); + + if ( ( *hDirAC )->hParamIsm != NULL ) { - count_free( hDirAC->hParamIsm ); - hDirAC->hParamIsm = NULL; + free( ( *hDirAC )->hParamIsm ); + ( *hDirAC )->hParamIsm = NULL; } - count_free( hDirAC ); + free( ( *hDirAC ) ); + ( *hDirAC ) = NULL; return; } @@ -350,6 +402,9 @@ void ivas_param_ism_enc( ) { int16_t i, j, ts, l_ts; +#ifdef NCHAN_ISM_PARAMETER + int16_t nchan_ism; +#endif int16_t num_time_slots; float *pcm_in[MAX_NUM_OBJECTS]; float fb_RealBuffer[MAX_NUM_OBJECTS][DIRAC_NO_FB_BANDS_MAX]; @@ -360,15 +415,22 @@ void ivas_param_ism_enc( DIRAC_ENC_HANDLE hDirAC; PARAM_ISM_CONFIG_HANDLE hParamIsm; +#ifdef NCHAN_ISM_PARAMETER + nchan_ism = st_ivas->hEncoderConfig->nchan_ism; +#endif hDirAC = st_ivas->hDirAC; hParamIsm = hDirAC->hParamIsm; - wmops_sub_start( "ivas_param_ism_enc" ); + push_wmops( "ivas_param_ism_enc" ); l_ts = input_frame / PARAM_ISM_MDFT_NO_SLOTS; num_time_slots = PARAM_ISM_MDFT_NO_SLOTS; +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_ism; i++ ) +#else for ( i = 0; i < hParamIsm->num_obj; i++ ) +#endif { pcm_in[i] = &data[i][0]; @@ -377,12 +439,18 @@ void ivas_param_ism_enc( p_fb_RealBuffer[i] = &fb_RealBuffer[i][0]; p_fb_ImagBuffer[i] = &fb_ImagBuffer[i][0]; } + for ( ts = 0; ts < num_time_slots; ts++ ) { ivas_fb_mixer_get_windowed_fr( hDirAC->hFbMixer, pcm_in, p_fb_RealBuffer, p_fb_ImagBuffer, l_ts, l_ts ); + ivas_fb_mixer_update_prior_input( hDirAC->hFbMixer, pcm_in, l_ts ); +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_ism; i++ ) +#else for ( i = 0; i < hParamIsm->num_obj; i++ ) +#endif { pcm_in[i] += l_ts; for ( j = 0; j < DIRAC_NO_FB_BANDS_MAX; j++ ) @@ -391,44 +459,208 @@ void ivas_param_ism_enc( } } } + /* Quantize DOAs */ +#ifdef NCHAN_ISM_PARAMETER + ivas_param_ism_enc_quantize_DOA( nchan_ism, st_ivas->hIsmMetaData, hParamIsm ); +#else ivas_param_ism_enc_quantize_DOA( st_ivas->hIsmMetaData, hParamIsm ); +#endif /* Compute object indices and power ratios */ +#ifdef NCHAN_ISM_PARAMETER + ivas_param_ism_compute_obj_parameters( nchan_ism, reference_power_obj, hParamIsm ); +#else ivas_param_ism_compute_obj_parameters( reference_power_obj, hParamIsm ); +#endif + + pop_wmops(); + return; +} + + +#ifndef DISCRETE_ISM_DTX_CNG +static void ivas_param_ism_enc_quantize_DOA_dtx( + float azimuth, + float elevation, + int16_t azi_bits, + int16_t ele_bits, + int16_t *azi_idx, + int16_t *ele_idx ) +{ + int16_t nbits, npoints, angle_spacing, az_alpha, ele_alpha; + float azi_val; + + /* Step 1: Determine angle spacing/n_points based on minimum value among elevation/azimuth bits */ + nbits = min( azi_bits, ele_bits ); + + if ( nbits == ISM_ELEVATION_NBITS ) + { + angle_spacing = 5; + } + else + { + angle_spacing = (int16_t) ( ( 180.f / (float) ( 1 << nbits ) ) + 0.5f ); + } + + npoints = (int16_t) ( ( 90 / angle_spacing ) + 0.5f ); + + /* Step 2: Quantize Elevation */ + ele_alpha = 2 * npoints - 1; + *ele_idx = (int16_t) ( ( elevation / angle_spacing ) + 0.5f ) + npoints; + if ( *ele_idx >= ele_alpha ) + { + *ele_idx = ele_alpha - 1; + } + assert( ( 0 <= *ele_idx ) && ( *ele_idx < ele_alpha ) ); + + /* Step 3: Quantize Azimuth */ + az_alpha = 4 * npoints - 1; + + /* Convert azimuth in {-180,180} into {0,360} before quantization */ + if ( azimuth >= 0 ) + { + azi_val = azimuth; + } + else + { + azi_val = azimuth + 360.f; + } + + /* Obtain the index of quantized azimuth values */ + *azi_idx = (int16_t) ( ( ( azi_val / 360.f ) * az_alpha ) + 0.5f ); + if ( *azi_idx == az_alpha ) + { + /*wrap around the azimuth angle*/ + *azi_idx = 0; + } + assert( ( 0 <= *azi_idx ) && ( *azi_idx < az_alpha ) ); - wmops_sub_end(); return; } + /*------------------------------------------------------------------------- - * ivas_ism_enc_config() + * ivas_param_ism_metadata_dtx_enc() * - * - select ISM format mode - * - reconfigure the ISM format encoder *-------------------------------------------------------------------------*/ -/*! r : ISM format mode */ -ivas_error ivas_ism_enc_config( - Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +void ivas_param_ism_metadata_dtx_enc( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i : ISM metadata handles */ + ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ + PARAM_ISM_CONFIG_HANDLE hParamIsm /* i : Param ISM Enc Handle */ +#ifdef NCHAN_ISM_PARAMETER + , + const int16_t nchan_ism /* i : number of ISM channels */ +#endif ) { - ivas_error error; - ISM_MODE last_ism_mode; + int16_t i, nBits, nBits_unused; + int16_t azi_idx, ele_idx; + int16_t coh_idx; + + nBits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC; + nBits -= SID_FORMAT_NBITS; + + /* Transmit the metadata */ + /* write number of objects - unary coding */ +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_ism; i++ ) +#else + for ( i = 1; i < hParamIsm->num_obj; i++ ) +#endif + { + push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 ); + } + push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 ); - error = IVAS_ERR_OK; + /* write sce id */ + push_indice( hBstr, IND_ISM_SCE_ID_DTX, hISMDTX->sce_id_dtx, 1 ); + + /* write noisy speech flag */ + push_indice( hBstr, IND_ISM_NOISY_SPEECH_FLAG, hParamIsm->flag_noisy_speech, 1 ); + + /* quantize and write coherence */ + coh_idx = (int16_t) ( hISMDTX->coh[0] * ( ( 1 << PARAM_ISM_DTX_COH_SCA_BITS ) - 1 ) + 0.5f ); + assert( ( coh_idx >= 0 ) && ( coh_idx <= ( ( 1 << PARAM_ISM_DTX_COH_SCA_BITS ) - 1 ) ) ); + push_indice( hBstr, IND_ISM_DTX_COH_SCA, coh_idx, PARAM_ISM_DTX_COH_SCA_BITS ); - last_ism_mode = st_ivas->ism_mode; +#ifdef NCHAN_ISM_PARAMETER + for ( i = 0; i < nchan_ism; i++ ) +#else + for ( i = 0; i < hParamIsm->num_obj; i++ ) +#endif + { + ivas_param_ism_enc_quantize_DOA_dtx( hIsmMeta[i]->azimuth, hIsmMeta[i]->elevation, PARAM_ISM_DTX_AZI_BITS, PARAM_ISM_DTX_ELE_BITS, &azi_idx, &ele_idx ); + push_indice( hBstr, IND_ISM_AZIMUTH, azi_idx, PARAM_ISM_DTX_AZI_BITS ); + push_indice( hBstr, IND_ISM_ELEVATION, ele_idx, PARAM_ISM_DTX_ELE_BITS ); + } - /* select ISM format mode */ - st_ivas->ism_mode = ivas_ism_mode_select( st_ivas->hEncoderConfig->nchan_inp, st_ivas->hEncoderConfig->ivas_total_brate ); +#ifdef DEBUG_MODE_PARAM_ISM + dbgwrite( &( hParamIsm->coh ), sizeof( float ), 1, 1, "./res/ParamISM_coh_enc.dat" ); +#endif - /* ISM format switching */ - if ( st_ivas->ism_mode != last_ism_mode ) + /* Write unused (padding) bits */ + nBits_unused = nBits - hBstr->nb_bits_tot; + while ( nBits_unused > 0 ) { - /*ivas_ism_dec_reconfigure( st_ivas );*/ - return IVAS_ERROR( IVAS_ERR_RECONFIGURE_NOT_SUPPORTED, "Error: ISM format switching not supported yet!!!\n\n" ); + i = min( nBits_unused, 16 ); + push_indice( hBstr, IND_UNUSED, 0, i ); + nBits_unused -= i; } - return error; +#ifdef DEBUGGING + assert( hBstr->nb_bits_tot == nBits ); +#endif + + return; +} +#endif + +/*-------------------------------------------------------------------* + * ivas_param_ism_compute_noisy_speech_flag() + * + * + *-------------------------------------------------------------------*/ + +void ivas_param_ism_compute_noisy_speech_flag( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + int16_t i; + + /* Move the Noisy speech buffer */ + for ( i = 0; i < ( PARAM_ISM_HYS_BUF_SIZE - 1 ); i++ ) + { + st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i + 1]; + } + + /* For the current frame, make a decision based on some core-coder flags */ + if ( st_ivas->hSCE[0]->hCoreCoder[0]->flag_noisy_speech_snr && st_ivas->hSCE[1]->hCoreCoder[0]->flag_noisy_speech_snr ) + { + if ( st_ivas->hSCE[0]->hCoreCoder[0]->vad_flag && st_ivas->hSCE[1]->hCoreCoder[0]->vad_flag ) + { + st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = 0; + } + else + { + st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = 1; + } + } + else + { + + st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i] = 0; + } + + /* Do a decision based on hysterisis */ + st_ivas->hDirAC->hParamIsm->flag_noisy_speech = 1; + for ( i = 0; i < PARAM_ISM_HYS_BUF_SIZE; i++ ) + { + st_ivas->hDirAC->hParamIsm->flag_noisy_speech = st_ivas->hDirAC->hParamIsm->flag_noisy_speech && st_ivas->hDirAC->hParamIsm->noisy_speech_buffer[i]; + } + + + return; } diff --git a/lib_enc/ivas_lfe_enc.c b/lib_enc/ivas_lfe_enc.c index 6ad0e5bef255b6042032f3754660304ed6a4c976..a14424774ffec7ed5270d26f8d46926c9568e53e 100644 --- a/lib_enc/ivas_lfe_enc.c +++ b/lib_enc/ivas_lfe_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------------------------* @@ -105,6 +105,11 @@ static void ivas_lfe_enc_quant( int16_t values[IVAS_LFE_MAX_NUM_DCT_COEFFS << 1]; float temp_lfe_dct[IVAS_LFE_MAX_NUM_DCT_COEFFS]; int16_t target_bits; + int16_t base2_num_bits_tot; + int16_t coding_strategy; + int16_t bits_written_arith_enc; + int16_t next_ind_pos_arith_enc; + int16_t num_ele_per_grp = IVAS_LFE_NUM_COEFFS_IN_SUBGRP << 1; target_bits = (int16_t) ( IVAS_LFE_BITRATE_5000 / FRAMES_PER_SEC ); @@ -127,6 +132,7 @@ static void ivas_lfe_enc_quant( uint16_t all_zeros_dct; lfe_abs_sum = 0; + coding_strategy = 0; num_dct_pass_bins = ivas_lfe_num_dct_pass_bins_tbl[quant_strategy]; max_of_vals = 0; num_groups = num_dct_pass_bins >> 1; @@ -236,24 +242,70 @@ static void ivas_lfe_enc_quant( push_next_indice( hBstr, write_bit, 1 ); } + bits_written_arith_enc = hBstr->nb_bits_tot; + next_ind_pos_arith_enc = hBstr->next_ind; + push_next_indice( hBstr, coding_strategy, 1 ); + base2_num_bits_tot = hBstr->nb_bits_tot - bits_written; + ivas_lfe_arith_coding( hLFE, hBstr, quant_strategy, values ); - if ( ( target_bits + IVAS_LFE_ID_BITS ) >= ( hBstr->nb_bits_tot - bits_written ) ) + for ( i = 0; i < num_groups; i++ ) { - break; + int16_t base2_num_bits = hLFE->lfe_enc_indices_coeffs_tbl[quant_strategy][i]; + base2_num_bits_tot += ( num_ele_per_grp * base2_num_bits ); } - else + + if ( ( base2_num_bits_tot ) < ( hBstr->nb_bits_tot - bits_written ) ) { - if ( quant_strategy < ( num_quant_strategies - 1 ) ) + if ( quant_strategy == ( num_quant_strategies - 1 ) || ( ( target_bits + IVAS_LFE_ID_BITS ) >= base2_num_bits_tot ) ) { - /* reset all indices that were already written - TODO: maybe better store them temporarily first and write at the very end? */ - for ( j = hBstr->next_ind - 1; j >= next_ind_pos; j-- ) + /* reset bits buffer and code the indices with base 2 coding */ + for ( j = hBstr->next_ind - 1; j >= next_ind_pos_arith_enc; j-- ) { - hBstr->ind_list[j].nb_bits = 0; + hBstr->ind_list[j].nb_bits = -1; + } + hBstr->nb_bits_tot = bits_written_arith_enc; + hBstr->next_ind = next_ind_pos_arith_enc; + coding_strategy = 1; + push_next_indice( hBstr, coding_strategy, 1 ); + + for ( i = 0; i < num_groups; i++ ) + { + int16_t base2_write_bits = hLFE->lfe_enc_indices_coeffs_tbl[quant_strategy][i]; + int16_t offset = 4 * i; + max_value = ivas_lfe_num_ele_in_coder_models[quant_strategy][i]; + + for ( j = 0; j < num_ele_per_grp; j++ ) + { + if ( values[j + offset] > max_value ) + { + values[j + offset] = max_value; + } + push_next_indice( hBstr, values[j + offset], base2_write_bits ); + } } + break; + } + } + else + { + if ( ( target_bits + IVAS_LFE_ID_BITS ) >= ( hBstr->nb_bits_tot - bits_written ) ) + { + break; + } + else + { + if ( quant_strategy < ( num_quant_strategies - 1 ) ) + { + /* reset all indices that were already written - TODO: maybe better store them temporarily first and write at the very end? */ + for ( j = hBstr->next_ind - 1; j >= next_ind_pos; j-- ) + { + hBstr->ind_list[j].nb_bits = -1; + } - hBstr->nb_bits_tot = bits_written; - hBstr->next_ind = next_ind_pos; + hBstr->nb_bits_tot = bits_written; + hBstr->next_ind = next_ind_pos; + } } } } @@ -331,6 +383,7 @@ ivas_error ivas_create_lfe_enc( int16_t input_frame; LFE_ENC_HANDLE hLFE; const float *filt_coeff; + int16_t i, j; input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); @@ -338,7 +391,7 @@ ivas_error ivas_create_lfe_enc( * Allocate LFE handle *-----------------------------------------------------------------*/ - if ( ( hLFE = (LFE_ENC_HANDLE) count_malloc( sizeof( LFE_ENC_DATA ) ) ) == NULL ) + if ( ( hLFE = (LFE_ENC_HANDLE) malloc( sizeof( LFE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE\n" ) ); } @@ -353,18 +406,18 @@ ivas_error ivas_create_lfe_enc( * Input memory buffer: allocate and initialize *-----------------------------------------------------------------*/ - if ( ( hLFE->old_wtda_audio = (float *) count_malloc( sizeof( float ) * (int16_t) ( input_Fs * IVAS_LFE_FADE_LEN_SEC_FLOAT ) ) ) == NULL ) + if ( ( hLFE->old_wtda_audio = (float *) malloc( sizeof( float ) * NS2SA( input_Fs, IVAS_LFE_FADE_NS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE memory\n" ) ); } - set_zero( hLFE->old_wtda_audio, (int16_t) ( input_Fs * IVAS_LFE_FADE_LEN_SEC_FLOAT ) ); + set_zero( hLFE->old_wtda_audio, NS2SA( input_Fs, IVAS_LFE_FADE_NS ) ); /*-----------------------------------------------------------------* * LFE Window: allocate and initialize *-----------------------------------------------------------------*/ - if ( ( hLFE->pWindow_state = (LFE_WINDOW_HANDLE) count_malloc( sizeof( LFE_WINDOW_DATA ) ) ) == NULL ) + if ( ( hLFE->pWindow_state = (LFE_WINDOW_HANDLE) malloc( sizeof( LFE_WINDOW_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE window structure\n" ) ); } @@ -384,6 +437,16 @@ ivas_error ivas_create_lfe_enc( hLFE->cum_freq_models[1][2] = ivas_str_lfe_freq_models.entropy_coder_model_coarse_sg3; hLFE->cum_freq_models[1][3] = &ivas_str_lfe_freq_models.entropy_coder_model_coarse_sg4; + /* Initialization base2 bits for each subgroup for no entropy coding */ + for ( i = 0; i < IVAS_MAX_NUM_QUANT_STRATS; i++ ) + { + for ( j = 0; j < IVAS_MAX_NUM_DCT_COEF_GROUPS; j++ ) + { + hLFE->lfe_enc_indices_coeffs_tbl[i][j] = + (int16_t) ceilf( log2f( (float) ( ivas_lfe_num_ele_in_coder_models[i][j] + 1 ) ) ); + } + } + *hLFE_out = hLFE; return IVAS_ERR_OK; @@ -397,21 +460,27 @@ ivas_error ivas_create_lfe_enc( *-------------------------------------------------------------------------*/ void ivas_lfe_enc_close( - LFE_ENC_HANDLE hLFE /* i/o: LFE encoder handle */ + LFE_ENC_HANDLE *hLFE /* i/o: LFE encoder handle */ ) { - if ( hLFE->old_wtda_audio != NULL ) + if ( hLFE == NULL || *hLFE == NULL ) + { + return; + } + + if ( ( *hLFE )->old_wtda_audio != NULL ) { - count_free( hLFE->old_wtda_audio ); - hLFE->old_wtda_audio = NULL; + free( ( *hLFE )->old_wtda_audio ); + ( *hLFE )->old_wtda_audio = NULL; } - if ( hLFE->pWindow_state ) + if ( ( *hLFE )->pWindow_state ) { - count_free( hLFE->pWindow_state ); - hLFE->pWindow_state = NULL; + free( ( *hLFE )->pWindow_state ); + ( *hLFE )->pWindow_state = NULL; } - count_free( hLFE ); + free( ( *hLFE ) ); + ( *hLFE ) = NULL; return; } diff --git a/lib_enc/ivas_masa_enc.c b/lib_enc/ivas_masa_enc.c index cda908a49b1365de8c52f7aedc60ae2fb8a358f1..fbb7af9ab4a3b42566b82e3c6f7fe953251b40b6 100644 --- a/lib_enc/ivas_masa_enc.c +++ b/lib_enc/ivas_masa_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,15 +31,16 @@ *******************************************************************************************************/ #include -#include "options.h" #include +#include "options.h" #include "ivas_cnst.h" #include "ivas_prot.h" #include "ivas_rom_com.h" #include "ivas_stat_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" + /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ @@ -50,9 +51,9 @@ static void combine_directions( MASA_ENCODER_HANDLE hMasa ); static void find_n_largest( const float *input, int16_t *largestIndices, const int16_t numElements, const int16_t numLargest ); -static void move_metadata_to_qmetadata( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMeta ); +static void move_metadata_to_qmetadata( const MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMeta ); -static void detect_metadata_composition( MASA_ENCODER_HANDLE hMasa, uint8_t *joinedSubframes, uint8_t *coherencePresent, uint8_t *isTwoDir ); +static void detect_metadata_composition( const MASA_ENCODER_HANDLE hMasa, uint8_t *joinedSubframes, uint8_t *coherencePresent, uint8_t *isTwoDir ); static void compensate_energy_ratios( MASA_ENCODER_HANDLE hMasa ); @@ -60,6 +61,17 @@ static int16_t encode_lfe_to_total_energy_ratio( MASA_ENCODER_HANDLE hMasa, BSTR static void reduce_metadata_further( MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hqmetadata, const IVAS_FORMAT ivas_format ); +#ifdef FIX_382_MASA_META_FRAMING_ASYNC +static void average_masa_metadata( MASA_METADATA_FRAME *masaMetadata, float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] ); + +static void copy_masa_metadata_subframe( const MASA_METADATA_HANDLE hMetaFrom, const uint8_t sfFrom, MASA_METADATA_HANDLE hMetaTo, const uint8_t sfTo ); + +static void copy_masa_metadata( const MASA_METADATA_HANDLE hMetaFrom, MASA_METADATA_HANDLE hMetaTo ); + +static uint8_t are_masa_subframes_similar( const MASA_METADATA_HANDLE frame1, const uint8_t sf1_idx, const MASA_METADATA_HANDLE frame2, const uint8_t sf2_idx ); + +static void detect_framing_async( MASA_ENCODER_HANDLE hMasa ); +#endif /*-----------------------------------------------------------------------* * Local constants @@ -88,7 +100,7 @@ ivas_error ivas_masa_enc_open( error = IVAS_ERR_OK; - if ( ( hMasa = (MASA_ENCODER_HANDLE) count_malloc( sizeof( MASA_ENCODER ) ) ) == NULL ) + if ( ( hMasa = (MASA_ENCODER_HANDLE) malloc( sizeof( MASA_ENCODER ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) ); } @@ -119,14 +131,16 @@ ivas_error ivas_masa_enc_open( mvs2s( DirAC_block_grouping, hMasa->config.block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); mvs2s( MASA_band_grouping_24, hMasa->config.band_grouping, MASA_FREQUENCY_BANDS + 1 ); +#ifndef FIX_350_MASA_DELAY_COMP if ( hEncoderConfig->ivas_format == MASA_FORMAT ) { for ( i = 0; i < st_ivas->nchan_transport; i++ ) { - hMasa->data.delay_buffer[i] = (float *) count_malloc( MASA_ENC_DELAY_SLOTS * CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hMasa->data.delay_buffer[i] = (float *) malloc( MASA_ENC_DELAY_SLOTS * CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); set_f( hMasa->data.delay_buffer[i], 0.0f, MASA_ENC_DELAY_SLOTS * CLDFB_NO_CHANNELS_MAX ); } } +#endif hMasa->data.onset_detector_1 = 0.0f; hMasa->data.onset_detector_2 = 0.0f; @@ -134,6 +148,13 @@ ivas_error ivas_masa_enc_open( set_zero( hMasa->data.lfeToTotalEnergyRatio, MAX_PARAM_SPATIAL_SUBFRAMES ); hMasa->data.prevq_lfeToTotalEnergyRatio = 0.0f; hMasa->data.prevq_lfeIndex = 0; + +#ifdef FIX_382_MASA_META_FRAMING_ASYNC + hMasa->data.sync_state.prev_sim_stop = 0; + hMasa->data.sync_state.prev_offset = 0; + hMasa->data.sync_state.frame_mode = MASA_FRAME_4SF; +#endif + st_ivas->hMasa = hMasa; return error; @@ -147,28 +168,39 @@ ivas_error ivas_masa_enc_open( *-----------------------------------------------------------------------*/ void ivas_masa_enc_close( - MASA_ENCODER_HANDLE hMasa, /* i/o: MASA metadata structure */ + MASA_ENCODER_HANDLE *hMasa /* i/o: MASA metadata structure */ +#ifndef FIX_350_MASA_DELAY_COMP + , const int16_t nchan_transport, /* i : Number of transport channels */ const IVAS_FORMAT ivas_format /* i : IVAS format */ +#endif ) { int16_t i; - for ( i = 0; i < hMasa->data.num_Cldfb_instances; i++ ) + if ( hMasa == NULL || *hMasa == NULL ) { - deleteCldfb( &( hMasa->data.cldfbAnaEnc[i] ) ); + return; } + for ( i = 0; i < ( *hMasa )->data.num_Cldfb_instances; i++ ) + { + deleteCldfb( &( ( *hMasa )->data.cldfbAnaEnc[i] ) ); + } + +#ifndef FIX_350_MASA_DELAY_COMP if ( ivas_format == MASA_FORMAT ) { for ( i = 0; i < nchan_transport; i++ ) { - count_free( hMasa->data.delay_buffer[i] ); - hMasa->data.delay_buffer[i] = NULL; + free( ( *hMasa )->data.delay_buffer[i] ); + ( *hMasa )->data.delay_buffer[i] = NULL; } } +#endif - count_free( hMasa ); + free( ( *hMasa ) ); + ( *hMasa ) = NULL; return; } @@ -180,7 +212,7 @@ void ivas_masa_enc_close( * main MASA encoder function *-----------------------------------------------------------------------*/ -void ivas_masa_encode( +ivas_error ivas_masa_encode( MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder structure */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ BSTR_ENC_HANDLE hMetaData, /* i/o: Metadata bitstream handle */ @@ -219,7 +251,11 @@ void ivas_masa_encode( if ( Opt_DTX_ON ) { - h_orig_metadata = (MASA_DIRECTIONAL_SPATIAL_META *) count_malloc( MASA_MAXIMUM_DIRECTIONS * sizeof( MASA_DIRECTIONAL_SPATIAL_META ) ); + if ( ( h_orig_metadata = (MASA_DIRECTIONAL_SPATIAL_META *) malloc( MASA_MAXIMUM_DIRECTIONS * sizeof( MASA_DIRECTIONAL_SPATIAL_META ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA encoder\n" ) ); + } + for ( i = 0; i < MASA_MAXIMUM_DIRECTIONS; i++ ) { for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) @@ -348,11 +384,9 @@ void ivas_masa_encode( } } - count_free( h_orig_metadata ); + free( h_orig_metadata ); - ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, masa_sid_descriptor, - ivas_format, - SBA_MODE_NONE ); + ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, masa_sid_descriptor, ivas_format, SBA_MODE_NONE ); /* restore old values */ hMasa->config.numCodingBands = numCodingBands; @@ -363,7 +397,7 @@ void ivas_masa_encode( hQMetaData->no_directions = numberOfDirectionsQMetaData; } - return; + return IVAS_ERR_OK; } @@ -399,6 +433,12 @@ void ivas_masa_estimate_energy( for ( ts = mrange[0]; ts < mrange[1]; ts++ ) { +#ifdef FIX_350_MASA_DELAY_COMP + for ( i = 0; i < nchan_transport; i++ ) + { + cldfbAnalysis_ts( &( data_f[i][l_ts * ts] ), Input_RealBuffer[i], Input_ImagBuffer[i], l_ts, hMasa->data.cldfbAnaEnc[i] ); + } +#else if ( ts < MASA_ENC_DELAY_SLOTS ) { for ( i = 0; i < nchan_transport; i++ ) @@ -413,6 +453,7 @@ void ivas_masa_estimate_energy( cldfbAnalysis_ts( &( data_f[i][l_ts * ( ts - MASA_ENC_DELAY_SLOTS )] ), Input_RealBuffer[i], Input_ImagBuffer[i], l_ts, hMasa->data.cldfbAnaEnc[i] ); } } +#endif for ( band_m_idx = 0; band_m_idx < MASA_FREQUENCY_BANDS; band_m_idx++ ) { @@ -440,10 +481,12 @@ void ivas_masa_estimate_energy( } } +#ifndef FIX_350_MASA_DELAY_COMP for ( i = 0; i < nchan_transport; i++ ) { mvr2r( &data_f[i][input_frame - MASA_ENC_DELAY_SLOTS * maxBin], &( hMasa->data.delay_buffer[i][0] ), MASA_ENC_DELAY_SLOTS * maxBin ); } +#endif return; } @@ -478,9 +521,19 @@ ivas_error ivas_masa_enc_config( ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, hQMetaData, &st_ivas->hEncoderConfig->element_mode_init, &st_ivas->nSCE, &st_ivas->nCPE ); - hQMetaData->is_masa_type_format = 1; + hQMetaData->is_masa_ivas_format = 1; + if ( ivas_format == MASA_FORMAT ) { +#ifdef FIX_382_MASA_META_FRAMING_ASYNC + detect_framing_async( hMasa ); /* detect the offset, set 1sf/4sf mode based on this. potentially also shift the metadata using a history buffer */ + if ( hMasa->data.sync_state.frame_mode == MASA_FRAME_1SF && hMasa->data.sync_state.prev_offset != 0 ) + { + /* average over sub-frames */ + average_masa_metadata( &( hMasa->masaMetadata ), hMasa->data.energy ); + } +#endif + /* Inspect metadata for parameter changes that affect coding. */ detect_metadata_composition( hMasa, &joinedSubframes, &coherencePresent, &isActualTwoDir ); hMasa->config.joinedSubframes = joinedSubframes; @@ -489,7 +542,7 @@ ivas_error ivas_masa_enc_config( } else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) { - /* For mcMASA, these are set only once as this function is called only once. */ + /* For McMASA, these are set only once as this function is called only once. */ hMasa->config.joinedSubframes = 0; hMasa->config.numberOfDirections = 1; } @@ -570,7 +623,11 @@ ivas_error ivas_masa_enc_config( ivas_set_qmetadata_maxbit_req( hQMetaData, ivas_format ); +#ifdef FIX_350_MASA_DELAY_COMP + masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, hQMetaData, st_ivas->hEncoderConfig->input_Fs, NULL ); +#else masa_sample_rate_band_correction( &( hMasa->config ), hMasa->data.band_mapping, hQMetaData, st_ivas->hEncoderConfig->input_Fs ); +#endif /* Transmit stereo signals using a mono downmix at lowest bitrates */ if ( ivas_format == MASA_FORMAT && st_ivas->nCPE == 1 && st_ivas->hCPE[0]->hStereoDft != NULL && st_ivas->hCPE[0]->hStereoDft->hConfig != NULL ) @@ -680,9 +737,10 @@ static void combine_freqbands_and_subframes( if ( numCodingBands < MASA_FREQUENCY_BANDS ) { + /* reduce metadata *frequency* resolution. time resolution is not touched */ for ( i = 0; i < numDirections; i++ ) { - for ( j = 0; j < numSf; j++ ) + for ( j = 0; j < numSf; j++ ) /* NB: for numSf==1, operates only on first sub-frame */ { for ( k = 0; k < MASA_FREQUENCY_BANDS; k++ ) { @@ -756,7 +814,7 @@ static void combine_freqbands_and_subframes( } } } - else if ( mergeRatiosOverSubframes ) + else if ( mergeRatiosOverSubframes ) /* keep frequency resolution */ { for ( j = 0; j < numSf; j++ ) { @@ -984,7 +1042,7 @@ static void find_n_largest( static void move_metadata_to_qmetadata( - MASA_ENCODER_HANDLE hMasa, + const MASA_ENCODER_HANDLE hMasa, IVAS_QMETADATA_HANDLE hQMeta ) { int16_t dir, sf, band; @@ -1056,18 +1114,25 @@ static void move_metadata_to_qmetadata( /* This function studies parametric MASA metadata to provide information for codec configuration */ static void detect_metadata_composition( - MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder data */ - uint8_t *joinedSubframes, /* o : Result of subframe composition */ - uint8_t *coherencePresent, /* o : Result of coherence presence */ - uint8_t *isTwoDir /* o : Result of two direction check */ + const MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder data */ + uint8_t *joinedSubframes, /* o : Result of subframe composition */ + uint8_t *coherencePresent, /* o : Result of coherence presence */ + uint8_t *isTwoDir /* o : Result of two direction check */ ) { MASA_METADATA_FRAME *hMeta; +#ifdef FIX_382_MASA_META_FRAMING_ASYNC + int8_t sf, band, dir, numDir; +#else int16_t sf, band, dir, numDir; +#endif int16_t nSubFrames; uint8_t dirValid[2] = { FALSE }; uint8_t cohPresent = FALSE; uint8_t sfDiffer = FALSE; +#ifdef FIX_382_MASA_META_FRAMING_ASYNC + uint8_t sfSimilar; +#endif hMeta = &( hMasa->masaMetadata ); numDir = hMeta->descriptive_meta.numberOfDirections + 1; @@ -1132,6 +1197,16 @@ static void detect_metadata_composition( } /* Check if data over subframes is identical. Check is done by comparing to first subframe. */ +#ifdef FIX_382_MASA_META_FRAMING_ASYNC + sfSimilar = TRUE; + sf = 1; + while ( ( sfSimilar == TRUE ) && ( sf < MAX_PARAM_SPATIAL_SUBFRAMES ) ) + { + sfSimilar = are_masa_subframes_similar( hMeta, 0, hMeta, sf ); + sf++; + } + sfDiffer = sfSimilar == TRUE ? FALSE : TRUE; +#else dir = 0; while ( sfDiffer == FALSE && dir < numDir ) { @@ -1178,6 +1253,7 @@ static void detect_metadata_composition( } dir++; } +#endif /* Further checks can be done with just one subframe if they are identical */ nSubFrames = sfDiffer == TRUE ? MAX_PARAM_SPATIAL_SUBFRAMES : 1; @@ -1679,6 +1755,7 @@ void ivas_masa_enc_reconfigure( int16_t n, tmp; int16_t sce_id, cpe_id; int32_t ivas_total_brate; + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) @@ -1720,3 +1797,404 @@ void ivas_masa_enc_reconfigure( return; } + + +#ifdef FIX_382_MASA_META_FRAMING_ASYNC +/*-------------------------------------------------------------------* + * average_masa_metadata() + * + * Average MASA metadata frame subframe contents: applies aggregation over time + *-------------------------------------------------------------------*/ + +static void average_masa_metadata( + MASA_METADATA_FRAME *hMeta, + float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] ) +{ + int16_t i, j, k; + float azi_rad, ele_rad; + uint8_t numDirections; + + /* use the nominal values without data-adaptivity */ + numDirections = hMeta->descriptive_meta.numberOfDirections + 1; + + /* azi/ele/nrg into vectors for each sub-frame and band */ + for ( i = 0; i < numDirections; i++ ) + { + for ( k = 0; k < MASA_FREQUENCY_BANDS; k++ ) + { + float x_sum, y_sum, z_sum, energy_sum, vec_len, spread_coh_sum, surr_coh_sum; + + x_sum = 0.0f; + y_sum = 0.0f; + z_sum = 0.0f; + energy_sum = 0.0f; + spread_coh_sum = 0.0f; + surr_coh_sum = 0.0f; + for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + azi_rad = hMeta->directional_meta[i].azimuth[j][k] / 180.0f * EVS_PI; + ele_rad = hMeta->directional_meta[i].elevation[j][k] / 180.0f * EVS_PI; + vec_len = hMeta->directional_meta[i].energy_ratio[j][k] * energy[j][k]; + + /* energy-weighted sum over subframes */ + x_sum += cosf( azi_rad ) * cosf( ele_rad ) * vec_len; + y_sum += sinf( azi_rad ) * cosf( ele_rad ) * vec_len; + z_sum += sinf( ele_rad ) * vec_len; + + energy_sum += energy[j][k]; + + spread_coh_sum += hMeta->directional_meta[i].spread_coherence[j][k] * energy[j][k]; + if ( i == 0 ) + { + /* this is in common metadata and not in each direction */ + surr_coh_sum += hMeta->common_meta.surround_coherence[j][k] * energy[j][k]; + } + } + + /* the data from the combined sub-frames is written into the first sub-frame band */ + j = 0; + hMeta->directional_meta[i].azimuth[j][k] = atan2f( y_sum, x_sum ) / EVS_PI * 180.0f; + hMeta->directional_meta[i].elevation[j][k] = atan2f( z_sum, sqrtf( x_sum * x_sum + y_sum * y_sum ) ) / EVS_PI * 180.0f; + + vec_len = sqrtf( x_sum * x_sum + y_sum * y_sum + z_sum * z_sum ); + hMeta->directional_meta[i].energy_ratio[j][k] = vec_len / ( energy_sum + EPSILON ); + + hMeta->directional_meta[i].spread_coherence[j][k] = spread_coh_sum / ( energy_sum + EPSILON ); + if ( i == 0 ) + { + hMeta->common_meta.surround_coherence[j][k] = surr_coh_sum / ( energy_sum + EPSILON ); + } + + /* copy the same value to all subframes */ + for ( j = 1; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + hMeta->directional_meta[i].azimuth[j][k] = hMeta->directional_meta[i].azimuth[0][k]; + hMeta->directional_meta[i].elevation[j][k] = hMeta->directional_meta[i].elevation[0][k]; + hMeta->directional_meta[i].energy_ratio[j][k] = hMeta->directional_meta[i].energy_ratio[0][k]; + hMeta->directional_meta[i].spread_coherence[j][k] = hMeta->directional_meta[i].spread_coherence[0][k]; + if ( i == 0 ) + { + hMeta->common_meta.surround_coherence[j][k] = hMeta->common_meta.surround_coherence[0][k]; + } + } + } + } + + for ( k = 0; k < MASA_FREQUENCY_BANDS; k++ ) + { + for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + if ( numDirections == 2 ) + { + hMeta->common_meta.diffuse_to_total_ratio[j][k] = max( 0.0f, 1.0f - hMeta->directional_meta[1].energy_ratio[j][k] - hMeta->directional_meta[0].energy_ratio[j][k] ); + } + else + { + hMeta->common_meta.diffuse_to_total_ratio[j][k] = max( 0.0f, 1.0f - hMeta->directional_meta[0].energy_ratio[j][k] ); + } + hMeta->common_meta.remainder_to_total_ratio[j][k] = 0.0f; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * copy_masa_metadata_subframe() + * + * Copy MASA metadata frame subframe contents + *-------------------------------------------------------------------*/ + +static void copy_masa_metadata_subframe( + const MASA_METADATA_HANDLE hMetaFrom, /* i : MASA frame metdata to be copied */ + const uint8_t sfFrom, /* i : subframe index of the copy source */ + MASA_METADATA_HANDLE hMetaTo, /* o : MASA frame metadata copy destination */ + const uint8_t sfTo /* i : subframe index of the copy target */ +) +{ + uint8_t dir; + + /* directional metadata */ + for ( dir = 0; dir < MASA_MAXIMUM_DIRECTIONS; dir++ ) + { + mvr2r( hMetaFrom->directional_meta[dir].azimuth[sfFrom], hMetaTo->directional_meta[dir].azimuth[sfTo], MASA_FREQUENCY_BANDS ); + mvr2r( hMetaFrom->directional_meta[dir].elevation[sfFrom], hMetaTo->directional_meta[dir].elevation[sfTo], MASA_FREQUENCY_BANDS ); + mvr2r( hMetaFrom->directional_meta[dir].energy_ratio[sfFrom], hMetaTo->directional_meta[dir].energy_ratio[sfTo], MASA_FREQUENCY_BANDS ); + mvr2r( hMetaFrom->directional_meta[dir].spread_coherence[sfFrom], hMetaTo->directional_meta[dir].spread_coherence[sfTo], MASA_FREQUENCY_BANDS ); + } + + /* common metadata */ + mvr2r( hMetaFrom->common_meta.diffuse_to_total_ratio[sfFrom], hMetaTo->common_meta.diffuse_to_total_ratio[sfTo], MASA_FREQUENCY_BANDS ); + mvr2r( hMetaFrom->common_meta.surround_coherence[sfFrom], hMetaTo->common_meta.surround_coherence[sfTo], MASA_FREQUENCY_BANDS ); + mvr2r( hMetaFrom->common_meta.remainder_to_total_ratio[sfFrom], hMetaTo->common_meta.remainder_to_total_ratio[sfTo], MASA_FREQUENCY_BANDS ); + + return; +} + + +/*-------------------------------------------------------------------* + * copy_masa_metadata() + * + * Copy MASA metada frame contents + *-------------------------------------------------------------------*/ + +static void copy_masa_metadata( + const MASA_METADATA_HANDLE hMetaFrom, /* i : MASA frame metadata to be copied */ + MASA_METADATA_HANDLE hMetaTo /* o : MASA frame metadata copy destination */ +) +{ + uint8_t sf, byte_idx; + + /* descriptive metadata */ + for ( byte_idx = 0; byte_idx < 8; byte_idx++ ) + { + hMetaTo->descriptive_meta.formatDescriptor[byte_idx] = hMetaFrom->descriptive_meta.formatDescriptor[byte_idx]; + } + + hMetaTo->descriptive_meta.numberOfDirections = hMetaFrom->descriptive_meta.numberOfDirections; + hMetaTo->descriptive_meta.numberOfChannels = hMetaFrom->descriptive_meta.numberOfChannels; + hMetaTo->descriptive_meta.sourceFormat = hMetaFrom->descriptive_meta.sourceFormat; + hMetaTo->descriptive_meta.transportDefinition = hMetaFrom->descriptive_meta.transportDefinition; + hMetaTo->descriptive_meta.channelAngle = hMetaFrom->descriptive_meta.channelAngle; + hMetaTo->descriptive_meta.channelDistance = hMetaFrom->descriptive_meta.channelDistance; + hMetaTo->descriptive_meta.channelLayout = hMetaFrom->descriptive_meta.channelLayout; + + /* directional and common metadata */ + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + copy_masa_metadata_subframe( hMetaFrom, sf, hMetaTo, sf ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * are_masa_subframes_similar() + * + * Compare the similarity of MASA metadata in two sub-frames + *-------------------------------------------------------------------*/ + +static uint8_t are_masa_subframes_similar( + const MASA_METADATA_HANDLE frame1, /* i : MASA metadata frame 1 */ + const uint8_t sf1_idx, /* i : index of the subframe of frame1 to inspect */ + const MASA_METADATA_HANDLE frame2, /* i : MASA metadata frame 2 */ + const uint8_t sf2_idx /* o : index of the subframe of frame2 to inspect */ +) +{ + uint8_t num_dir; + uint8_t dir; + uint8_t band_idx; + uint8_t sf_differ; + + num_dir = frame1->descriptive_meta.numberOfDirections; + dir = 0; + band_idx = 0; + sf_differ = FALSE; + + if ( num_dir != frame2->descriptive_meta.numberOfDirections ) + { + sf_differ = TRUE; + } + else + { + /* check per-direction metadata */ + dir = 0; + band_idx = 0; + + while ( ( sf_differ == FALSE ) && ( dir <= num_dir ) ) + { + band_idx = 0; + while ( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) ) + { + float azi_dif; + azi_dif = fabsf( frame1->directional_meta[dir].azimuth[sf1_idx][band_idx] - frame2->directional_meta[dir].azimuth[sf2_idx][band_idx] ); + azi_dif = azi_dif > 180.0f ? 360.0f - azi_dif : azi_dif; + + if ( azi_dif > MASA_ANGLE_TOLERANCE ) + { + sf_differ = TRUE; + break; + } + + if ( fabsf( frame1->directional_meta[dir].elevation[sf1_idx][band_idx] - frame2->directional_meta[dir].elevation[sf2_idx][band_idx] ) > MASA_ANGLE_TOLERANCE ) + { + sf_differ = TRUE; + break; + } + + if ( fabsf( frame1->directional_meta[dir].energy_ratio[sf1_idx][band_idx] - frame2->directional_meta[dir].energy_ratio[sf2_idx][band_idx] ) > MASA_RATIO_TOLERANCE ) + { + sf_differ = TRUE; + break; + } + + if ( fabsf( frame1->directional_meta[dir].spread_coherence[sf1_idx][band_idx] - frame2->directional_meta[dir].spread_coherence[sf2_idx][band_idx] ) > MASA_COHERENCE_TOLERANCE ) + { + sf_differ = TRUE; + break; + } + + band_idx++; + } + dir++; + } + + /* check the common metadata */ + while ( ( sf_differ == FALSE ) && ( band_idx < MASA_FREQUENCY_BANDS ) ) + { + if ( fabsf( frame1->common_meta.surround_coherence[sf1_idx][band_idx] - frame2->common_meta.surround_coherence[sf2_idx][band_idx] ) > MASA_COHERENCE_TOLERANCE ) + { + sf_differ = TRUE; + break; + } + + band_idx++; + } + } + + /* TODO: a nicer negation */ // VE: ?? + if ( sf_differ ) + { + return FALSE; + } + else + { + return TRUE; + } +} + + +/*-------------------------------------------------------------------* + * detect_framing_async() + * + * Compare the similarity of MASA metadata in two sub-frames + * Analysis result is stored in hMasa->data.sync_state, and + * potentially hMasa->masaMetadata is modified + *-------------------------------------------------------------------*/ + +static void detect_framing_async( + MASA_ENCODER_HANDLE hMasa /* i/o: MASA encoder structure */ +) +{ + MASA_METADATA_HANDLE current_meta; + MASA_METADATA_HANDLE previous_meta; + MASA_SYNC_HANDLE sync_state; + MASA_FRAME_MODE frame_mode; + uint8_t n_sim_start, n_sim_stop, sf_idx; + uint8_t found_offset; + + current_meta = &( hMasa->masaMetadata ); /* metadata from current frame */ + sync_state = &( hMasa->data.sync_state ); /* synchronization structure */ + previous_meta = &( sync_state->previous_metadata ); + + /* check current frame, how many are similar from the start and from the end */ + n_sim_start = 1; + for ( sf_idx = n_sim_start; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + if ( are_masa_subframes_similar( current_meta, 0, current_meta, sf_idx ) == TRUE ) + { + n_sim_start = sf_idx + 1; + } + else + { + break; + } + } + + /* number of similar sub-frames starting from the end of the frame */ + if ( n_sim_start == MAX_PARAM_SPATIAL_SUBFRAMES ) /* shortcut */ + { + n_sim_stop = n_sim_start; + } + else + { + n_sim_stop = 1; + for ( sf_idx = 2; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + /* we need to check only the two middle sub-frames, as all being the same would have taken the shortcut above */ + if ( are_masa_subframes_similar( current_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1, current_meta, MAX_PARAM_SPATIAL_SUBFRAMES - sf_idx ) == TRUE ) + { + n_sim_stop = sf_idx; + } + else + { + break; + } + } + } + + frame_mode = MASA_FRAME_4SF; /* default mode: 4sf */ + if ( sync_state->prev_offset > MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) + { + /* earlier offset was large => reset the offset */ + found_offset = 0; + } + else + { + /* keep previous offset unless something else is found. alternatively, we could reset always */ + found_offset = sync_state->prev_offset; + } + + if ( ( n_sim_start == MAX_PARAM_SPATIAL_SUBFRAMES ) && ( n_sim_stop == MAX_PARAM_SPATIAL_SUBFRAMES ) ) + { + /* full frame consists of similar sub-frames */ + frame_mode = MASA_FRAME_1SF; + if ( ( sync_state->prev_sim_stop != 0 ) && ( are_masa_subframes_similar( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ) == TRUE ) ) + { + /* > 4 sub-frames of similar data */ + if ( sync_state->prev_sim_stop < 3 ) + { + /* can nicely align the framing with the earlier data and a small offset */ + found_offset = sync_state->prev_sim_stop; + } + else + { + /* too many similar sub-frames to determine the offset accurately => keep earlier value */ + found_offset = sync_state->prev_offset; + } + } + else + { + /* earlier window was different => reset the offset */ + found_offset = 0; + } + } + else if ( n_sim_stop == 3 ) + { + /* first sub-frame different that the rest 3 + => make a risky guess that the future sf would be the same too and we're in an offset case */ + frame_mode = MASA_FRAME_1SF; + found_offset = 3; + } + else if ( ( sync_state->prev_sim_stop > 0 ) && ( are_masa_subframes_similar( current_meta, 0, previous_meta, MAX_PARAM_SPATIAL_SUBFRAMES - 1 ) == TRUE ) ) + { + /* seeing data similar to past */ + if ( ( n_sim_start > 1 ) && ( n_sim_start + sync_state->prev_sim_stop >= MAX_PARAM_SPATIAL_SUBFRAMES ) ) + { + /* with the past, would have at least one long frame similar subframes */ + frame_mode = MASA_FRAME_1SF; + + if ( sync_state->prev_offset == 0 ) + { + found_offset = min( 2, sync_state->prev_sim_stop ); + } + else + { + found_offset = sync_state->prev_offset; + } + } + } + + /* keep the original contents of the frame, but then perform interpolation later */ + /* just copy current frame to storage */ + copy_masa_metadata( current_meta, previous_meta ); + + sync_state->prev_sim_stop = n_sim_stop; + sync_state->prev_offset = found_offset; + sync_state->frame_mode = frame_mode; + + return; +} +#endif diff --git a/lib_enc/ivas_mc_param_enc.c b/lib_enc/ivas_mc_param_enc.c index fce9a85f714efc3fc4f4955d1fd23753a371f030..db9945d0cec3cc358dcec3be5c7ddd917e750ad7 100644 --- a/lib_enc/ivas_mc_param_enc.c +++ b/lib_enc/ivas_mc_param_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #ifdef DEBUG_PLOT #include "deb_out.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -75,6 +75,7 @@ static void ivas_param_mc_encode_parameter( int16_t *idx_in, HANDLE_IVAS_PARAM_M static void ivas_param_mc_range_encoder( const int16_t *seq_in, const int16_t num_symbols, const uint16_t *cum_freq, const uint16_t *sym_freq, const uint16_t tot_shift, const int16_t max_nb_bits, uint16_t *bit_buffer, int16_t *bit_pos ); + /*------------------------------------------------------------------------- * ivas_param_mc_enc_open() * @@ -97,7 +98,7 @@ ivas_error ivas_param_mc_enc_open( error = IVAS_ERR_OK; /* Sanity Checks */ - if ( ( hParamMC = (PARAM_MC_ENC_HANDLE) count_malloc( sizeof( PARAM_MC_ENC_DATA ) ) ) == NULL ) + if ( ( hParamMC = (PARAM_MC_ENC_HANDLE) malloc( sizeof( PARAM_MC_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Paramtric MC\n" ) ); } @@ -145,12 +146,11 @@ ivas_error ivas_param_mc_enc_open( } /* Allocate and initialize FB mixer handle */ - if ( ( error = ivas_FB_mixer_open( &( hParamMC->hFbMixer ), input_Fs, fb_cfg ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_FB_mixer_open( &( hParamMC->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) { return error; } - /* open/init parameter coding */ ivas_param_mc_metadata_open( mc_input_setup, hParamMC->lfe_index, ivas_total_brate, &hParamMC->hMetadataPMC ); @@ -219,6 +219,140 @@ ivas_error ivas_param_mc_enc_open( } +/*------------------------------------------------------------------------- + * ivas_param_mc_enc_reconfig() + * + * Reconfigure Parametric MC encoder + *------------------------------------------------------------------------*/ + +ivas_error ivas_param_mc_enc_reconfig( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +) +{ + int16_t i, k, l; + PARAM_MC_ENC_HANDLE hParamMC; + uint16_t config_index; + MC_LS_SETUP mc_input_setup; + int16_t max_bwidth; + int32_t input_Fs, ivas_total_brate; + ivas_error error; + + error = IVAS_ERR_OK; + + mc_input_setup = st_ivas->hEncoderConfig->mc_input_setup; + max_bwidth = st_ivas->hEncoderConfig->max_bwidth; + input_Fs = st_ivas->hEncoderConfig->input_Fs; + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + hParamMC = st_ivas->hParamMC; + + /* Preparing Config */ + st_ivas->nchan_transport = ivas_param_mc_getNumTransportChannels( ivas_total_brate, mc_input_setup ); + + /* get configuration index */ + config_index = ivas_param_mc_get_configuration_index( mc_input_setup, ivas_total_brate ); + + /* set core coder dependent on the number of transport channels */ + switch ( st_ivas->nchan_transport ) + { + case 4: + case 3: + st_ivas->nCPE = 2; + st_ivas->nSCE = 0; + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + break; + case 2: + st_ivas->nCPE = 1; + st_ivas->nSCE = 0; + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + break; +#ifdef DEBUGGING + default: + assert( 0 && "Number of transport channels not supported by ParamMC!\n" ); +#endif + } + + /* get dmx factors */ + hParamMC->dmx_factors = ivas_param_mc_conf[config_index].dmx_fac; + + /* deallocate the full icc map, gets newly allocated in the metadata open function */ + for ( i = 0; i < 2; i++ ) + { +#ifdef DEBUGGING + assert( hParamMC->hMetadataPMC.icc_map_full[i] != NULL ); +#endif + if ( hParamMC->hMetadataPMC.icc_map_full[i] != NULL ) + { + free( hParamMC->hMetadataPMC.icc_map_full[i] ); + hParamMC->hMetadataPMC.icc_map_full[i] = NULL; + } + } + + /* open/init parameter coding */ + ivas_param_mc_metadata_open( mc_input_setup, hParamMC->lfe_index, ivas_total_brate, &hParamMC->hMetadataPMC ); + + /* init icc index states */ + for ( i = 0; i < PARAM_MC_PARAMETER_FRAMES; i++ ) + { + set_s( hParamMC->icc_map_index[i], -1, PARAM_MC_SZ_ICC_MAP ); + + for ( l = 0; l < hParamMC->hMetadataPMC.icc_mapping_conf->icc_map_size_lfe; l++ ) + { + for ( k = 0; k < hParamMC->hMetadataPMC.icc_map_size_full; k++ ) + { + if ( hParamMC->hMetadataPMC.icc_mapping[i][l][0] == hParamMC->hMetadataPMC.icc_map_full[0][k] && hParamMC->hMetadataPMC.icc_mapping[i][l][1] == hParamMC->hMetadataPMC.icc_map_full[1][k] ) + { + hParamMC->icc_map_index[i][l] = k; + } + } + } + } + + /* Band Grouping */ + if ( hParamMC->hMetadataPMC.num_parameter_bands == 20 ) + { + mvs2s( param_mc_band_grouping_20, hParamMC->band_grouping, 20 + 1 ); + } + else if ( hParamMC->hMetadataPMC.num_parameter_bands == 14 ) + { + mvs2s( param_mc_band_grouping_14, hParamMC->band_grouping, 14 + 1 ); + } + else if ( hParamMC->hMetadataPMC.num_parameter_bands == 10 ) + { + mvs2s( param_mc_band_grouping_10, hParamMC->band_grouping, 10 + 1 ); + } + else + { + assert( 0 && "nbands must be 20, 14, or 10!" ); + } + + /* set max parameter band for abs cov */ + i = 0; + while ( hParamMC->band_grouping[i] <= PARAM_MC_MAX_BAND_ABS_COV_ENC ) + { + hParamMC->max_param_band_abs_cov = ( i++ ); + } + + /* parameter band grouping: 60 band CLDFB to 240 band MDFT resolution */ + for ( i = 0; i < hParamMC->hMetadataPMC.num_parameter_bands + 1; i++ ) + { + hParamMC->band_grouping[i] *= CLDFB_TO_MDFT_FAC; + } + + /* set correct coded band width */ + hParamMC->hMetadataPMC.coded_bwidth = max_bwidth; + hParamMC->hMetadataPMC.last_coded_bwidth = max_bwidth; + ivas_param_mc_set_coded_bands( &hParamMC->hMetadataPMC ); + + /* initialize offset for transient detection */ + hParamMC->transient_detector_delay = ( NSUBBLOCKS_SHIFT + 1 ) + NSUBBLOCKS + 1 - (int16_t) ceilf( (float) NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS ) / (float) NS2SA( input_Fs, 2 * DIRAC_SLOT_NS ) ); + + /* Init total/dmx ener factors */ + set_f( hParamMC->ener_fac, 0.0f, PARAM_MC_MAX_PARAMETER_BANDS ); + + return error; +} + + /*------------------------------------------------------------------------- * ivas_param_mc_enc_close() * @@ -226,14 +360,20 @@ ivas_error ivas_param_mc_enc_open( *------------------------------------------------------------------------*/ void ivas_param_mc_enc_close( - PARAM_MC_ENC_HANDLE hParamMC, /* i/o: Parametric MC encoder handle */ + PARAM_MC_ENC_HANDLE *hParamMC, /* i/o: Parametric MC encoder handle */ const int32_t sampling_rate ) { - ivas_param_mc_metadata_close( &hParamMC->hMetadataPMC ); + if ( hParamMC == NULL || *hParamMC == NULL ) + { + return; + } + + ivas_param_mc_metadata_close( &( *hParamMC )->hMetadataPMC ); - ivas_FB_mixer_close( &hParamMC->hFbMixer, sampling_rate ); + ivas_FB_mixer_close( &( *hParamMC )->hFbMixer, sampling_rate, 0 ); - count_free( hParamMC ); + free( ( *hParamMC ) ); + ( *hParamMC ) = NULL; return; } @@ -246,10 +386,10 @@ void ivas_param_mc_enc_close( *------------------------------------------------------------------------*/ void ivas_param_mc_enc( - Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ - BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ - float data_f[][L_FRAME48k], /* i/o: input: CICP6, CICP12, CICP14, CICP16 or CICP19 MC data */ - const int16_t input_frame /* i : input frame length */ + Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ + BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ + float data_f[][L_FRAME48k], /* i/o: input: CICP6, CICP12, CICP14, CICP16 or CICP19 MC data */ + const int16_t input_frame /* i : input frame length */ ) { int16_t k; @@ -267,7 +407,7 @@ void ivas_param_mc_enc( PARAM_MC_ENC_HANDLE hParamMC; int16_t nchan_inp; - wmops_sub_start( "param_mc_enc" ); + push_wmops( "param_mc_enc" ); /* initializations */ hParamMC = st_ivas->hParamMC; @@ -409,7 +549,7 @@ void ivas_param_mc_enc( /* updates */ hParamMC->hMetadataPMC.last_coded_bwidth = hParamMC->hMetadataPMC.coded_bwidth; - wmops_sub_end(); + pop_wmops(); return; } @@ -500,11 +640,9 @@ static void ivas_param_mc_param_est_enc( int16_t start_ts; const float *p_dmx_fac; - wmops_sub_start( "param_mc_prm_est" ); + push_wmops( "param_mc_prm_est" ); /* initializations */ - - l_ts = input_frame / PARAM_MC_MDFT_NO_SLOTS; num_time_slots = PARAM_MC_MDFT_NO_SLOTS; start_ts = hParamMC->hMetadataPMC.bAttackPresent ? hParamMC->hMetadataPMC.attackIndex : 0; @@ -776,8 +914,7 @@ static void ivas_param_mc_param_est_enc( hParamMC->hMetadataPMC.lfe_on = 1; } - - wmops_sub_end(); + pop_wmops(); return; } @@ -1034,7 +1171,7 @@ static void ivas_param_mc_quantize_ilds( float tot_ener, dmx_ener, ener_fac, delta_fac; int16_t ILD_idx[PARAM_MC_SZ_ILD_MAP]; - wmops_sub_start( "param_mc_prm_q" ); + push_wmops( "param_mc_prm_q" ); /* Initialization */ set_zero( Nrg, MAX_CICP_CHANNELS ); @@ -1056,7 +1193,7 @@ static void ivas_param_mc_quantize_ilds( /* Downsampling */ if ( ( hParamMC->hMetadataPMC.bAttackPresent == 0 ) && ( hParamMC->hMetadataPMC.param_frame_idx != hParamMC->hMetadataPMC.coding_band_mapping[freq_idx] ) ) { - wmops_sub_end(); + pop_wmops(); return; } @@ -1143,7 +1280,7 @@ static void ivas_param_mc_quantize_ilds( /* Save current quantized ICLDs */ mvs2s( ILD_idx, ILD_idx_out + freq_idx * ild_map_size, num_ilds_to_code ); - wmops_sub_end(); + pop_wmops(); return; } @@ -1308,7 +1445,7 @@ static void ivas_param_mc_transient_detection( float *pAccSubblockNrg; float attackRatioThreshold; - wmops_sub_start( "param_mc_trn_det" ); + push_wmops( "param_mc_trn_det" ); attackRatioThreshold = hTranDet->transientDetector.attackRatioThreshold; pSubblockNrg = &hTranDet->subblockEnergies.subblockNrg[hParamMC->transient_detector_delay]; @@ -1339,7 +1476,7 @@ static void ivas_param_mc_transient_detection( *pAttackIndex = attackIndex; *pbIsAttackPresent = bIsAttackPresent; - wmops_sub_end(); + pop_wmops(); return; } @@ -1369,7 +1506,7 @@ static void ivas_param_mc_write_bs( int16_t ild_map_size_wo_lfe; int16_t ild_map_size; - wmops_sub_start( "param_mc_prm_enc" ); + push_wmops( "param_mc_prm_enc" ); /* Init */ set_zero( seq_tmp_uni, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ILD_MAP ); @@ -1434,7 +1571,7 @@ static void ivas_param_mc_write_bs( ivas_param_mc_encode_parameter( ILD_idx, &hParamMC->hMetadataPMC, &hParamMC->hMetadataPMC.ild_coding, nbands, band_step, ild_map_size_wo_lfe, ild_map_size, bit_buffer, bit_pos ); - wmops_sub_end(); + pop_wmops(); return; } @@ -1518,7 +1655,7 @@ static void ivas_param_mc_encode_parameter( dbgwrite( seq, sizeof( int16_t ), sz_seq, 1, "./res/param_mc_quant_param_idx_enc.dat" ); #endif - bit_cnt_uni = sz_seq * hParameterCodingInfo->uni_bits - 1; /* -1 for the additional diff/direct signalling bit for the range encoder*/ + bit_cnt_uni = sz_seq * hParameterCodingInfo->uni_bits - 1; /* -1 for the additional diff/direct signaling bit for the range encoder*/ /* code the direct index sequence */ ivas_param_mc_range_encoder( seq, sz_seq, hParameterCodingInfo->cum_freq, hParameterCodingInfo->sym_freq, PARAM_MC_RANGE_CODER_TOT_SHIFT, bit_cnt_uni, &tmp_bit_buffer[0], &bit_cnt_range ); @@ -1587,6 +1724,7 @@ static void ivas_param_mc_dec2bin( { bits[idx] = ( val >> ( N - 1 - idx ) ) & 1; } + return; } diff --git a/lib_enc/ivas_mcmasa_enc.c b/lib_enc/ivas_mcmasa_enc.c index 595f758e51b715415306ac608e6c5f70f50aa4a4..866e4e176c9b0f915d58f87ff6d993486652c258 100644 --- a/lib_enc/ivas_mcmasa_enc.c +++ b/lib_enc/ivas_mcmasa_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,7 +34,6 @@ #include #include #include - #include "ivas_cnst.h" #include "ivas_prot.h" #include "options.h" @@ -44,7 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -70,9 +69,7 @@ static void ivas_mcmasa_dmx( MCMASA_ENC_HANDLE hMcMasa, float data_f[][L_FRAME48 static void compute_cov_mtx( float sr[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], float si[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], const int16_t freq, const int16_t N, CovarianceMatrix *COVls ); -static void computeIntensityVector_enc( const int16_t *band_grouping, float Cldfb_RealBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], float Cldfb_ImagBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], const int16_t enc_param_start_band, /* i: first band to process */ - const int16_t num_frequency_bands, - float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS] ); +static void computeIntensityVector_enc( const int16_t *band_grouping, float Cldfb_RealBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], float Cldfb_ImagBuffer[DIRAC_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], const int16_t enc_param_start_band, const int16_t num_frequency_bands, float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS] ); static void computeVerticalDiffuseness( float **buffer_intensity, const float *buffer_energy, const int16_t averaging_length, const int16_t num_freq_bands, float *diffuseness ); @@ -113,7 +110,7 @@ ivas_error ivas_mcmasa_enc_open( assert( st_ivas->hMasa != NULL && "MASA encoder handle is not present" ); hMasa = st_ivas->hMasa; - if ( NULL == ( hMcMasa = (MCMASA_ENC_HANDLE) count_malloc( sizeof( MCMASA_ENC_DATA ) ) ) ) + if ( ( hMcMasa = (MCMASA_ENC_HANDLE) malloc( sizeof( MCMASA_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } @@ -197,7 +194,7 @@ ivas_error ivas_mcmasa_enc_open( } /* Allocate and initialize FB mixer handle */ - if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixer ), input_Fs, fb_cfg ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) { return error; } @@ -206,9 +203,16 @@ ivas_error ivas_mcmasa_enc_open( if ( hMcMasa->separateChannelEnabled ) { /* TD Energy calculation with LP */ - hMcMasa->delay_buffer_lfe[0] = (float *) count_malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ); + if ( ( hMcMasa->delay_buffer_lfe[0] = (float *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } set_zero( hMcMasa->delay_buffer_lfe[0], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); - hMcMasa->delay_buffer_lfe[1] = (float *) count_malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ); + + if ( ( hMcMasa->delay_buffer_lfe[1] = (float *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } set_zero( hMcMasa->delay_buffer_lfe[1], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); hMcMasa->hFbMixerLfe = NULL; } @@ -220,7 +224,7 @@ ivas_error ivas_mcmasa_enc_open( return error; } - if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixerLfe ), input_Fs, fb_cfgLfe ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixerLfe ), input_Fs, fb_cfgLfe, 0 ) ) != IVAS_ERR_OK ) { return error; } @@ -238,7 +242,10 @@ ivas_error ivas_mcmasa_enc_open( bufferSize = (int16_t) ( ( input_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES ); for ( i = 0; i < 2; i++ ) { - hMcMasa->lfeAnaRingBuffer[i] = (float *) count_malloc( bufferSize * sizeof( float ) ); + if ( ( hMcMasa->lfeAnaRingBuffer[i] = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } set_zero( hMcMasa->lfeAnaRingBuffer[i], bufferSize ); hMcMasa->lowpassSum[i] = 0.0f; } @@ -252,33 +259,56 @@ ivas_error ivas_mcmasa_enc_open( /* intensity 3-dim */ for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - hMcMasa->direction_vector_m[i] = (float **) count_malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ); + if ( ( hMcMasa->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { - hMcMasa->direction_vector_m[i][j] = (float *) count_malloc( hMcMasa->nbands * sizeof( float ) ); + if ( ( hMcMasa->direction_vector_m[i][j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } } } hMcMasa->no_col_avg_diff = (int8_t) ( DIRAC_NO_COL_AVG_DIFF_NS / dirac_slot_ns ); for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - hMcMasa->buffer_intensity_real[i] = (float **) count_malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ); + if ( ( hMcMasa->buffer_intensity_real[i] = (float **) malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) { - hMcMasa->buffer_intensity_real[i][j] = (float *) count_malloc( hMcMasa->nbands * sizeof( float ) ); + if ( ( hMcMasa->buffer_intensity_real[i][j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } set_zero( hMcMasa->buffer_intensity_real[i][j], hMcMasa->nbands ); } } - hMcMasa->buffer_intensity_real_vert = (float **) count_malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ); + if ( ( hMcMasa->buffer_intensity_real_vert = (float **) malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) { - hMcMasa->buffer_intensity_real_vert[j] = (float *) count_malloc( hMcMasa->nbands * sizeof( float ) ); + if ( ( hMcMasa->buffer_intensity_real_vert[j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } set_zero( hMcMasa->buffer_intensity_real_vert[j], hMcMasa->nbands ); } - hMcMasa->buffer_energy = (float *) count_malloc( hMcMasa->nbands * hMcMasa->no_col_avg_diff * sizeof( float ) ); + if ( ( hMcMasa->buffer_energy = (float *) malloc( hMcMasa->nbands * hMcMasa->no_col_avg_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } set_zero( hMcMasa->buffer_energy, hMcMasa->nbands * hMcMasa->no_col_avg_diff ); if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1 ) @@ -398,6 +428,54 @@ ivas_error ivas_mcmasa_enc_open( } +/*------------------------------------------------------------------------- + * ivas_mcmasa_enc_reconfig() + * + * Reconfigure McMASA encoder + *------------------------------------------------------------------------*/ + +ivas_error ivas_mcmasa_enc_reconfig( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + int32_t ivas_total_brate; + ivas_error error; + + error = IVAS_ERR_OK; + + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + + if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) + { + /* bitrate changed, may need to do something */ + + /* brute-force solution: close McMASA and re-instantiate with new settings */ +#ifdef FIX_350_MASA_DELAY_COMP + ivas_masa_enc_close( &( st_ivas->hMasa ) ); +#else + ivas_masa_enc_close( &( st_ivas->hMasa ), st_ivas->nchan_transport, st_ivas->hEncoderConfig->ivas_format ); +#endif + ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); + + /* Determine if to separate some channels from the analysis */ + ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->hEncoderConfig->element_mode_init ), ivas_total_brate ); + + if ( ( error = ivas_masa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_mcmasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* core SCE, CPE reconfiguration happens later */ + } + + return error; +} + /*--------------------------------------------------------------------------* * ivas_mcmasa_enc_close() * @@ -405,30 +483,33 @@ ivas_error ivas_mcmasa_enc_open( *--------------------------------------------------------------------------*/ void ivas_mcmasa_enc_close( - MCMASA_ENC_HANDLE hMcMasa, /* i/o: encoder McMASA handle */ - const int32_t input_Fs /* i : input sampling rate */ + MCMASA_ENC_HANDLE *hMcMasa, /* i/o: encoder McMASA handle */ + const int32_t input_Fs /* i : input sampling rate */ ) { int16_t i, j; - if ( hMcMasa->separateChannelEnabled ) + if ( hMcMasa == NULL || *hMcMasa == NULL ) { - count_free( hMcMasa->delay_buffer_lfe[0] ); - count_free( hMcMasa->delay_buffer_lfe[1] ); + return; } - if ( hMcMasa->separateChannelEnabled ) + + if ( ( *hMcMasa )->separateChannelEnabled ) { + free( ( *hMcMasa )->delay_buffer_lfe[0] ); + free( ( *hMcMasa )->delay_buffer_lfe[1] ); + for ( i = 0; i < 2; i++ ) { - count_free( hMcMasa->lfeAnaRingBuffer[i] ); + free( ( *hMcMasa )->lfeAnaRingBuffer[i] ); } } - ivas_FB_mixer_close( &hMcMasa->hFbMixer, input_Fs ); + ivas_FB_mixer_close( &( *hMcMasa )->hFbMixer, input_Fs, 0 ); - if ( !hMcMasa->separateChannelEnabled ) + if ( !( *hMcMasa )->separateChannelEnabled ) { - ivas_FB_mixer_close( &hMcMasa->hFbMixerLfe, input_Fs ); + ivas_FB_mixer_close( &( *hMcMasa )->hFbMixerLfe, input_Fs, 0 ); } /* intensity 3-dim */ @@ -436,35 +517,36 @@ void ivas_mcmasa_enc_close( { for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { - count_free( hMcMasa->direction_vector_m[i][j] ); - hMcMasa->direction_vector_m[i][j] = NULL; + free( ( *hMcMasa )->direction_vector_m[i][j] ); + ( *hMcMasa )->direction_vector_m[i][j] = NULL; } - for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) + for ( j = 0; j < ( *hMcMasa )->no_col_avg_diff; j++ ) { - count_free( hMcMasa->buffer_intensity_real[i][j] ); - hMcMasa->buffer_intensity_real[i][j] = NULL; + free( ( *hMcMasa )->buffer_intensity_real[i][j] ); + ( *hMcMasa )->buffer_intensity_real[i][j] = NULL; } - count_free( hMcMasa->buffer_intensity_real[i] ); - hMcMasa->buffer_intensity_real[i] = NULL; + free( ( *hMcMasa )->buffer_intensity_real[i] ); + ( *hMcMasa )->buffer_intensity_real[i] = NULL; - count_free( hMcMasa->direction_vector_m[i] ); - hMcMasa->direction_vector_m[i] = NULL; + free( ( *hMcMasa )->direction_vector_m[i] ); + ( *hMcMasa )->direction_vector_m[i] = NULL; } - for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) + for ( j = 0; j < ( *hMcMasa )->no_col_avg_diff; j++ ) { - count_free( hMcMasa->buffer_intensity_real_vert[j] ); - hMcMasa->buffer_intensity_real_vert[j] = NULL; + free( ( *hMcMasa )->buffer_intensity_real_vert[j] ); + ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL; } - count_free( hMcMasa->buffer_intensity_real_vert ); - hMcMasa->buffer_intensity_real_vert = NULL; + free( ( *hMcMasa )->buffer_intensity_real_vert ); + ( *hMcMasa )->buffer_intensity_real_vert = NULL; - count_free( hMcMasa->buffer_energy ); - hMcMasa->buffer_energy = NULL; + free( ( *hMcMasa )->buffer_energy ); + ( *hMcMasa )->buffer_energy = NULL; - count_free( hMcMasa ); + free( ( *hMcMasa ) ); + ( *hMcMasa ) = NULL; return; } @@ -488,15 +570,12 @@ void ivas_mcmasa_enc( int16_t i, j, k; int16_t nBands = hMcMasa->nbands; int16_t nBlocks = MAX_PARAM_SPATIAL_SUBFRAMES; - uint8_t fixedDistance = 0; - float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - float separatedChannelSignal[L_FRAME48k]; /* Compute low frequency energy */ @@ -723,7 +802,6 @@ void ivas_mcmasa_param_est_enc( set_zero( coherentEnergyRatio[0], hMcMasa->nbands ); } - /* Copy current frame to memory for delay compensation */ for ( i = 0; i < numAnalysisChannels; i++ ) { @@ -892,9 +970,14 @@ void ivas_mcmasa_param_est_enc( 0, num_freq_bands, intensity_even_real ); - computeReferencePower_enc( hMcMasa->band_grouping, FoaEven_RealBuffer, FoaEven_ImagBuffer, reference_power[ts], + + computeReferencePower_enc( hMcMasa->band_grouping, + FoaEven_RealBuffer, + FoaEven_ImagBuffer, + reference_power[ts], 0, - num_freq_bands ); + num_freq_bands, + SBA_MODE_NONE ); /* Fill buffers of length "averaging_length" time slots for intensity and energy */ hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % hMcMasa->no_col_avg_diff ) + 1; /* averaging_length = 32 */ @@ -1135,6 +1218,7 @@ void ivas_mcmasa_param_est_enc( { numSubFramesForRatio = MAX_PARAM_SPATIAL_SUBFRAMES; } + for ( i = 0; i < numSubFramesForRatio; i++ ) { for ( j = 0; j < hMcMasa->nbands; j++ ) @@ -1148,6 +1232,86 @@ void ivas_mcmasa_param_est_enc( } +/*--------------------------------------------------------------------------* + * ivas_mcmasa_dmx_modify() + * + * + *--------------------------------------------------------------------------*/ + +void ivas_mcmasa_dmx_modify( + const int16_t n_samples, /* i : input frame length in samples */ + float dmx[][L_FRAME48k + NS2SA( 48000, IVAS_FB_ENC_DELAY_NS )], /* i/o: downmix signal to be transformed into another format. TODO: buffer size into define? */ + const int16_t n_chnls_dmx_old, /* i : number of downmix channels in the old format */ + const int16_t n_chnls_dmx_new ) /* i : number of downmix channels in the target format */ +{ + /* assumed data ordering in **dmx: [sce][cpe_chnl0][cpe_chnl1], i.e., [c][l][r] */ + int16_t i; + + assert( ( n_chnls_dmx_old == 1 || n_chnls_dmx_old == 2 || n_chnls_dmx_old == 3 ) && "Input downmix may contain only 1-3 channels." ); + assert( ( n_chnls_dmx_new == 1 || n_chnls_dmx_new == 2 || n_chnls_dmx_new == 3 ) && "Output downmix may contain only 1-3 channels." ); + + if ( n_chnls_dmx_old == n_chnls_dmx_new ) + { + /* same dmx layout -> nothing to do */ + return; + } + + if ( n_chnls_dmx_old == 1 ) + { + /* split mono energy into identical channels */ + for ( i = 0; i < n_samples; i++ ) + { + if ( n_chnls_dmx_new == 2 ) + { + dmx[1][i] = dmx[0][i] * INV_SQRT2; + dmx[2][i] = dmx[1][i]; + } + else if ( n_chnls_dmx_new == 3 ) + { + dmx[0][i] = dmx[0][i] * INV_SQRT3; + } + } + } + else if ( n_chnls_dmx_old == 2 ) + { + for ( i = 0; i < n_samples; i++ ) + { + if ( n_chnls_dmx_new == 1 ) + { + /* sum l and r */ + dmx[0][i] = dmx[1][i] + dmx[2][i]; + } + else if ( n_chnls_dmx_new == 3 ) + { + dmx[0][i] = 0.5f * ( dmx[1][i] + dmx[2][i] ); + dmx[1][i] = dmx[1][i] - dmx[0][i]; + dmx[2][i] = dmx[2][i] - dmx[0][i]; + } + } + } + else if ( n_chnls_dmx_old == 3 ) + { + for ( i = 0; i < n_samples; i++ ) + { + if ( n_chnls_dmx_new == 1 ) + { + /* sum all channels */ + dmx[0][i] = dmx[0][i] + dmx[1][i] + dmx[2][i]; + } + else if ( n_chnls_dmx_new == 2 ) + { + /* mix center into sides */ + dmx[0][i] *= INV_SQRT2; + dmx[1][i] += dmx[0][i]; + dmx[2][i] += dmx[0][i]; + } + } + } + + return; +} + + /*--------------------------------------------------------------------------* * Local functions *--------------------------------------------------------------------------*/ diff --git a/lib_enc/ivas_mct_core_enc.c b/lib_enc/ivas_mct_core_enc.c index de513c770e28b56819fa4b27e1e41803fe66e9c5..c2c2e284c2ae200d2146122d403ad4acf6f7c1aa 100644 --- a/lib_enc/ivas_mct_core_enc.c +++ b/lib_enc/ivas_mct_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------* @@ -51,34 +51,44 @@ *----------------------------------------------------------*/ static void FindChannelRatio( - MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ - Encoder_State **sts, /* i/o: encoder state structure */ - int16_t chBitRatios[MCT_MAX_CHANNELS], - const int16_t nchan /* i : number of channels */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ +#endif + Encoder_State **sts, /* i/o: encoder state structure */ + int16_t chBitRatios[MCT_MAX_CHANNELS], /* o : bit-disctribution channel ratios */ + const int16_t nChannels /* i : number of channels to be coded */ ) { - float sum_nrg = 0; - float chRatio; + float sum_nrg, chRatio; int16_t i; - float nrg[MCT_MAX_CHANNELS] = { 0 }; + float nrg[MCT_MAX_CHANNELS]; set_f( nrg, 0, MCT_MAX_CHANNELS ); - getChannelEnergies( sts, nrg, nchan ); + getChannelEnergies( sts, nrg, nChannels ); /*calculate total energy without LFE*/ - for ( i = 0; i < nchan; i++ ) + sum_nrg = 0; + for ( i = 0; i < nChannels; i++ ) { - if ( sts[i]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[i]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( sts[i]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[i]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { sum_nrg += nrg[i]; } } sum_nrg = 1.0f / max( sum_nrg, EPSILON ); - for ( i = 0; i < nchan; i++ ) + for ( i = 0; i < nChannels; i++ ) { - if ( sts[i]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[i]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( sts[i]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[i]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { chRatio = nrg[i] * sum_nrg; chBitRatios[i] = min( BITRATE_MCT_RATIO_RANGE - 1, max( 1, (uint16_t) ( BITRATE_MCT_RATIO_RANGE * chRatio + 0.5f ) ) ); @@ -87,15 +97,17 @@ static void FindChannelRatio( { chBitRatios[i] = 0; } +#ifndef ISSUE_24_CLEANUP_MCT_LFE else if ( hMCT->num_lfe ) { assert( sts[i]->mct_chan_mode == MCT_CHAN_MODE_LFE ); chBitRatios[i] = !hMCT->LFE_off; } +#endif } #ifdef DEBUG_MODE_MDCT - for ( i = 0; i < nchan; i++ ) + for ( i = 0; i < nChannels; i++ ) { dbgwrite( &chBitRatios[i], sizeof( int16_t ), 1, 1, "./res/chBitRatio" ); /* dbgwrite(&chRatio[i], sizeof(float),1,1,"./res/chRatio");*/ @@ -106,54 +118,48 @@ static void FindChannelRatio( } +/*----------------------------------------------------------* + * AdjustChannelRatios() + * + * adjust ratio of channels for bit distribution + *----------------------------------------------------------*/ + static void AdjustChannelRatios( - int16_t chBitRatios[MCT_MAX_CHANNELS], - const int16_t nchan /* i : number of channels */ -#ifdef FIX_I1_113 - , - const int32_t ivas_total_brate, - const int16_t nAvailBits, - const int16_t sba_order -#endif + int16_t chBitRatios[MCT_MAX_CHANNELS], /* o : bit-disctribution channel ratios */ + const int16_t nChannels, /* i/o: number of channels */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const int16_t nAvailBits, /* i : number of available bits */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { int16_t force_ch_bit_ratios[IVAS_SPAR_MAX_DMX_CHS]; -#ifdef FIX_I1_113 int32_t temp_brs[IVAS_SPAR_MAX_DMX_CHS]; -#endif float cur_ratio, tar_ratio, sum_ratio, sum_tar_ratio; int16_t ratio_diff, i; -#ifndef FIX_I1_113 - force_ch_bit_ratios[0] = 9; - force_ch_bit_ratios[1] = 7; - force_ch_bit_ratios[2] = 5; - force_ch_bit_ratios[3] = 3; -#else - ivas_spar_bitrate_dist( temp_brs, nAvailBits, , sba_order, 3 ); + ivas_spar_bitrate_dist( temp_brs, nAvailBits, ivas_total_brate, sba_order, (int16_t) FB ); sum_ratio = 0.0f; - for ( i = 0; i < nchan; i++ ) + for ( i = 0; i < nChannels; i++ ) { sum_ratio += (float) temp_brs[i]; } - for ( i = 0; i < nchan; i++ ) + for ( i = 0; i < nChannels; i++ ) { cur_ratio = temp_brs[i] / sum_ratio; force_ch_bit_ratios[i] = min( BITRATE_MCT_RATIO_RANGE - 1, max( 1, (uint16_t) ( BITRATE_MCT_RATIO_RANGE * cur_ratio + 0.5f ) ) ); } -#endif /* adjust the ratios further based on received chBitRatios[]*/ ratio_diff = 0; sum_ratio = 0.0f; sum_tar_ratio = 0.0f; - for ( i = 0; i < nchan; i++ ) + for ( i = 0; i < nChannels; i++ ) { sum_ratio += (float) chBitRatios[i]; sum_tar_ratio += (float) force_ch_bit_ratios[i]; } - for ( i = 3; i < nchan; i++ ) + for ( i = 3; i < nChannels; i++ ) { cur_ratio = (float) chBitRatios[i] / sum_ratio; tar_ratio = (float) force_ch_bit_ratios[i] / sum_tar_ratio; @@ -164,29 +170,30 @@ static void AdjustChannelRatios( assert( chBitRatios[i] < ( BITRATE_MCT_RATIO_RANGE - 1 ) ); ratio_diff += force_ch_bit_ratios[i] - chBitRatios[i]; } - for ( i = 0; i < min( 3, nchan ); i++ ) + + for ( i = 0; i < min( 3, nChannels ); i++ ) { assert( force_ch_bit_ratios[i] >= 0 ); chBitRatios[i] = min( BITRATE_MCT_RATIO_RANGE - 1, force_ch_bit_ratios[i] ); } chBitRatios[1] += ratio_diff; -#ifdef FIX_I1_113 /* make sure final ratios are within range*/ sum_ratio = 0.0f; - for ( i = 0; i < nchan; i++ ) + for ( i = 0; i < nChannels; i++ ) { sum_ratio += (float) chBitRatios[i]; } - for ( i = 0; i < nchan; i++ ) + for ( i = 0; i < nChannels; i++ ) { cur_ratio = chBitRatios[i] / sum_ratio; chBitRatios[i] = min( BITRATE_MCT_RATIO_RANGE - 1, max( 1, (uint16_t) ( BITRATE_MCT_RATIO_RANGE * cur_ratio + 0.5f ) ) ); } -#endif return; } + + /*-------------------------------------------------------------------* * ivas_mct_core_enc() * @@ -201,14 +208,10 @@ void ivas_mct_core_enc( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ const int16_t switch_bw, /* i : flag bandwidth switch occurance */ const int16_t lfe_bits, /* i : bits spent for LFE */ - const SBA_MODE sba_mode /* i : SBA mode */ -#ifdef FIX_I1_113 - , - const int16_t sba_order -#endif + const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { - int16_t ch, nSubframes, L_subframeTCX; + int16_t ch, ch_core, nSubframes, L_subframeTCX; int16_t i, cpe_id, n, nAvailBits; int16_t nCPE; float *orig_spectrum[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ @@ -237,7 +240,7 @@ void ivas_mct_core_enc( static FILE *f_bit_split = 0; #endif - wmops_sub_start( "mct_encoding" ); + push_wmops( "mct_encoding" ); /*--------------------------------------------------------------* * Initialization @@ -246,6 +249,8 @@ void ivas_mct_core_enc( total_side_bits = 0; nCPE = nChannels / CPE_CHANNELS; + + /*in case of odd number of channels*/ if ( ( nCPE * CPE_CHANNELS ) != nChannels ) { nCPE++; @@ -264,7 +269,11 @@ void ivas_mct_core_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { sts[i] = hCPE[cpe_id]->hCoreCoder[ch]; - if ( hCPE[cpe_id]->hCoreCoder[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE || hCPE[cpe_id]->hCoreCoder[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( hCPE[cpe_id]->hCoreCoder[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || hCPE[cpe_id]->hCoreCoder[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { i++; continue; @@ -285,7 +294,7 @@ void ivas_mct_core_enc( for ( ch = 0; ch < (int16_t) ( hMCT->nchan_out_woLFE * 0.5 ); ch++ ) { - int16_t ch_core = ch * CPE_CHANNELS; + ch_core = ch * CPE_CHANNELS; if ( switch_bw ) { @@ -313,7 +322,11 @@ void ivas_mct_core_enc( { st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && hMCT->LFE_off ) || st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && hMCT->LFE_off ) || +#endif + st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -341,7 +354,11 @@ void ivas_mct_core_enc( for ( ch = 0; ch < nChannels; ch++ ) { - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -388,7 +405,11 @@ void ivas_mct_core_enc( for ( ch = 0; ch < nChannels; ch++ ) { st = sts[ch]; - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -420,7 +441,11 @@ void ivas_mct_core_enc( for ( ch = 0; ch < nChannels; ch++ ) { st = sts[ch]; - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -441,7 +466,11 @@ void ivas_mct_core_enc( for ( ch = 0; ch < nChannels; ch++ ) { st = sts[ch]; - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -454,7 +483,11 @@ void ivas_mct_core_enc( { st = sts[ch]; - if ( ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) && hMCT->LFE_off ) || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) && hMCT->LFE_off ) || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -469,15 +502,11 @@ void ivas_mct_core_enc( write_mct_bitstream( sts, hMCT, nChannels ); - FindChannelRatio( hMCT, sts, chBitRatios, nChannels ); - -#ifndef FIX_I1_113 - if ( hMCT->hbr_mct ) - { - assert( ivas_total_brate >= IVAS_256k ); - AdjustChannelRatios( chBitRatios, nChannels ); - } + FindChannelRatio( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + hMCT, #endif + sts, chBitRatios, nChannels ); nAvailBits = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC ) - NBITS_BWIDTH - hMCT->nBitsMCT - lfe_bits ); @@ -491,10 +520,7 @@ void ivas_mct_core_enc( else if ( ivas_format == SBA_FORMAT ) { nAvailBits -= IVAS_FORMAT_SIGNALING_NBITS_SBA; - if ( sba_mode != SBA_MODE_SPAR || ivas_total_brate >= IVAS_256k ) - { - nAvailBits -= SBA_ORDER_BITS + SBA_PLANAR_BITS; - } + nAvailBits -= SBA_ORDER_BITS + SBA_PLANAR_BITS; } for ( cpe_id = 0, i = 0; cpe_id < nCPE; cpe_id++ ) @@ -508,29 +534,39 @@ void ivas_mct_core_enc( /*substract bits needed for the bitrate ratios */ for ( ch = 0; ch < nChannels; ch++ ) { - if ( ( ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) && hMCT->LFE_off ) || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) && hMCT->LFE_off ) || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } nAvailBits -= NBBITS_MCT_RATIO; } - nAvailBits -= total_side_bits + ( hMCT->num_lfe ? 1 : 0 ) + hMCT->nchan_out_woLFE; /* if MC 1 extra bit that was initially send to signal LFE_off */ + nAvailBits -= total_side_bits +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + ( hMCT->num_lfe ? 1 : 0 ) +#endif + + hMCT->nchan_out_woLFE; /* if MC 1 extra bit that was initially send to signal LFE_off */ #ifdef DEBUG_MODE_MDCT dbgwrite( &nAvailBits, sizeof( int16_t ), 1, 1, "./res/availBits" ); #endif -#ifdef FIX_I1_113 if ( hMCT->hbr_mct ) { assert( ivas_total_brate >= IVAS_256k ); AdjustChannelRatios( chBitRatios, nChannels, ivas_total_brate, nAvailBits, sba_order ); } -#endif for ( ch = 0; ch < nChannels; ch++ ) { - if ( ( ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) && hMCT->LFE_off ) || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) && hMCT->LFE_off ) || +#endif + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } @@ -553,15 +589,18 @@ void ivas_mct_core_enc( { continue; } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( !( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) && hMCT->LFE_off ) ) /* indicates LFE with no content */ { +#endif st->total_brate = ( st->bits_frame_channel + st->side_bits_frame_channel ) * FRAMES_PER_SEC; #ifdef DEBUGGING total_brate += st->total_brate; #endif +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif } #ifdef DEBUGGING if ( hCPE[cpe_id]->hMetaData != NULL ) @@ -572,20 +611,16 @@ void ivas_mct_core_enc( } #ifdef DEBUGGING - if ( ivas_format == SBA_FORMAT && sba_mode == SBA_MODE_SPAR && ivas_total_brate < IVAS_256k ) - { - format_bits = IVAS_FORMAT_SIGNALING_NBITS_SBA; - } - else - { - format_bits = ( ivas_format == MC_FORMAT ? IVAS_FORMAT_SIGNALING_NBITS + MC_LS_SETUP_BITS : IVAS_FORMAT_SIGNALING_NBITS_SBA + SBA_ORDER_BITS + SBA_PLANAR_BITS ); - } - - mct_bits += hMCT->nBitsMCT + ( hMCT->num_lfe ? 1 : 0 ) + hMCT->nchan_out_woLFE; + format_bits = ( ivas_format == MC_FORMAT ? IVAS_FORMAT_SIGNALING_NBITS + MC_LS_SETUP_BITS : IVAS_FORMAT_SIGNALING_NBITS_SBA + SBA_ORDER_BITS + SBA_PLANAR_BITS ); + mct_bits += hMCT->nBitsMCT +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + ( hMCT->num_lfe ? 1 : 0 ) +#endif + + hMCT->nchan_out_woLFE; assert( ( total_brate + ( NBITS_BWIDTH + format_bits + mct_bits + sba_meta + lfe_bits ) * FRAMES_PER_SEC ) == ivas_total_brate ); #endif - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index 85c3ed0afcf3651dd918bb125c642f533c324d09..75191d0a412361b4b8732f3472e12cec085a3ddc 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,9 +41,110 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" + + +/*-----------------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------------*/ + +static ivas_error ivas_mc_enc_reconfig( Encoder_Struct *st_ivas, const int16_t last_mc_mode ); +/*-------------------------------------------------------------------* + * set_mct_enc_params() + * + * Set hMCT handle parameters + *-------------------------------------------------------------------*/ + +static void set_mct_enc_params( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + const int32_t ivas_total_brate, /* i : IVAS total bitrate */ + const SBA_MODE sba_mode, /* i : SBA mode */ + const uint16_t b_nchan_change /* i : flag indicating different channel count */ +) +{ + int16_t n; + + if ( b_nchan_change ) + { + hMCT->currBlockDataCnt = 0; + + /*Initialize bits required to signal channel-pair index*/ + hMCT->bitsChannelPairIndex = max( 1, (int16_t) ( floor( ( log( hMCT->nchan_out_woLFE * ( hMCT->nchan_out_woLFE - 1 ) / 2 - 1 ) / log( 2. ) ) ) + 1 ) ); + + set_s( hMCT->lowE_ch, 0, MCT_MAX_CHANNELS ); + + for ( n = 0; n < MCT_MAX_CHANNELS; n++ ) + { + set_f( hMCT->lastxCorrMatrix[n], 0, MCT_MAX_CHANNELS ); + } + } + + hMCT->hbr_mct = 0; + if ( sba_mode == SBA_MODE_SPAR && ivas_total_brate >= IVAS_256k ) + { + hMCT->hbr_mct = 1; + } + + return; +} + +/*-------------------------------------------------------------------* + * map_input_to_cpe_channels() + * + * for MC_MODE map input channels to cpe channels + * mid channel (ch==2) is mapped to last odd-channel CPE + * all channels after LFE are mapped to cpe_id=1 and onwards + * E.g. for 5_1 and for 3 CPEs: + * cpe_id 0: L=data[0] R=data[1] + * cpe_id 1: L=data[4] R=data[5] + * cpe_id 2: L=data[2] (mid) R=NULL + *-------------------------------------------------------------------*/ +#ifdef ISSUE_24_CLEANUP_MCT_LFE +static void map_input_to_cpe_channels( + const Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + float *pdata[MAX_INPUT_CHANNELS], /* o: mapped input pointers */ + float data[MCT_MAX_CHANNELS][L_FRAME48k] /* i: input channel data */ +) +{ + int16_t i, n; + + i = 0; + + for ( n = 0; n < LFE_CHANNEL - 1; n++ ) + { + pdata[i] = data[n]; + i++; + } + + if ( st_ivas->hEncoderConfig->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) + { + for ( n = LFE_CHANNEL + 1; n < st_ivas->nchan_transport; n++ ) + { + pdata[i] = data[n]; + i++; + } + pdata[i] = data[LFE_CHANNEL - 1]; + } + else + { + for ( ; n < st_ivas->nchan_transport; n++ ) + { + pdata[i] = data[n]; + i++; + } + } + + /* odd channel CPE*/ + if ( ( st_ivas->nchan_transport < st_ivas->nCPE * CPE_CHANNELS ) || ( st_ivas->mc_mode == MC_MODE_MCT && st_ivas->hMCT->nchan_out_woLFE < st_ivas->nCPE * CPE_CHANNELS ) ) + { + pdata[st_ivas->nCPE * CPE_CHANNELS - 1] = NULL; + } + + return; +} +#endif /*-------------------------------------------------------------------* * ivas_mct_enc() * @@ -67,10 +168,13 @@ ivas_error ivas_mct_enc( int16_t max_bwidth; int32_t ivas_total_brate; ivas_error error; +#ifdef ISSUE_24_CLEANUP_MCT_LFE + float *pdata[MAX_INPUT_CHANNELS]; +#endif error = IVAS_ERR_OK; - wmops_sub_start( "ivas_mct_enc" ); + push_wmops( "ivas_mct_enc" ); /* Initialization */ hMCT = st_ivas->hMCT; @@ -83,7 +187,7 @@ ivas_error ivas_mct_enc( #ifdef DEBUG_FORCE_MCT_CP if ( ivas_format == MC_FORMAT ) { - assert( "Debugging switch works only with SBA modes" ); + assert( !"Debugging switch works only with SBA modes" ); } #endif @@ -96,11 +200,22 @@ ivas_error ivas_mct_enc( hMCT->p_orig_spectrum_long[cpe_id][n] = orig_spectrum_long[cpe_id][n]; hCPE->hCoreCoder[n]->input_bwidth = hCPE->hCoreCoder[n]->last_input_bwidth; /* updated in BWD */ hCPE->hCoreCoder[n]->bwidth = hCPE->hCoreCoder[n]->last_bwidth; /* updated in BWD */ +#ifdef ISSUE_24_CLEANUP_MCT_LFE + /* reset channel mode from previous state*/ + if ( ( hCPE->cpe_id * CPE_CHANNELS + n ) >= hMCT->nchan_out_woLFE ) + { + hCPE->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + } + else + { + hCPE->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } +#endif } } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->LFE_off = 1; /* disable LFE coding by default for the moment */ - +#endif /* reconfiguration in case of bitrate switching */ if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) { @@ -116,39 +231,57 @@ ivas_error ivas_mct_enc( /* set coded audio band-width */ switch_bw = set_bw_mct( st_ivas->hCPE, st_ivas->nCPE ); +#ifdef ISSUE_24_CLEANUP_MCT_LFE + /*for MC and MCT remove pointer to LFE input that has been processed seperately */ + map_input_to_cpe_channels( st_ivas, pdata, data ); +#endif /* pre-processing */ for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { +#ifdef ISSUE_24_CLEANUP_MCT_LFE + if ( ( error = ivas_cpe_enc( st_ivas, cpe_id, pdata[cpe_id * CPE_CHANNELS], pdata[cpe_id * CPE_CHANNELS + 1], input_frame, nb_bits_metadata ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_cpe_enc( st_ivas, cpe_id, data[cpe_id * CPE_CHANNELS], data[cpe_id * CPE_CHANNELS + 1], input_frame, nb_bits_metadata ) ) != IVAS_ERR_OK ) +#endif { return error; } } /* joint MCT encoding */ - ivas_mct_core_enc( ivas_format, hMCT, st_ivas->hCPE, hMCT->nchan_out_woLFE + hMCT->num_lfe, ivas_total_brate, switch_bw, - ivas_format == MC_FORMAT ? (int16_t) st_ivas->hLFE->lfe_bits : 0, st_ivas->sba_mode -#ifdef FIX_I1_113 - , - st_ivas->hEncoderConfig->sba_order + ivas_mct_core_enc( ivas_format, hMCT, st_ivas->hCPE, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + hMCT->nchan_out_woLFE + hMCT->num_lfe +#else + hMCT->nchan_out_woLFE #endif - ); + , + ivas_total_brate, switch_bw, + ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) ? (int16_t) st_ivas->hLFE->lfe_bits : 0, + st_ivas->hEncoderConfig->sba_order ); /* Spectrum quantization and coding */ for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { hCPE = st_ivas->hCPE[cpe_id]; - ivas_mdct_quant_coder( hCPE, hMCT->LFE_off, hMCT->tnsBits[cpe_id], hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], 1 ); + ivas_mdct_quant_coder( hCPE, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + hMCT->LFE_off, +#endif + hMCT->tnsBits[cpe_id], hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], 1 ); /* update input samples buffer (as done in ivas_cpe_enc() for other than MCT coding) */ for ( n = 0; n < CPE_CHANNELS; n++ ) { mvr2r( hCPE->hCoreCoder[n]->input, hCPE->hCoreCoder[n]->old_input_signal, input_frame ); + + /* common encoder updates */ + updt_enc_common( hCPE->hCoreCoder[n] ); } } - wmops_sub_end(); + pop_wmops(); return error; } @@ -178,7 +311,7 @@ ivas_error create_mct_enc( * Allocate MCT handle *-----------------------------------------------------------------*/ - if ( ( hMCT = (MCT_ENC_HANDLE) count_malloc( sizeof( MCT_ENC_DATA ) ) ) == NULL ) + if ( ( hMCT = (MCT_ENC_HANDLE) malloc( sizeof( MCT_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT\n" ) ); } @@ -191,28 +324,30 @@ ivas_error create_mct_enc( if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) { hMCT->nchan_out_woLFE = st_ivas->hEncoderConfig->nchan_inp - 1; /* LFE channel is coded separately */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->num_lfe = TRUE; +#endif } - else if ( ivas_format == SBA_FORMAT && st_ivas->hSpar ) - { - hMCT->nchan_out_woLFE = ivas_get_spar_num_TCs( ivas_total_brate, st_ivas->hEncoderConfig->sba_order ); - - hMCT->num_lfe = FALSE; - } - else if ( ivas_format == SBA_FORMAT && st_ivas->hDirAC ) + else if ( ivas_format == SBA_FORMAT ) { - hMCT->nchan_out_woLFE = ivas_dirac_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->sba_order, st_ivas->hEncoderConfig->sba_planar ); + hMCT->nchan_out_woLFE = ivas_get_sba_num_TCs( ivas_total_brate, st_ivas->sba_analysis_order ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->num_lfe = FALSE; +#endif } else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC ) { hMCT->nchan_out_woLFE = ivas_param_mc_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->mc_input_setup ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->num_lfe = FALSE; +#endif } else if ( ivas_format == SBA_FORMAT ) { - hMCT->nchan_out_woLFE = ivas_sba_get_nchan( st_ivas->hEncoderConfig->sba_order, st_ivas->hEncoderConfig->sba_planar ); + hMCT->nchan_out_woLFE = ivas_sba_get_nchan( st_ivas->sba_analysis_order, st_ivas->hEncoderConfig->sba_planar ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->num_lfe = FALSE; +#endif } else { @@ -221,21 +356,27 @@ ivas_error create_mct_enc( cp_bitrate = ivas_total_brate / hMCT->nchan_out_woLFE * CPE_CHANNELS; - /* indicate LFE for appropriate core-coder channel */ for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { for ( n = 0; n < CPE_CHANNELS; n++ ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ( hMCT->num_lfe > 0 ) && ( ( n + cpe_id * CPE_CHANNELS ) == LFE_CHANNEL ) ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_LFE; } +#endif } } /* in case we have an uneven number of transport channels, indicate last channel ID as inactive */ - if ( ( hMCT->nchan_out_woLFE + hMCT->num_lfe ) % 2 ) + if ( ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ) % + 2 ) { st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; } @@ -245,9 +386,10 @@ ivas_error create_mct_enc( for ( n = 0; n < max_blocks; n++ ) { + assert( st_ivas->hEncoderConfig->element_mode_init == IVAS_CPE_MDCT && "MCT is not supported for other stereo modes" ); - if ( ( hMCT->hBlockData[n] = (MCT_BLOCK_DATA_HANDLE) count_malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n] = (MCT_BLOCK_DATA_HANDLE) malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT block data structure\n" ) ); } @@ -261,7 +403,7 @@ ivas_error create_mct_enc( * MDCT stereo initialization *-----------------------------------------------------------------*/ - if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); } @@ -281,22 +423,7 @@ ivas_error create_mct_enc( * Initializations *-----------------------------------------------------------------*/ - hMCT->currBlockDataCnt = 0; - - /*Initialize bits required to signal channel-pair index*/ - hMCT->bitsChannelPairIndex = max( 1, (int16_t) ( floor( ( log( hMCT->nchan_out_woLFE * ( hMCT->nchan_out_woLFE - 1 ) / 2 - 1 ) / log( 2. ) ) ) + 1 ) ); - - set_s( hMCT->lowE_ch, 0, MCT_MAX_CHANNELS ); - - for ( n = 0; n < MCT_MAX_CHANNELS; n++ ) - { - set_f( hMCT->lastxCorrMatrix[n], 0, MCT_MAX_CHANNELS ); - } - hMCT->hbr_mct = 0; - if ( st_ivas->sba_mode == SBA_MODE_SPAR && ivas_total_brate >= IVAS_256k ) - { - hMCT->hbr_mct = 1; - } + set_mct_enc_params( hMCT, ivas_total_brate, st_ivas->sba_mode, 1 ); st_ivas->hMCT = hMCT; @@ -335,17 +462,23 @@ ivas_error mct_enc_reconfigure( if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) { hMCT->nchan_out_woLFE = st_ivas->hEncoderConfig->nchan_inp - 1; /* LFE channel is coded separately */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->num_lfe = TRUE; +#endif } - else if ( ivas_format == SBA_FORMAT && st_ivas->hDirAC ) + else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC ) { - hMCT->nchan_out_woLFE = ivas_dirac_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->sba_order, st_ivas->hEncoderConfig->sba_planar ); + hMCT->nchan_out_woLFE = ivas_param_mc_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->mc_input_setup ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->num_lfe = FALSE; +#endif } else if ( ivas_format == SBA_FORMAT ) { - hMCT->nchan_out_woLFE = ivas_sba_get_nchan( st_ivas->hEncoderConfig->sba_order, st_ivas->hEncoderConfig->sba_planar ); + hMCT->nchan_out_woLFE = st_ivas->nchan_transport; +#ifndef ISSUE_24_CLEANUP_MCT_LFE hMCT->num_lfe = FALSE; +#endif } else { @@ -355,21 +488,28 @@ ivas_error mct_enc_reconfigure( cp_bitrate = ivas_total_brate / hMCT->nchan_out_woLFE * CPE_CHANNELS; - /* indicate LFE for appropriate core-coder channel */ for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) { + st_ivas->hCPE[cpe_id]->element_brate = cp_bitrate; for ( n = 0; n < CPE_CHANNELS; n++ ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ( hMCT->num_lfe > 0 ) && ( ( n + cpe_id * CPE_CHANNELS ) == LFE_CHANNEL ) ) { st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_LFE; } +#endif } } /* in case we have an uneven number of transport channels, indicate last channel ID as inactive */ - if ( ( hMCT->nchan_out_woLFE + hMCT->num_lfe ) % 2 ) + if ( ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ) % + 2 ) { st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; } @@ -386,10 +526,19 @@ ivas_error mct_enc_reconfigure( st->total_brate = st_ivas->hCPE[cpe_id]->element_brate; - if ( !( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) ) + if ( !( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) || +#endif + ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) ) { st->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[cpe_id]->element_brate / FRAMES_PER_SEC ); - st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_mode, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); if ( st->igf ) { IGFEncSetMode( st->hIGFEnc, st_ivas->hCPE[cpe_id]->element_brate, st->bwidth, st->element_mode, st->rf_mode ); @@ -412,7 +561,7 @@ ivas_error mct_enc_reconfigure( if ( hMCT->hBlockData[n] == NULL ) { mem_init = 1; - if ( ( hMCT->hBlockData[n] = (MCT_BLOCK_DATA_HANDLE) count_malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n] = (MCT_BLOCK_DATA_HANDLE) malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT block data structure\n" ) ); } @@ -426,7 +575,7 @@ ivas_error mct_enc_reconfigure( * MDCT stereo initialization *-----------------------------------------------------------------*/ - if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + if ( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); } @@ -446,11 +595,11 @@ ivas_error mct_enc_reconfigure( { if ( hMCT->hBlockData[n]->hStereoMdct != NULL ) { - count_free( hMCT->hBlockData[n]->hStereoMdct ); + free( hMCT->hBlockData[n]->hStereoMdct ); hMCT->hBlockData[n]->hStereoMdct = NULL; } - count_free( hMCT->hBlockData[n] ); + free( hMCT->hBlockData[n] ); hMCT->hBlockData[n] = NULL; } } @@ -459,19 +608,7 @@ ivas_error mct_enc_reconfigure( * Initializations *-----------------------------------------------------------------*/ - if ( b_nchan_change ) - { - hMCT->currBlockDataCnt = 0; - /*Initialize bits required to signal channel-pair index*/ - hMCT->bitsChannelPairIndex = max( 1, (int16_t) ( floor( ( log( hMCT->nchan_out_woLFE * ( hMCT->nchan_out_woLFE - 1 ) / 2 - 1 ) / log( 2. ) ) ) + 1 ) ); - - set_s( hMCT->lowE_ch, 0, MCT_MAX_CHANNELS ); - - for ( n = 0; n < MCT_MAX_CHANNELS; n++ ) - { - set_f( hMCT->lastxCorrMatrix[n], 0, MCT_MAX_CHANNELS ); - } - } + set_mct_enc_params( hMCT, ivas_total_brate, st_ivas->sba_mode, b_nchan_change ); return IVAS_ERR_OK; } @@ -484,29 +621,35 @@ ivas_error mct_enc_reconfigure( *-------------------------------------------------------------------------*/ void ivas_mct_enc_close( - MCT_ENC_HANDLE hMCT /* i/o: MCT encoder structure */ + MCT_ENC_HANDLE *hMCT /* i/o: MCT encoder structure */ ) { int16_t n, maxBlocks; - maxBlocks = hMCT->nchan_out_woLFE / 2; + if ( hMCT == NULL || *hMCT == NULL ) + { + return; + } + + maxBlocks = ( *hMCT )->nchan_out_woLFE / 2; for ( n = 0; n < maxBlocks; n++ ) { - if ( hMCT->hBlockData[n] != NULL ) + if ( ( *hMCT )->hBlockData[n] != NULL ) { - if ( hMCT->hBlockData[n]->hStereoMdct != NULL ) + if ( ( *hMCT )->hBlockData[n]->hStereoMdct != NULL ) { - count_free( hMCT->hBlockData[n]->hStereoMdct ); - hMCT->hBlockData[n]->hStereoMdct = NULL; + free( ( *hMCT )->hBlockData[n]->hStereoMdct ); + ( *hMCT )->hBlockData[n]->hStereoMdct = NULL; } - count_free( hMCT->hBlockData[n] ); - hMCT->hBlockData[n] = NULL; + free( ( *hMCT )->hBlockData[n] ); + ( *hMCT )->hBlockData[n] = NULL; } } - count_free( hMCT ); + free( ( *hMCT ) ); + ( *hMCT ) = NULL; return; } @@ -542,8 +685,243 @@ ivas_error ivas_mc_enc_config( /* MC format switching */ if ( st_ivas->hEncoderConfig->last_ivas_total_brate != st_ivas->hEncoderConfig->ivas_total_brate || st_ivas->mc_mode != last_mc_mode ) { - /*ivas_mc_enc_reconfigure( st_ivas );*/ - return IVAS_ERROR( IVAS_ERR_RECONFIGURE_NOT_SUPPORTED, "Error: MC format switching not supported yet!!!\n\n" ); + if ( ( error = ivas_mc_enc_reconfig( st_ivas, last_mc_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return error; +} + + +/*------------------------------------------------------------------------- + * ivas_mc_enc_reconfig() + * + * Reconfigure the MC format encoder + *-------------------------------------------------------------------------*/ + +static ivas_error ivas_mc_enc_reconfig( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const int16_t last_mc_mode /* i: last frame mc mode */ +) +{ + int16_t nchan_transport_old, nSCE_old, nCPE_old; + ivas_error error; + int32_t new_brate_SCE, new_brate_CPE; + + error = IVAS_ERR_OK; + + nchan_transport_old = st_ivas->nchan_transport; + nSCE_old = st_ivas->nSCE; + nCPE_old = st_ivas->nCPE; + + /*-----------------------------------------------------------------* + * Reconfigure MC modules + *-----------------------------------------------------------------*/ + + if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + st_ivas->nSCE = 0; + st_ivas->nCPE = st_ivas->hEncoderConfig->nchan_inp / 2; + + st_ivas->nchan_transport = ivas_mc_ls_setup_get_num_channels( st_ivas->hEncoderConfig->mc_input_setup ); + + if ( last_mc_mode != MC_MODE_MCT ) + { + /* create LFE handle */ + if ( ( error = ivas_create_lfe_enc( &st_ivas->hLFE, st_ivas->hEncoderConfig->input_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*De-allocate handles for other MC modes*/ + ivas_param_mc_enc_close( &( st_ivas->hParamMC ), st_ivas->hEncoderConfig->input_Fs ); + + /* De-allocate McMasa-related handles */ + ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); + +#ifdef FIX_350_MASA_DELAY_COMP + ivas_masa_enc_close( &( st_ivas->hMasa ) ); +#else + ivas_masa_enc_close( &( st_ivas->hMasa ), nchan_transport_old, MC_FORMAT ); +#endif + + ivas_qmetadata_close( &st_ivas->hQMetaData ); + } + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + { + if ( last_mc_mode != MC_MODE_PARAMMC ) + { + if ( ( error = ivas_param_mc_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_param_mc_enc_reconfig( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* De-allocate McMasa-related handles */ + ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); + + if ( st_ivas->hMasa != NULL ) + { +#ifdef FIX_350_MASA_DELAY_COMP + ivas_masa_enc_close( &( st_ivas->hMasa ) ); +#else + ivas_masa_enc_close( &( st_ivas->hMasa ), nchan_transport_old, MC_FORMAT ); +#endif + st_ivas->hMasa = NULL; + } + + ivas_qmetadata_close( &st_ivas->hQMetaData ); + + /* De-allocate MCT handle if last mode was MCT */ + if ( last_mc_mode == MC_MODE_MCT && st_ivas->nchan_transport <= CPE_CHANNELS ) + { + ivas_mct_enc_close( &( st_ivas->hMCT ) ); + } + + if ( last_mc_mode == MC_MODE_MCT && st_ivas->hLFE != NULL ) + { + /* LFE handle */ + ivas_lfe_enc_close( &( st_ivas->hLFE ) ); + } + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + if ( last_mc_mode != MC_MODE_MCMASA ) + { + ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->hEncoderConfig->element_mode_init ), st_ivas->hEncoderConfig->ivas_total_brate ); + + if ( ( error = ivas_qmetadata_open( &( st_ivas->hQMetaData ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_masa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_mcmasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + /* reconfigure McMASA instance */ + if ( ( error = ivas_mcmasa_enc_reconfig( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + ivas_param_mc_enc_close( &( st_ivas->hParamMC ), st_ivas->hEncoderConfig->input_Fs ); + + if ( last_mc_mode == MC_MODE_MCT ) + { + /* LFE handle */ + ivas_lfe_enc_close( &( st_ivas->hLFE ) ); + + ivas_mct_enc_close( &( st_ivas->hMCT ) ); + } + } + + if ( st_ivas->mc_mode != MC_MODE_MCMASA ) + { + if ( st_ivas->nchan_transport == 1 ) + { + st_ivas->hEncoderConfig->element_mode_init = IVAS_SCE; + } + else + { + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + } + } + + /*-----------------------------------------------------------------* + * Reconfigure core coder + *-----------------------------------------------------------------*/ + + /* special case: MCT->ParamMC with more than 2 TC, CPE 1 stays, but has the wrong mct_chan_mode in channel 1 + and might have IGF and TranDet static memory not allocated and the bit stream index list not set, + set correct mct_chan_mode and init missing static mem + do it here since it is _very_ MC specific */ + if ( last_mc_mode == MC_MODE_MCT && st_ivas->mc_mode == MC_MODE_PARAMMC && st_ivas->nchan_transport > CPE_CHANNELS ) + { + Encoder_State *st = st_ivas->hCPE[1]->hCoreCoder[1]; + + if ( st_ivas->nchan_transport == 3 ) + { + st->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + } + else + { + st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } + + if ( st->hTranDet == NULL ) + { + if ( ( st->hTranDet = (TRAN_DET_HANDLE) malloc( sizeof( TRAN_DET_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Transient Detection\n" ) ); + } + + InitTransientDetection( (int16_t) ( st->input_Fs / FRAMES_PER_SEC ), NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), st->hTranDet, 0 ); + } + + if ( st->hIGFEnc == NULL ) + { + if ( ( st->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n" ) ); + } + } + + st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + /* set last core to TCX20 */ + st->last_core = TCX_20_CORE; + } +#ifndef ISSUE_24_CLEANUP_MCT_LFE + else if ( last_mc_mode == MC_MODE_PARAMMC && st_ivas->mc_mode == MC_MODE_MCT && nchan_transport_old > 2 ) + { +#ifdef DEBUGGING + assert( st_ivas->hCPE[1] != NULL ); +#endif + st_ivas->hCPE[1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_LFE; + } +#endif + if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + ivas_mcmasa_split_brate( st_ivas->hMcMasa->separateChannelEnabled, st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nSCE, st_ivas->nCPE, &new_brate_SCE, &new_brate_CPE ); + } + else if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + new_brate_SCE = 0; + new_brate_CPE = ( st_ivas->hEncoderConfig->ivas_total_brate / ( st_ivas->nchan_transport - 1 ) ) * CPE_CHANNELS; + } + else + { + new_brate_SCE = 0; /*st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport;*/ + new_brate_CPE = ( st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS; + } + + if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, new_brate_SCE, new_brate_CPE, last_mc_mode ) ) != IVAS_ERR_OK ) + { + return error; } return error; diff --git a/lib_enc/ivas_mct_enc_mct.c b/lib_enc/ivas_mct_enc_mct.c index 62ff9be888b91c8d274957f598f37d20a41f0075..9c0e43caa0291367f263909b8362439b0f5d4c60 100644 --- a/lib_enc/ivas_mct_enc_mct.c +++ b/lib_enc/ivas_mct_enc_mct.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,7 @@ #include "ivas_cnst.h" #include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include #define SPAR_CORR_THRES 0.9f @@ -62,7 +62,11 @@ void getChannelEnergies( for ( ch = 0; ch < nchan; ch++ ) { st = sts[ch]; - if ( st->mct_chan_mode != MCT_CHAN_MODE_IGNORE && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( st->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && st->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; L_subframe = st->hTcxEnc->L_frameTCX / nSubframes; @@ -156,7 +160,11 @@ static void getCorrelationMatrix( int16_t ch1, ch2, n, nchan; float tmp; - nchan = hMCT->nchan_out_woLFE + hMCT->num_lfe; + nchan = hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ; /* correlation */ for ( ch1 = 0; ch1 < nchan; ch1++ ) @@ -166,8 +174,12 @@ static void getCorrelationMatrix( xCorrMatrix[ch1][ch2] = 0; if ( sts[ch1]->core == sts[ch2]->core && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && - sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_LFE && - sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_LFE && + sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { int16_t nSubframes = ( sts[ch1]->core == TCX_20_CORE ? 1 : NB_DIV ); int16_t L_subframe = sts[ch1]->hTcxEnc->L_frameTCX / nSubframes; @@ -225,9 +237,19 @@ static void getBestCorrelation( *_ch2 = -1; *max_corr = 0.f; - for ( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE + hMCT->num_lfe ); ch1++ ) + for ( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); + ch1++ ) { - for ( ch2 = ch1 + 1; ch2 < ( hMCT->nchan_out_woLFE + hMCT->num_lfe ); ch2++ ) + for ( ch2 = ch1 + 1; ch2 < ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); + ch2++ ) { if ( fabsf( *max_corr ) < fabsf( xCorrMatrix[ch1][ch2] ) ) { @@ -308,13 +330,27 @@ static void updateCorrelationMatrix( int16_t ch1, ch2, n; /* correlation: */ - for ( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE + hMCT->num_lfe ); ch1++ ) + for ( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); + ch1++ ) { - for ( ch2 = ch1; ch2 < ( hMCT->nchan_out_woLFE + hMCT->num_lfe ); ch2++ ) + for ( ch2 = ch1; ch2 < ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); + ch2++ ) { if ( sts[ch1]->core == sts[ch2]->core && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && - sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_LFE && - sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_LFE && + sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { int16_t nSubframes = ( sts[ch1]->core == TCX_20_CORE ? 1 : NB_DIV ); @@ -341,8 +377,11 @@ static void updateCorrelationMatrix( static int16_t channelPairToIndex( const int16_t chIdx1, const int16_t chIdx2, - const int16_t nChannels, + const int16_t nChannels +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , Encoder_State **sts /* i/o: encoder state structure */ +#endif ) { int16_t ch1, ch2; @@ -354,11 +393,12 @@ static int16_t channelPairToIndex( { for ( ch1 = 0; ch1 < ch2; ch1++ ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[ch1]->mct_chan_mode == MCT_CHAN_MODE_LFE || sts[ch2]->mct_chan_mode == MCT_CHAN_MODE_LFE ) { continue; } - +#endif if ( ch1 == chIdx1 && ch2 == chIdx2 ) { return pairIdx; @@ -398,7 +438,11 @@ static void getGlobalILD( /*calculate total energy without LFE*/ for ( ch = 0; ch < nchan; ch++ ) { - if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { meanE += nrg[ch]; cnt++; @@ -410,7 +454,11 @@ static void getGlobalILD( meanE = max( meanE / cnt, EPSILON ); for ( ch = 0; ch < nchan; ch++ ) { - if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { nSubframes = ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; L_subframe = sts[ch]->hTcxEnc->L_frameTCX / nSubframes; @@ -474,7 +522,7 @@ void apply_MCT_enc( float tmp_max_corr; int16_t count_active_ch = 0; - wmops_sub_start( "mct_core_enc_mct" ); + push_wmops( "mct_core_enc_mct" ); forceKeepTree = 1; inactiveBlockDetected = 0; @@ -483,11 +531,19 @@ void apply_MCT_enc( /*Determine active channels*/ for ( ch = 0; ch < nchan; ch++ ) { - if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { count_active_ch++; } +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#else + else +#endif { hMCT->mc_global_ild[ch] = 0; } @@ -508,8 +564,16 @@ void apply_MCT_enc( { for ( ch1 = 0; ch1 < ch2; ch1++ ) { - if ( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_LFE && - sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + && + sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { sumCorrDiff += fabsf( hMCT->lastxCorrMatrix[ch1][ch2] - xCorrMatrix[ch1][ch2] ); } @@ -600,8 +664,12 @@ void apply_MCT_enc( } /* calculate all related values: */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE assert( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_LFE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_LFE ); +#else + assert( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ); +#endif getBlockValues( sts, ch1, ch2, hMCT->hBlockData[currBlockDataCnt], mdst_spectrum, inv_spectrum, inv_mdst_spectrum ); @@ -686,7 +754,11 @@ void apply_MCT_enc( for ( ch = 0; ch < nchan; ch++ ) { - if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE +#endif + ) { if ( ( !cpEle[ch] ) || hMCT->currBlockDataCnt == 0 ) { @@ -739,7 +811,7 @@ void apply_MCT_enc( } #endif - wmops_sub_end(); + pop_wmops(); return; } @@ -771,7 +843,11 @@ void write_mct_bitstream( /* first write core info and overlap mode for all channels */ for ( ch = 0; ch < nchan; ch++ ) { - if ( ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) && hMCT->currBlockDataCnt && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) && +#endif + hMCT->currBlockDataCnt && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) { push_next_indice( hBstr, hMCT->mc_global_ild[ch], SMDCT_GLOBAL_ILD_BITS ); } @@ -781,7 +857,11 @@ void write_mct_bitstream( { for ( ch = 0; ch < nchan; ch++ ) { - if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE && sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE && +#endif + sts[ch]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) { push_next_indice( hBstr, hMCT->lowE_ch[ch], 1 ); } @@ -794,7 +874,12 @@ void write_mct_bitstream( hBlock = hMCT->hBlockData[pair]; /*calculate channel pair index and write it to BS*/ - channelPairIndex = channelPairToIndex( hBlock->ch1, hBlock->ch2, nchan, sts ); + channelPairIndex = channelPairToIndex( hBlock->ch1, hBlock->ch2, nchan +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + sts +#endif + ); push_next_indice( hBstr, channelPairIndex, hMCT->bitsChannelPairIndex ); /*point to encoder states of actual channels to write block pair bits*/ @@ -834,11 +919,15 @@ void mctStereoIGF_enc( float *p_powerSpecMsInv[CPE_CHANNELS][NB_DIV]; float *p_inv_spectrum[CPE_CHANNELS][NB_DIV]; float *p_orig_spectrum[CPE_CHANNELS][NB_DIV]; - float p_powerSpec[NB_DIV][N_MAX]; + float *p_powerSpec[NB_DIV]; int16_t singleChEle[MCT_MAX_CHANNELS]; L_subframeTCX = 0; /* to avoid compilation warning */ - set_s( singleChEle, 1, hMCT->nchan_out_woLFE + hMCT->num_lfe ); + set_s( singleChEle, 1, hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); for ( b = 0; b < hMCT->currBlockDataCnt; b++ ) { @@ -855,10 +944,8 @@ void mctStereoIGF_enc( p_st[0] = sts[ch1]; p_st[1] = sts[ch2]; - mvr2r( powerSpec[ch1], p_powerSpec[0], L_FRAME48k ); - set_f( &p_powerSpec[0][L_FRAME48k], 0.f, N_MAX - L_FRAME48k ); - mvr2r( powerSpec[ch2], p_powerSpec[1], L_FRAME48k ); - set_f( &p_powerSpec[1][L_FRAME48k], 0.f, N_MAX - L_FRAME48k ); + p_powerSpec[0] = powerSpec[ch1]; + p_powerSpec[1] = powerSpec[ch2]; /* Band-wise M/S for MDST */ nSubframes = p_st[0]->hTcxEnc->tcxMode == TCX_20 ? 1 : NB_DIV; @@ -891,15 +978,28 @@ void mctStereoIGF_enc( } /* channel elements that are coded separately detected */ - if ( sum_s( singleChEle, ( hMCT->nchan_out_woLFE + hMCT->num_lfe ) ) != 0 ) + if ( sum_s( singleChEle, ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ) ) != 0 ) { - for ( ch = 0; ch < ( hMCT->nchan_out_woLFE + hMCT->num_lfe ); ch++ ) + for ( ch = 0; ch < ( hMCT->nchan_out_woLFE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + + hMCT->num_lfe +#endif + ); + ch++ ) { if ( singleChEle[ch] ) { st = sts[ch]; - if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE || st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode == MCT_CHAN_MODE_LFE || +#endif + st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { continue; } diff --git a/lib_enc/ivas_mdct_core_enc.c b/lib_enc/ivas_mdct_core_enc.c index 6f0735837b2da9d81f00d7063b594433f6158248..62223d9005a36bf4c4b827bd5ce1cab72dc9c556 100644 --- a/lib_enc/ivas_mdct_core_enc.c +++ b/lib_enc/ivas_mdct_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------* * Local constants @@ -63,10 +63,8 @@ static void enc_prm_pre_mdct( int16_t param[], /* i : parameters */ const int16_t *no_param_tns, /* i : number of TNS parameters per subframe */ int16_t p_param[2], /* o : pointer to parameters for next round of bs writing */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - const int16_t is_mct, -#endif - BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ ) { int16_t nbits_start; @@ -80,41 +78,29 @@ static void enc_prm_pre_mdct( * Header *--------------------------------------------------------------------------------*/ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - writeTCXMode( st, hBstr, is_mct, &nbits_start ); -#else - writeTCXMode( st, hBstr, &nbits_start ); -#endif + writeTCXMode( st, hBstr, MCT_flag, &nbits_start ); /* write last_core for core switching and error concealment */ -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - if ( st->core == TCX_20_CORE ) - { - push_next_indice( hBstr, st->last_core != ACELP_CORE, 1 ); - } -#else push_next_indice( hBstr, st->last_core != ACELP_CORE, 1 ); -#endif -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 writeTCXWindowing( hBstr, st->hTcxCfg->tcx_curr_overlap_mode ); if ( st->core == TCX_10_CORE ) { writeTCXWindowing( hBstr, st->hTcxCfg->tcx_last_overlap_mode ); } -#else - writeTCXWindowing( hBstr, st->hTcxCfg->tcx_curr_overlap_mode ); -#endif - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->element_mode == IVAS_CPE_MDCT && st->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif push_next_indice( hBstr, st->hTcxEnc->kernel_type[0], st->last_core != ACELP_CORE ? 2 : 1 ); if ( st->core == TCX_10_CORE ) { assert( ( st->hTcxEnc->kernel_type[0] & 1 ) == ( st->hTcxEnc->kernel_type[1] >> 1 ) ); push_next_indice( hBstr, st->hTcxEnc->kernel_type[1] & 1, 1 ); } +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif st->glr_reset = 0; #ifdef DEBUG_PLOT_BITS @@ -305,7 +291,12 @@ static void kernel_switch_update_transforms( int16_t i, leftOverlap = 0, rightOverlap = 0; const float *left_win, *right_win; - tcx_get_windows( hTcxCfg, (int16_t) windowedTimeSignal[0], (int16_t) windowedTimeSignal[1], &leftOverlap, &left_win, &rightOverlap, &right_win, 1, 0 ); + tcx_get_windows( hTcxCfg, (int16_t) windowedTimeSignal[0], (int16_t) windowedTimeSignal[1], &leftOverlap, &left_win, &rightOverlap, &right_win, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); if ( speech_TCX != NULL && tcxTransType != TCX_20 && (int16_t) windowedTimeSignal[0] == FULL_OVERLAP && s - leftOverlap > minWindowLen ) { for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ @@ -328,7 +319,12 @@ static void kernel_switch_update_transforms( s = hTcxCfg->tcx5SizeFB; /* obtain 1st TCX5 again */ nSubframes *= 2; - WindowSignal( hTcxCfg, leftOverlap / 2, RECTANGULAR_OVERLAP, MIN_OVERLAP, &leftOverlap, &rightOverlap, windowedTimeSignal + 2, &s, tcx5Win, 0, 1, 0 ); + WindowSignal( hTcxCfg, leftOverlap / 2, RECTANGULAR_OVERLAP, MIN_OVERLAP, &leftOverlap, &rightOverlap, windowedTimeSignal + 2, &s, tcx5Win, 0, 1 +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + 0 +#endif + ); kernel_switch_trafo( tcx5Win, sigR, leftOverlap, s /* L_subfr. */ - ( leftOverlap + rightOverlap ) / 2, rightOverlap, kernelType ); if ( kernelType & 1 ) /* 2nd TCX5 is kernelType 3 */ @@ -593,9 +589,11 @@ void ivas_mdct_core_whitening_enc( int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* o : number of tns parameters put into prm */ int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to the parameter table */ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ - int16_t *LFE_off, /* o : flag if LFE has zero content */ - const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ - const int16_t nChannels /* i : total number of coded channels */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + int16_t *LFE_off, /* o : flag if LFE has zero content */ +#endif + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t nChannels /* i : total number of coded channels */ ) { int16_t n, ch, nSubframes, L_subframe, L_subframeTCX, tcx_subframe_coded_lines; @@ -619,7 +617,7 @@ void ivas_mdct_core_whitening_enc( int16_t nbits_start_sns; int16_t num_sns; - wmops_sub_start( "mdct_core_whitening" ); + push_wmops( "mdct_core_whitening" ); /*--------------------------------------------------------------* * Initialization @@ -629,10 +627,14 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( sts[ch]->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif stereo_tcx_init_enc( sts[ch] ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif set_s( tnsSize[ch], 0, 2 ); set_s( tnsBits[ch], 0, 2 ); @@ -672,10 +674,14 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif SetTCXModeInfo( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif } } @@ -689,12 +695,14 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) +#else + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) +#endif { continue; } - SetCurrentPsychParams( st->core, 0, st->hTcxCfg ); /* tcx ltp analysis on the 12.8kHz weighted speech, saves preproc resampling to sr_core */ @@ -703,13 +711,38 @@ void ivas_mdct_core_whitening_enc( core_signal_analysis_high_bitrate( new_samples[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, mdst_spectrum[ch], tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0 ); /* BWD in MDCT domain */ +#ifndef FIX_MDCT_BASED_BWD if ( st->hTcxEnc->transform_type[0] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE ) +#else + if ( st->mct_chan_mode != MCT_CHAN_MODE_IGNORE ) +#endif { bw_detect( st, NULL, st->hTcxEnc->spectrum[0], NULL ); } } +#else +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) +#else + if ( st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) +#endif + { + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + bw_detect( st, NULL, st->hTcxEnc->spectrum[n], NULL, mct_on ); + + if ( nSubframes == NB_DIV && n == 0 ) + { + st->last_input_bwidth = st->input_bwidth; + } + } + } +#endif if ( st->last_core == ACELP_CORE ) /* reset past kernel info */ { @@ -724,7 +757,7 @@ void ivas_mdct_core_whitening_enc( sts[0]->hTcxEnc->fUseTns[1] = 0; - if ( sts[0]->element_brate < IVAS_80k && sts[0]->core == sts[1]->core && sts[0]->element_mode == IVAS_CPE_MDCT && !mct_on ) + if ( sts[0]->element_brate < IVAS_80k && sts[0]->core == sts[1]->core && sts[0]->element_mode == IVAS_CPE_MDCT && !mct_on && !hCPE->hStereoMdct->isSBAStereoMode ) { int16_t nSampCore; int32_t totalRate; @@ -820,7 +853,11 @@ void ivas_mdct_core_whitening_enc( { TCX_ENC_HANDLE hTcxEncCh = sts[ch]->hTcxEnc; - if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { hTcxEncCh->kernel_symmetry_past = hTcxEncCh->kernel_type[0] = 0; @@ -849,7 +886,11 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { continue; } @@ -894,11 +935,15 @@ void ivas_mdct_core_whitening_enc( } /* MCT: detect whether there are silent channels and set mct_chan_mode accordingly */ - if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE && mct_on ) + if ( +#ifndef ISSUE_24_CLEANUP_MCT_LFE + st->mct_chan_mode != MCT_CHAN_MODE_LFE && +#endif + mct_on ) { chE_tot = sum_f( chE, NB_DIV ); - if ( chE_tot < SILENT_CHANNEL_THRES ) + if ( chE_tot < SILENT_CHANNEL_THRES && nSubframes == 1 ) { st->mct_chan_mode = MCT_CHAN_MODE_IGNORE; st->bits_frame_channel = 0; @@ -911,7 +956,11 @@ void ivas_mdct_core_whitening_enc( } /* set low br mode, if possible. Can later be discarded, depending on the stereo mode used for SNS parameter decoding */ - if ( hCPE->element_brate == IVAS_48k && !( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) + if ( hCPE->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[1]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) ) { sns_low_br_mode = !sts[0]->sp_aud_decision0; } @@ -938,7 +987,11 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { param_lpc[ch][0] = ch; - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { continue; } @@ -961,7 +1014,11 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { continue; } @@ -989,7 +1046,11 @@ void ivas_mdct_core_whitening_enc( /* first deinterleave once more */ for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { continue; } @@ -1010,7 +1071,11 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE ) + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[ch]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) { continue; } @@ -1032,8 +1097,9 @@ void ivas_mdct_core_whitening_enc( } } } - - /*check whether LFE channel is active*/ +#ifndef ISSUE_24_CLEANUP_MCT_LFE +/*check whether LFE channel is active*/ +#endif for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { /*no need to write last channel bit in case of odd channels*/ @@ -1046,12 +1112,15 @@ void ivas_mdct_core_whitening_enc( if ( mct_on ) /* signal bits should be written only for MCT*/ { +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { assert( *LFE_off == 1 ); push_next_indice( hBstr, *LFE_off, 1 ); } - else if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + else +#endif + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) { push_next_indice( hBstr, 1, 1 ); } @@ -1068,19 +1137,19 @@ void ivas_mdct_core_whitening_enc( { st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( *LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { st->side_bits_frame_channel = 0; /*dummy initialization to prevent range coder crashing in case all channels are silent and bits are distributed to channel 0 */ - *p_param[ch] = 9; + *p_param[ch] = 1 + NOISE_FILL_RANGES + LTPSIZE + tnsSize[ch][0] + NPRM_CTX_HM; continue; } -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT enc_prm_pre_mdct( st, param_core[ch], ( ( ( ch > 0 ) && ( sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 ) && !mct_on ) ? tnsSize[ch] : NULL ), p_param[ch], mct_on, hBstr ); -#else - enc_prm_pre_mdct( st, param_core[ch], ( ( ( ch > 0 ) && ( sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 ) && !mct_on ) ? tnsSize[ch] : NULL ), p_param[ch], hBstr ); -#endif if ( ch > 0 && sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 && !mct_on ) { @@ -1117,7 +1186,11 @@ void ivas_mdct_core_whitening_enc( { st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( *LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { skipped_first_channel = 1; continue; @@ -1131,7 +1204,11 @@ void ivas_mdct_core_whitening_enc( { push_next_indice( hBstr, param_lpc[0][0] >> 1, 1 ); - if ( st->element_brate == IVAS_48k && !( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) + if ( st->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + || sts[1]->mct_chan_mode == MCT_CHAN_MODE_LFE +#endif + ) ) { /* write classifier decision to signal low br mode for SNS encoding, for all other configs, low_br mode is not possible */ push_next_indice( hBstr, sns_low_br_mode, 1 ); @@ -1146,7 +1223,11 @@ void ivas_mdct_core_whitening_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( *LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { continue; } @@ -1160,7 +1241,7 @@ void ivas_mdct_core_whitening_enc( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -1172,12 +1253,14 @@ void ivas_mdct_core_whitening_enc( *---------------------------------------------------------------*/ void ivas_mdct_quant_coder( - CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ - const int16_t LFE_off, /* i : flag if LFE is inactive */ - int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ - int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ - const int16_t is_mct /* i : is mct flag */ + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE + const int16_t LFE_off, /* i : flag if LFE is inactive */ +#endif + int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { Encoder_State *st, **sts; @@ -1199,7 +1282,7 @@ void ivas_mdct_quant_coder( int16_t target_bitsTCX10[CPE_CHANNELS][NB_DIV]; int16_t nbits_start, total_nbbits; - wmops_sub_start( "mdct_core_Q" ); + push_wmops( "mdct_core_Q" ); sts = hCPE->hCoreCoder; @@ -1219,7 +1302,11 @@ void ivas_mdct_quant_coder( st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { ignore_chan[ch] = 1; continue; @@ -1273,13 +1360,17 @@ void ivas_mdct_quant_coder( } } - EstimateStereoTCXNoiseLevel( sts, quantized_spectrum, gain_tcx, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns, param_core, is_mct ); + EstimateStereoTCXNoiseLevel( sts, quantized_spectrum, gain_tcx, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns, param_core, MCT_flag ); for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; - if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { /*Enable appropriate upadte of tcx_curr_overlap_mode even for uncoded channel index 1*/ L_frameTCX[ch][0] = ( st->core == TCX_10_CORE ) ? st->hTcxEnc->L_frameTCX >> 1 : st->hTcxEnc->L_frameTCX; @@ -1306,7 +1397,11 @@ void ivas_mdct_quant_coder( * Generate Bitstream *---------------------------------------------------------------*/ - if ( ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) && LFE_off ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#ifndef ISSUE_24_CLEANUP_MCT_LFE + if ( ( st->mct_chan_mode == MCT_CHAN_MODE_LFE && ( LFE_off ) ) || ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) ) +#else + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) +#endif { continue; } @@ -1319,7 +1414,7 @@ void ivas_mdct_quant_coder( assert( st->bits_frame_channel == total_nbbits ); } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_enc/ivas_pca_enc.c b/lib_enc/ivas_pca_enc.c index 6694a36f25b9a2e8480b68440b58f5ae56bfa27b..8ecac8d208381ae0f6c36ea2c6f480596135a7cc 100644 --- a/lib_enc/ivas_pca_enc.c +++ b/lib_enc/ivas_pca_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,8 +40,7 @@ #include "ivas_cnst.h" #include #include -#include "typedef.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -95,29 +94,6 @@ static void pca_enc_reset( } -/*------------------------------------------------------------------------- - * ivas_pca_enc() - * - * Initialize PCA encoder - *------------------------------------------------------------------------*/ - -void init_pca_enc( - PCA_ENC_STATE *hPCA /* i/o: PCA encoder structure */ -) -{ - hPCA->prev_bypass_decision = PCA_MODE_INACTIVE; - pca_enc_reset( hPCA ); - - return; -} - - -/*------------------------------------------------------------------------- - * pca_transform_sub() - * - * - *------------------------------------------------------------------------*/ - static void pca_transform_sub( float *eigVec, float *transformed_data[8], /* i : input/transformed audio channels */ @@ -264,6 +240,23 @@ static void sort4_D_eigVec( } +/*------------------------------------------------------------------------- + * ivas_pca_enc_init() + * + * Initialize PCA encoder + *------------------------------------------------------------------------*/ + +void ivas_pca_enc_init( + PCA_ENC_STATE *hPCA /* i/o: PCA encoder structure */ +) +{ + hPCA->prev_bypass_decision = PCA_MODE_INACTIVE; + pca_enc_reset( hPCA ); + + return; +} + + /*------------------------------------------------------------------------- * ivas_pca_enc() * diff --git a/lib_enc/ivas_qmetadata_enc.c b/lib_enc/ivas_qmetadata_enc.c index 8a10750e11651c423e5ec0d5dd4573a83ca96395..ac4f83a65794d7bbcdc2104e7b858d5bc8319ff7 100644 --- a/lib_enc/ivas_qmetadata_enc.c +++ b/lib_enc/ivas_qmetadata_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include "ivas_stat_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" @@ -144,13 +144,13 @@ ivas_error ivas_qmetadata_enc_encode( float azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; int16_t all_coherence_zero; int16_t bit_pos_0, total_bits_1dir, bits_no_dirs_coh; - int16_t bits_signalling[QMETADATA_MAX_NO_DIRECTIONS]; + int16_t bits_signaling[QMETADATA_MAX_NO_DIRECTIONS]; int16_t indice_coherence; int16_t bits_dir_bands[MASA_MAXIMUM_CODING_SUBBANDS], raw_flag[MASA_MAXIMUM_CODING_SUBBANDS]; int16_t diff_bits, bits_ec, next_ind_raw_flag; int16_t dfRatio_bits[MASA_MAXIMUM_CODING_SUBBANDS]; int16_t bits_surround_coh, no_TF; - int16_t dir2_bands[MASA_MAXIMUM_CODING_SUBBANDS / 2]; + int16_t dir2_bands[MASA_MAXIMUM_TWO_DIR_BANDS]; int16_t ind_order[MASA_MAXIMUM_CODING_SUBBANDS]; int16_t reduce_bits; ivas_error error; @@ -375,7 +375,7 @@ ivas_error ivas_qmetadata_enc_encode( } #endif - bits_signalling[d] = 0; + bits_signaling[d] = 0; /*Coherence */ bits_coherence[d] = 0; @@ -399,7 +399,7 @@ ivas_error ivas_qmetadata_enc_encode( /* Signalling 2D*/ push_next_indice( hMetaData, ( q_direction->not_in_2D > 0 ), 1 ); /*2D flag*/ - bits_signalling[d] = 1; + bits_signaling[d] = 1; /* Save state of metadata bitstream buffer after writing energy ratios, number of dirs and save space for coherence*/ bit_pos_start = hMetaData->nb_bits_tot; @@ -410,7 +410,7 @@ ivas_error ivas_qmetadata_enc_encode( if ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) { push_next_indice( hMetaData, 0, 1 ); /*Write 1 bit to signal EC frame-wise (EC1)*/ - bits_signalling[d]++; + bits_signaling[d]++; } next_ind_raw_flag = hMetaData->next_ind; @@ -418,7 +418,7 @@ ivas_error ivas_qmetadata_enc_encode( bits_dir_bands[0] = ivas_qmetadata_raw_encode_dir( NULL, q_direction, q_direction->cfg.nbands, q_direction->cfg.start_band ); - reduce_bits = hQMetaData->is_masa_type_format ? ( total_bits_1dir - ( bits_diff[d] + bits_coherence[d] + bits_signalling[d] ) - 1 ) : MASA_MAX_BITS; + reduce_bits = hQMetaData->is_masa_ivas_format ? ( total_bits_1dir - ( bits_diff[d] + bits_coherence[d] + bits_signaling[d] ) - 1 ) : MASA_MAX_BITS; bits_ec = ivas_qmetadata_entropy_encode_dir( hMetaData, q_direction, diffuseness_index_max_ec_frame, q_direction->cfg.nbands, q_direction->cfg.start_band, bits_dir_bands[0], reduce_bits ); @@ -432,25 +432,25 @@ ivas_error ivas_qmetadata_enc_encode( } bits_dir[d] = bits_ec + 1; #ifdef DEBUG_MODE_QMETADATA - tmp = bits_dir[d] - ( total_bits_1dir - ( bits_diff[d] + bits_coherence[d] + bits_signalling[d] ) ); + tmp = bits_dir[d] - ( total_bits_1dir - ( bits_diff[d] + bits_coherence[d] + bits_signaling[d] ) ); #endif extra_bits = hQMetaData->metadata_max_bits - ( hMetaData->nb_bits_tot - bit_pos_0 ); #ifdef DEBUGGING - assert( bit_pos_start + bits_signalling[d] - 1 + bits_dir[d] == hMetaData->nb_bits_tot ); + assert( bit_pos_start + bits_signaling[d] - 1 + bits_dir[d] == hMetaData->nb_bits_tot ); #endif #ifdef DEBUG_MODE_QMETADATA ec_flag = 0; #endif /* Encode quantized directions with EC band-wise */ - if ( ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signalling[d] > total_bits_1dir ) && q_direction->cfg.nblocks > 1 ) + if ( ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signaling[d] > total_bits_1dir ) && q_direction->cfg.nblocks > 1 ) { restore_metadata_buffer( hMetaData, next_ind_start, last_ind_start, bit_pos_start ); - /* Write signalling */ + /* Write signaling */ push_next_indice( hMetaData, 1, 1 ); /*Write 1 bit to signal no EC frame-wise (EC1)*/ push_next_indice( hMetaData, 0, 1 ); /*Write 1 bit to signal EC band-wise (EC2)*/ - bits_signalling[d] = 3; + bits_signaling[d] = 3; /* Write raw flags */ next_ind_raw_flag = hMetaData->next_ind; @@ -460,7 +460,7 @@ ivas_error ivas_qmetadata_enc_encode( } bits_dir[d] = 0; - diff_bits = bits_diff[d] + bits_coherence[d] + bits_signalling[d] - total_bits_1dir; + diff_bits = bits_diff[d] + bits_coherence[d] + bits_signaling[d] - total_bits_1dir; for ( i = start_band; i < nbands; i++ ) { bits_dir_bands[i] = ivas_qmetadata_raw_encode_dir( NULL, q_direction, i + 1, i ); @@ -501,14 +501,14 @@ ivas_error ivas_qmetadata_enc_encode( extra_bits = hQMetaData->metadata_max_bits - ( hMetaData->nb_bits_tot - bit_pos_0 ); #ifdef DEBUGGING - if ( ( diff_bits <= 0 ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signalling[d] > total_bits_1dir ) ) + if ( ( diff_bits <= 0 ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signaling[d] > total_bits_1dir ) ) { return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "not possible!!" ); } #endif #ifdef DEBUGGING - assert( bit_pos_start + bits_signalling[d] - 1 + bits_dir[d] == hMetaData->nb_bits_tot ); + assert( bit_pos_start + bits_signaling[d] - 1 + bits_dir[d] == hMetaData->nb_bits_tot ); #endif #ifdef DEBUG_MODE_QMETADATA ec_flag = 1; @@ -516,7 +516,7 @@ ivas_error ivas_qmetadata_enc_encode( } /* Requantized directions */ - if ( ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signalling[d] > total_bits_1dir ) ) + if ( ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signaling[d] > total_bits_1dir ) ) { /*Bit budget exceeded, bit reduction strategy?*/ @@ -528,27 +528,29 @@ ivas_error ivas_qmetadata_enc_encode( if ( nblocks > 1 ) { push_next_indice( hMetaData, 1, 1 ); /*Write 1 bit to signal requantization stage (EC3)*/ - bits_signalling[d] = 3; + bits_signaling[d] = 3; } else { - bits_signalling[d] = 2; + bits_signaling[d] = 2; } - if ( hQMetaData->is_masa_type_format == 0 ) + + if ( hQMetaData->is_masa_ivas_format == 0 ) { - reduce_bits = bits_dir_raw - ( total_bits_1dir - bits_diff[d] - bits_coherence[d] - bits_signalling[d] ); + reduce_bits = bits_dir_raw - ( total_bits_1dir - bits_diff[d] - bits_coherence[d] - bits_signaling[d] ); ind_order[0] = -1; } else { ind_order[0] = 0; - reduce_bits = min( nbands * nblocks + MASA_BIT_REDUCT_PARAM, bits_dir_raw - ( total_bits_1dir - bits_diff[d] - bits_coherence[d] - bits_signalling[d] ) ); + reduce_bits = min( nbands * nblocks + MASA_BIT_REDUCT_PARAM, bits_dir_raw - ( total_bits_1dir - bits_diff[d] - bits_coherence[d] - bits_signaling[d] ) ); if ( reduce_bits > bits_dir_raw - nbands * nblocks ) { reduce_bits = bits_dir_raw - nbands * nblocks; } } + only_reduce_bits_direction( &extra_bits, q_direction, reduce_bits, nbands, nblocks, ind_order ); bits_dir[d] = hMetaData->nb_bits_tot; requantize_direction_EC_3( &extra_bits, q_direction, nbands, hMetaData, elevation_orig, azimuth_orig, ind_order ); @@ -639,6 +641,7 @@ ivas_error ivas_qmetadata_enc_encode( mvr2r( q_direction->band_data[i].azimuth, q_direction->band_data[i].q_azimuth, nblocks ); mvr2r( q_direction->band_data[i].elevation, q_direction->band_data[i].q_elevation, nblocks ); } + /* Copy original DOAs back to q_direction*/ for ( i = start_band; i < nbands; i++ ) { @@ -681,17 +684,20 @@ void ivas_qmetadata_enc_sid_encode( { if ( sba_mode == SBA_MODE_SPAR ) { - metadata_sid_bits = (int16_t) ( IVAS_SID_5k - SID_2k40 ) / FRAMES_PER_SEC - ( SPAR_DTX_BANDS * SPAR_SID_BITS_TAR_PER_BAND ) - 1; /* -1 for inactive mode header bit*/ + /* TODO: still use old sid frame size to keep bitexactness */ + metadata_sid_bits = (int16_t) ( 5000 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - ( SPAR_DTX_BANDS * SPAR_SID_BITS_TAR_PER_BAND ) - 1; /* -1 for inactive mode header bit*/ } else { - /* keep 13.2 and 16.4 sid bitrate as 4.4 kbps for now*/ - metadata_sid_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + /* keep 13.2 and 16.4 SID bitrate as 4.4 kbps for now*/ + /* TODO: still use old sid frame size to keep bitexactness */ + metadata_sid_bits = ( 4400 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; } } else { - metadata_sid_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + /* TODO: still use old sid frame size to keep bitexactness */ + metadata_sid_bits = ( 4400 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; } #ifdef DEBUG_MODE_QMETADATA @@ -870,6 +876,20 @@ void ivas_qmetadata_enc_sid_encode( } #endif + /* TODO: temporary to keep BE */ + if ( ivas_format == SBA_FORMAT ) + { + if ( sba_mode != SBA_MODE_SPAR ) + { + /* keep 13.2 and 16.4 SID bitrate as 4.4 kbps for now*/ + metadata_sid_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - 1; /* -1 for spar/dirac indicator*/ + } + } + else + { + metadata_sid_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + } + /* fill bits*/ assert( ( hMetaData->nb_bits_tot - bit_pos_start ) <= metadata_sid_bits && "Too many written bits!" ); while ( ( hMetaData->nb_bits_tot - bit_pos_start ) < metadata_sid_bits ) @@ -893,11 +913,11 @@ void reset_metadata_spatial( int32_t *total_brate, /* o : total bitrate */ const int32_t core_brate, /* i : core bitrate */ const int16_t nb_bits_metadata, /* i : number of meatdata bits */ - const SBA_MODE sba_mode, /* i : SBA mode */ - const int16_t element_mode /* i : element mode */ + const SBA_MODE sba_mode /* i : SBA mode */ ) { int16_t i, next_ind_sid, last_ind_sid; + int16_t metadata_sid_bits; if ( core_brate == SID_2k40 || core_brate == FRAME_NO_DATA ) { @@ -906,13 +926,11 @@ void reset_metadata_spatial( if ( sba_mode == SBA_MODE_SPAR ) { assert( hMetaData->ind_list[0].nb_bits == 1 ); - if ( element_mode > IVAS_SCE ) + hMetaData->ind_list[0].value = 1; + metadata_sid_bits = (int16_t) ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + while ( hMetaData->nb_bits_tot < metadata_sid_bits ) { - hMetaData->ind_list[0].value = 1; - } - else - { - hMetaData->ind_list[0].value = 0; + push_next_indice( hMetaData, 0, 1 ); /*fill bit*/ } } else @@ -943,7 +961,7 @@ void reset_metadata_spatial( hMetaData->ind_list[i].nb_bits = -1; } hMetaData->last_ind = hMetaData->next_ind; - assert( ( hMetaData->nb_bits_tot == ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS ) && "Problem of SID metadata in SCE" ); + assert( ( hMetaData->nb_bits_tot == ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS ) && "Problem of SID metadata in SCE" ); } } else @@ -1252,7 +1270,7 @@ static int16_t ivas_qmetadata_entropy_encode_diffuseness( if ( nbands == 1 ) { - /* If there is only one band, diffuseness should be coded directly as raw with no signalling. */ + /* If there is only one band, diffuseness should be coded directly as raw with no signaling. */ push_next_indice( hMetaData, q_direction->band_data[0].energy_ratio_index[0], MASA_BITS_ER ); *diffuseness_index_max_ec_frame = 5; return ( hMetaData->nb_bits_tot - start_bit_pos ); @@ -1389,7 +1407,7 @@ static int16_t ivas_qmetadata_entropy_encode_df_ratio( if ( nbands == 1 ) { - /* If there is only one band, ratio should be coded directly as raw with no signalling. */ + /* If there is only one band, ratio should be coded directly as raw with no signaling. */ push_next_indice( hMetaData, q_direction->band_data[0].energy_ratio_index[0], df_ratio_bits[0] ); return ( hMetaData->nb_bits_tot - start_bit_pos ); @@ -1439,7 +1457,7 @@ static int16_t ivas_qmetadata_entropy_encode_df_ratio( push_next_indice( hMetaData, 0, 1 ); /* Signal between EC and raw */ if ( ec_mode > 1 ) { - /* Only use bit for signalling if necessary */ + /* Only use bit for signaling if necessary */ push_next_indice( hMetaData, 0, 1 ); /* Signal between one value or bandwise diff mode */ } @@ -4038,27 +4056,24 @@ static int16_t encode_spread_coherence_1sf( BSTR_ENC_HANDLE hMasaMetaData /* i/o: metadata bitstream handle */ ) { - int16_t i, j; + int16_t i, j, k; int16_t idx_ER; int16_t nbits, nbits_fr; uint16_t idx_sp_coh[MASA_MAXIMUM_CODING_SUBBANDS]; uint16_t mr_idx_sp_coh[MASA_MAXIMUM_CODING_SUBBANDS]; int16_t GR_ord, bits_GR; - uint64_t idx; + uint64_t idx, idx1; int16_t no_idx16; - int16_t k; int16_t no_cv[MASA_MAXIMUM_CODING_SUBBANDS]; IVAS_QDIRECTION *q_direction; - int16_t half_coding_subbands, nbits_fr1; - uint64_t idx1; - uint8_t coding_subbands; + int16_t half_coding_subbands, nbits_fr1, coding_subbands; uint16_t idx_sp_coh_shift[MASA_MAXIMUM_CODING_SUBBANDS]; uint8_t idx_shift; int16_t max_val = 0, nbits_max; int16_t extra_cv; int16_t no_cv_shift[MASA_MAXIMUM_CODING_SUBBANDS], min_idx; - coding_subbands = (uint8_t) ( q_metadata->q_direction[idx_d].cfg.nbands ); + coding_subbands = q_metadata->q_direction[idx_d].cfg.nbands; q_direction = &( q_metadata->q_direction[idx_d] ); nbits = 0; GR_ord = 1; @@ -4219,28 +4234,25 @@ static int16_t encode_surround_coherence( BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */ ) { - int16_t i, j; - int16_t idx_ER; + int16_t i, j, k; + int16_t idx_ER, idx16; int16_t nbits, nbits_fr; uint16_t idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; uint16_t mr_idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; int16_t GR_ord, bits_GR; - uint64_t idx; + uint64_t idx, idx1; int16_t no_idx16; - int16_t k; int16_t no_cv[MASA_MAXIMUM_CODING_SUBBANDS]; float error_ratio_surr; IVAS_QDIRECTION *q_direction; - int16_t half_coding_subbands, nbits_fr1; - uint64_t idx1; - uint8_t coding_subbands; + int16_t half_coding_subbands, nbits_fr1, coding_subbands; int16_t all_coherence_zero; uint16_t idx_sur_coh_shift[MASA_MAXIMUM_CODING_SUBBANDS]; uint8_t idx_shift; int16_t max_val = 0, nbits_max; int16_t no_cv_shift[MASA_MAXIMUM_CODING_SUBBANDS], min_idx; - coding_subbands = (uint8_t) ( hQMetaData->q_direction[0].cfg.nbands ); + coding_subbands = hQMetaData->q_direction[0].cfg.nbands; all_coherence_zero = hQMetaData->all_coherence_zero; q_direction = &( hQMetaData->q_direction[0] ); nbits = 0; @@ -4259,7 +4271,8 @@ static int16_t encode_surround_coherence( if ( hQMetaData->no_directions == 2 ) { k += hQMetaData->twoDirBands[j]; - error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[0] - q_direction[1].band_data[max( k - 1, 0 )].energy_ratio[0] * hQMetaData->twoDirBands[j]; + idx16 = max( k - 1, 0 ); + error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[0] - q_direction[1].band_data[idx16].energy_ratio[0] * hQMetaData->twoDirBands[j]; } else { diff --git a/lib_enc/ivas_qspherical_enc.c b/lib_enc/ivas_qspherical_enc.c index b8f889b472b55059c4599a19f66a15aecccaad66..80a9d0064f2dcfb23dbeb91ed3719dd74e0a526c 100644 --- a/lib_enc/ivas_qspherical_enc.c +++ b/lib_enc/ivas_qspherical_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include "ivas_stat_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "prot.h" diff --git a/lib_enc/ivas_range_uni_enc.c b/lib_enc/ivas_range_uni_enc.c index be325d47bc76841b7116256fffc131107d64cf86..82f6813c2e8bcd56293f85de9ca1f5d3dc87f225 100644 --- a/lib_enc/ivas_range_uni_enc.c +++ b/lib_enc/ivas_range_uni_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "options.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUGGING #include "debug.h" #endif diff --git a/lib_enc/ivas_rom_enc.c b/lib_enc/ivas_rom_enc.c index 783085fb86e1909107cdd3a6719fe8407b813db9..ae7cd2ee1a6c29c3f1fdcb2ae51b93bf31803ce1 100644 --- a/lib_enc/ivas_rom_enc.c +++ b/lib_enc/ivas_rom_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "cnst.h" #include "ivas_cnst.h" #include -#include "wmops.h" +#include "wmc_auto.h" /* clang-format off */ @@ -534,158 +534,6 @@ const float ari_bit_estimate_s17_LC[RANGE_N_CONTEXT][RANGE_N_SYMBOLS] = * Stereo downmix to EVS ROM tables *----------------------------------------------------------------------------------*/ -const float Stereo_dmx_s_wnd_coef_eps_16k[L_FRAME16k * 3 / 4] = { - 0.00000000f, 0.000385506690f, 0.000770864717f, 0.00115592557f, 0.00154054083f, 0.00192456215f, 0.00230784155f, 0.00269023119f, 0.00307158381f, 0.00345175178f, - 0.00383058959f, 0.00420795102f, 0.00458368938f, 0.00495766103f, 0.00532972161f, 0.00569972629f, 0.00606753491f, 0.00643300405f, 0.00679599261f, 0.00715636183f, - 0.00751397246f, 0.00786868576f, 0.00822036527f, 0.00856887549f, 0.00891408324f, 0.00925585348f, 0.00959405676f, 0.00992856082f, 0.0102592362f, 0.0105859563f, - 0.0109085962f, 0.0112270303f, 0.0115411365f, 0.0118507938f, 0.0121558821f, 0.0124562839f, 0.0127518829f, 0.0130425673f, 0.0133282226f, 0.0136087397f, - 0.0138840098f, 0.0141539266f, 0.0144183896f, 0.0146772927f, 0.0149305379f, 0.0151780248f, 0.0154196629f, 0.0156553555f, 0.0158850122f, 0.0161085464f, - 0.0163258687f, 0.0165368970f, 0.0167415515f, 0.0169397499f, 0.0171314199f, 0.0173164830f, 0.0174948741f, 0.0176665168f, 0.0178313497f, 0.0179893095f, - 0.0181403328f, 0.0182843637f, 0.0184213445f, 0.0185512230f, 0.0186739527f, 0.0187894795f, 0.0188977662f, 0.0189987645f, 0.0190924387f, 0.0191787537f, - 0.0192576759f, 0.0193291716f, 0.0193932168f, 0.0194497835f, 0.0194988549f, 0.0195404068f, 0.0195744261f, 0.0196008999f, 0.0196198169f, 0.0196311697f, - 0.0196349546f, 0.0196311697f, 0.0196198169f, 0.0196008999f, 0.0195744261f, 0.0195404068f, 0.0194988549f, 0.0194497835f, 0.0193932150f, 0.0193291716f, - 0.0192576740f, 0.0191787537f, 0.0190924387f, 0.0189987645f, 0.0188977644f, 0.0187894795f, 0.0186739508f, 0.0185512230f, 0.0184213426f, 0.0182843637f, - 0.0181403328f, 0.0179893095f, 0.0178313479f, 0.0176665168f, 0.0174948722f, 0.0173164830f, 0.0171314199f, 0.0169397499f, 0.0167415496f, 0.0165368970f, - 0.0163258687f, 0.0161085445f, 0.0158850104f, 0.0156553555f, 0.0154196629f, 0.0151780220f, 0.0149305360f, 0.0146772927f, 0.0144183887f, 0.0141539248f, - 0.0138840098f, 0.0136087388f, 0.0133282207f, 0.0130425654f, 0.0127518829f, 0.0124562830f, 0.0121558802f, 0.0118507929f, 0.0115411356f, 0.0112270294f, - 0.0109085953f, 0.0105859553f, 0.0102592343f, 0.00992855709f, 0.00959405396f, 0.00925585162f, 0.00891408045f, 0.00856887735f, 0.00822036248f, 0.00786868297f, - 0.00751396874f, 0.00715636322f, 0.00679598982f, 0.00643300032f, 0.00606753537f, 0.00569972722f, 0.00532971695f, 0.00495765638f, 0.00458368938f, 0.00420795055f, - 0.00383058493f, 0.00345175178f, 0.00307158334f, 0.00269023073f, 0.00230784062f, 0.00192456122f, 0.00154053967f, 0.00115592428f, 0.000770863262f, 0.000385505118f, - -1.71654224e-09f, -0.000385508552f, -0.000770866696f, -0.00115592312f, -0.00154053851f, -0.00192456460f, -0.00230784412f, -0.00269023376f, -0.00307158637f, -0.00345175504f, - -0.00383058819f, -0.00420794915f, -0.00458368799f, -0.00495766429f, -0.00532972487f, -0.00569973048f, -0.00606753910f, -0.00643300358f, -0.00679599261f, -0.00715636183f, - -0.00751397153f, -0.00786868948f, -0.00822036993f, -0.00856888015f, -0.00891408417f, -0.00925585441f, -0.00959405676f, -0.00992856082f, -0.0102592362f, -0.0105859619f, - -0.0109086009f, -0.0112270284f, -0.0115411393f, -0.0118507957f, -0.0121558839f, -0.0124562858f, -0.0127518848f, -0.0130425720f, -0.0133282207f, -0.0136087369f, - -0.0138840117f, -0.0141539304f, -0.0144183915f, -0.0146772945f, -0.0149305388f, -0.0151780248f, -0.0154196648f, -0.0156553555f, -0.0158850141f, -0.0161085445f, - -0.0163258705f, -0.0165369026f, -0.0167415477f, -0.0169397499f, -0.0171314217f, -0.0173164848f, -0.0174948759f, -0.0176665168f, -0.0178313479f, -0.0179893095f, - -0.0181403328f, -0.0182843637f, -0.0184213463f, -0.0185512248f, -0.0186739527f, -0.0187894795f, -0.0188977644f, -0.0189987663f, -0.0190924387f, -0.0191787556f, - -0.0192576759f, -0.0193291716f, -0.0193932150f, -0.0194497835f, -0.0194988549f, -0.0195404068f, -0.0195744261f, -0.0196008999f, -0.0196198169f, -0.0196311697f -}; - -const float Stereo_dmx_s_wnd_coef_eps_32k[L_FRAME32k * 3 / 4] = { - 0.00000000f, 9.63813145e-05f, 0.000192753345f, 0.000289106771f, 0.000385432359f, 0.000481720810f, 0.000577962783f, 0.000674149080f, 0.000770270417f, 0.000866317423f, - 0.000962281076f, 0.00105815195f, 0.00115392078f, 0.00124957843f, 0.00134511560f, 0.00144052308f, 0.00153579190f, 0.00163091265f, 0.00172587589f, 0.00182067312f, - 0.00191529479f, 0.00200973195f, 0.00210397551f, 0.00219801581f, 0.00229184469f, 0.00238545262f, 0.00247883052f, 0.00257196953f, 0.00266486080f, 0.00275749480f, - 0.00284986314f, 0.00294195698f, 0.00303376745f, 0.00312528526f, 0.00321650202f, 0.00330740865f, 0.00339799630f, 0.00348825660f, 0.00357818091f, 0.00366776017f, - 0.00375698623f, 0.00384584931f, 0.00393434288f, 0.00402245624f, 0.00411018264f, 0.00419751229f, 0.00428443775f, 0.00437095016f, 0.00445704162f, 0.00454270327f, - 0.00462792674f, 0.00471270457f, 0.00479702838f, 0.00488088885f, 0.00496428041f, 0.00504719233f, 0.00512961810f, 0.00521154935f, 0.00529297814f, 0.00537389703f, - 0.00545429811f, 0.00553417346f, 0.00561351515f, 0.00569231622f, 0.00577056827f, 0.00584826432f, 0.00592539692f, 0.00600195816f, 0.00607794104f, 0.00615333812f, - 0.00622814195f, 0.00630234554f, 0.00637594145f, 0.00644892361f, 0.00652128365f, 0.00659301504f, 0.00666411128f, 0.00673456443f, 0.00680436986f, 0.00687351823f, - 0.00694200490f, 0.00700982194f, 0.00707696332f, 0.00714342389f, 0.00720919482f, 0.00727427099f, 0.00733864633f, 0.00740231434f, 0.00746526895f, 0.00752750318f, - 0.00758901238f, 0.00764979096f, 0.00770983147f, 0.00776912877f, 0.00782767776f, 0.00788547192f, 0.00794250611f, 0.00799877476f, 0.00805427320f, 0.00810899399f, - 0.00816293433f, 0.00821608771f, 0.00826844852f, 0.00832001306f, 0.00837077573f, 0.00842073187f, 0.00846987497f, 0.00851820316f, 0.00856570993f, 0.00861239061f, - 0.00865824148f, 0.00870325882f, 0.00874743704f, 0.00879077055f, 0.00883325841f, 0.00887489505f, 0.00891567487f, 0.00895559601f, 0.00899465475f, 0.00903284643f, - 0.00907016639f, 0.00910661276f, 0.00914218184f, 0.00917686895f, 0.00921067223f, 0.00924358703f, 0.00927561149f, 0.00930674188f, 0.00933697633f, 0.00936630927f, - 0.00939473975f, 0.00942226499f, 0.00944888312f, 0.00947458949f, 0.00949938223f, 0.00952325948f, 0.00954621937f, 0.00956825912f, 0.00958937686f, 0.00960957073f, - 0.00962883793f, 0.00964717567f, 0.00966458581f, 0.00968106277f, 0.00969660841f, 0.00971121807f, 0.00972489174f, 0.00973762851f, 0.00974942744f, 0.00976028573f, - 0.00977020338f, 0.00977917947f, 0.00978721306f, 0.00979430322f, 0.00980044995f, 0.00980565138f, 0.00980990846f, 0.00981321931f, 0.00981558487f, 0.00981700420f, - 0.00981747732f, 0.00981700420f, 0.00981558487f, 0.00981321931f, 0.00980990846f, 0.00980565138f, 0.00980044995f, 0.00979430322f, 0.00978721306f, 0.00977917947f, - 0.00977020338f, 0.00976028573f, 0.00974942744f, 0.00973762851f, 0.00972489174f, 0.00971121807f, 0.00969660748f, 0.00968106277f, 0.00966458581f, 0.00964717567f, - 0.00962883700f, 0.00960956980f, 0.00958937686f, 0.00956825912f, 0.00954621937f, 0.00952325948f, 0.00949938223f, 0.00947458856f, 0.00944888219f, 0.00942226499f, - 0.00939473975f, 0.00936630927f, 0.00933697540f, 0.00930674188f, 0.00927561149f, 0.00924358703f, 0.00921067130f, 0.00917686801f, 0.00914218184f, 0.00910661276f, - 0.00907016639f, 0.00903284550f, 0.00899465475f, 0.00895559601f, 0.00891567394f, 0.00887489505f, 0.00883325841f, 0.00879077055f, 0.00874743611f, 0.00870325882f, - 0.00865824148f, 0.00861238968f, 0.00856570993f, 0.00851820316f, 0.00846987497f, 0.00842073094f, 0.00837077480f, 0.00832001306f, 0.00826844852f, 0.00821608678f, - 0.00816293433f, 0.00810899399f, 0.00805427227f, 0.00799877476f, 0.00794250518f, 0.00788547192f, 0.00782767776f, 0.00776912784f, 0.00770983147f, 0.00764979003f, - 0.00758901099f, 0.00752750272f, 0.00746526802f, 0.00740231294f, 0.00733864633f, 0.00727427006f, 0.00720919436f, 0.00714342296f, 0.00707696239f, 0.00700982334f, - 0.00694200490f, 0.00687351730f, 0.00680436939f, 0.00673456397f, 0.00666411035f, 0.00659301365f, 0.00652128272f, 0.00644892408f, 0.00637594145f, 0.00630234415f, - 0.00622814149f, 0.00615333673f, 0.00607794011f, 0.00600195862f, 0.00592539646f, 0.00584826525f, 0.00577056780f, 0.00569231436f, 0.00561351469f, 0.00553417206f, - 0.00545429764f, 0.00537389750f, 0.00529297767f, 0.00521154935f, 0.00512961717f, 0.00504719047f, 0.00496427855f, 0.00488088885f, 0.00479702698f, 0.00471270457f, - 0.00462792581f, 0.00454270281f, 0.00445704022f, 0.00437094783f, 0.00428443868f, 0.00419751182f, 0.00411018124f, 0.00402245624f, 0.00393434148f, 0.00384584907f, - 0.00375698437f, 0.00366775948f, 0.00357818161f, 0.00348825636f, 0.00339799491f, 0.00330740795f, 0.00321650016f, 0.00312528457f, 0.00303376769f, 0.00294195651f, - 0.00284986361f, 0.00275749387f, 0.00266485848f, 0.00257196836f, 0.00247882819f, 0.00238545146f, 0.00229184469f, 0.00219801464f, 0.00210397528f, 0.00200973079f, - 0.00191529247f, 0.00182067417f, 0.00172587589f, 0.00163091114f, 0.00153579167f, 0.00144052168f, 0.00134511536f, 0.00124957680f, 0.00115392031f, 0.00105815264f, - 0.000962280610f, 0.000866315851f, 0.000770269835f, 0.000674147333f, 0.000577962142f, 0.000481721276f, 0.000385431631f, 0.000289107207f, 0.000192752559f, 9.63793209e-05f, - -8.58271121e-10f, -9.63833809e-05f, -0.000192754276f, -0.000289106567f, -0.000385433348f, -0.000481720665f, -0.000577961560f, -0.000674149022f, -0.000770269253f, -0.000866317481f, - -0.000962282298f, -0.00105815206f, -0.00115392206f, -0.00124957855f, -0.00134511688f, -0.00144052564f, -0.00153579318f, -0.00163091510f, -0.00172587752f, -0.00182067591f, - -0.00191529409f, -0.00200973242f, -0.00210397458f, -0.00219801627f, -0.00229184399f, -0.00238545309f, -0.00247883215f, -0.00257196999f, -0.00266486243f, -0.00275749573f, - -0.00284986524f, -0.00294196024f, -0.00303376955f, -0.00312528410f, -0.00321650179f, -0.00330740749f, -0.00339799630f, -0.00348825776f, -0.00357818091f, -0.00366776134f, - -0.00375698577f, -0.00384585070f, -0.00393434474f, -0.00402245764f, -0.00411018496f, -0.00419751368f, -0.00428444007f, -0.00437094970f, -0.00445704209f, -0.00454270234f, - -0.00462792721f, -0.00471270364f, -0.00479702838f, -0.00488089072f, -0.00496428041f, -0.00504719326f, -0.00512961810f, -0.00521155121f, -0.00529298093f, -0.00537389843f, - -0.00545430044f, -0.00553417299f, -0.00561351422f, -0.00569231622f, -0.00577056967f, -0.00584826432f, -0.00592539785f, -0.00600195816f, -0.00607794197f, -0.00615333952f, - -0.00622814288f, -0.00630234741f, -0.00637594238f, -0.00644892501f, -0.00652128598f, -0.00659301504f, -0.00666411035f, -0.00673456537f, -0.00680436846f, -0.00687351823f, - -0.00694200583f, -0.00700982241f, -0.00707696518f, -0.00714342389f, -0.00720919576f, -0.00727427332f, -0.00733864726f, -0.00740231574f, -0.00746526942f, -0.00752750272f, - -0.00758901238f, -0.00764979143f, -0.00770983240f, -0.00776912784f, -0.00782767776f, -0.00788547192f, -0.00794250704f, -0.00799877662f, -0.00805427227f, -0.00810899492f, - -0.00816293526f, -0.00821608957f, -0.00826845132f, -0.00832001399f, -0.00837077387f, -0.00842073094f, -0.00846987497f, -0.00851820316f, -0.00856571086f, -0.00861239061f, - -0.00865824241f, -0.00870325882f, -0.00874743797f, -0.00879077241f, -0.00883325841f, -0.00887489505f, -0.00891567394f, -0.00895559601f, -0.00899465475f, -0.00903284643f, - -0.00907016639f, -0.00910661276f, -0.00914218184f, -0.00917686988f, -0.00921067316f, -0.00924358703f, -0.00927561242f, -0.00930674374f, -0.00933697633f, -0.00936631020f, - -0.00939473975f, -0.00942226499f, -0.00944888219f, -0.00947458949f, -0.00949938316f, -0.00952326041f, -0.00954621937f, -0.00956825912f, -0.00958937779f, -0.00960957073f, - -0.00962883793f, -0.00964717567f, -0.00966458581f, -0.00968106370f, -0.00969660748f, -0.00971121807f, -0.00972489174f, -0.00973762851f, -0.00974942744f, -0.00976028573f, - -0.00977020338f, -0.00977917947f, -0.00978721306f, -0.00979430322f, -0.00980044995f, -0.00980565138f, -0.00980990846f, -0.00981321931f, -0.00981558487f, -0.00981700420f -}; - -const float Stereo_dmx_s_wnd_coef_eps_48k[L_FRAME48k * 3 / 4] = { - 0.00000000f, 4.28365238e-05f, 8.56712068e-05f, 0.000128502230f, 0.000171327745f, 0.000214145897f, 0.000256954925f, 0.000299752894f, 0.000342538056f, 0.000385308522f, - 0.000428062514f, 0.000470798172f, 0.000513513631f, 0.000556207087f, 0.000598876737f, 0.000641520717f, 0.000684137223f, 0.000726724451f, 0.000769280537f, 0.000811803620f, - 0.000854292011f, 0.000896743732f, 0.000939157035f, 0.000981530058f, 0.00102386123f, 0.00106614840f, 0.00110838993f, 0.00115058408f, 0.00119272876f, 0.00123482244f, - 0.00127686327f, 0.00131884927f, 0.00136077893f, 0.00140265026f, 0.00144446141f, 0.00148621085f, 0.00152789650f, 0.00156951661f, 0.00161106954f, 0.00165255368f, - 0.00169396668f, 0.00173530739f, 0.00177657383f, 0.00181776390f, 0.00185887620f, 0.00189990876f, 0.00194086006f, 0.00198172848f, 0.00202251156f, 0.00206320849f, - 0.00210381625f, 0.00214433460f, 0.00218476099f, 0.00222509354f, 0.00226533110f, 0.00230547134f, 0.00234551285f, 0.00238545402f, 0.00242529274f, 0.00246502785f, - 0.00250465749f, 0.00254417956f, 0.00258359266f, 0.00262289518f, 0.00266208523f, 0.00270116120f, 0.00274012191f, 0.00277896458f, 0.00281768874f, 0.00285629183f, - 0.00289477292f, 0.00293312967f, 0.00297136116f, 0.00300946506f, 0.00304743997f, 0.00308528449f, 0.00312299700f, 0.00316057540f, 0.00319801876f, 0.00323532475f, - 0.00327249244f, 0.00330952019f, 0.00334640569f, 0.00338314800f, 0.00341974548f, 0.00345619628f, 0.00349249900f, 0.00352865248f, 0.00356465438f, 0.00360050355f, - 0.00363619882f, 0.00367173832f, 0.00370712043f, 0.00374234351f, 0.00377740664f, 0.00381230796f, 0.00384704559f, 0.00388161885f, 0.00391602563f, 0.00395026430f, - 0.00398433441f, 0.00401823362f, 0.00405196054f, 0.00408551423f, 0.00411889236f, 0.00415209495f, 0.00418511871f, 0.00421796367f, 0.00425062794f, 0.00428310968f, - 0.00431540888f, 0.00434752228f, 0.00437944988f, 0.00441118982f, 0.00444274070f, 0.00447410159f, 0.00450527016f, 0.00453624642f, 0.00456702849f, 0.00459761405f, - 0.00462800311f, 0.00465819426f, 0.00468818564f, 0.00471797585f, 0.00474756397f, 0.00477694906f, 0.00480613019f, 0.00483510410f, 0.00486387173f, 0.00489243073f, - 0.00492078019f, 0.00494891917f, 0.00497684581f, 0.00500455918f, 0.00503205787f, 0.00505934143f, 0.00508640893f, 0.00511325756f, 0.00513988733f, 0.00516629731f, - 0.00519248564f, 0.00521845184f, 0.00524419453f, 0.00526971230f, 0.00529500423f, 0.00532006938f, 0.00534490682f, 0.00536951516f, 0.00539389346f, 0.00541804079f, - 0.00544195622f, 0.00546563789f, 0.00548908627f, 0.00551229948f, 0.00553527568f, 0.00555801531f, 0.00558051746f, 0.00560277933f, 0.00562480185f, 0.00564658362f, - 0.00566812325f, 0.00568941981f, 0.00571047375f, 0.00573128136f, 0.00575184496f, 0.00577216130f, 0.00579223083f, 0.00581205217f, 0.00583162485f, 0.00585094700f, - 0.00587001862f, 0.00588883879f, 0.00590740750f, 0.00592572242f, 0.00594378356f, 0.00596159045f, 0.00597914122f, 0.00599643635f, 0.00601347443f, 0.00603025546f, - 0.00604677759f, 0.00606304128f, 0.00607904466f, 0.00609478820f, 0.00611026958f, 0.00612549018f, 0.00614044815f, 0.00615514303f, 0.00616957434f, 0.00618374115f, - 0.00619764347f, 0.00621127989f, 0.00622465089f, 0.00623775460f, 0.00625059102f, 0.00626316015f, 0.00627546059f, 0.00628749235f, 0.00629925495f, 0.00631074747f, - 0.00632196991f, 0.00633292133f, 0.00634360174f, 0.00635401066f, 0.00636414625f, 0.00637401035f, 0.00638360064f, 0.00639291806f, 0.00640196120f, 0.00641073054f, - 0.00641922513f, 0.00642744405f, 0.00643538870f, 0.00644305674f, 0.00645044958f, 0.00645756535f, 0.00646440545f, 0.00647096802f, 0.00647725351f, 0.00648326147f, - 0.00648899190f, 0.00649444386f, 0.00649961783f, 0.00650451379f, 0.00650913082f, 0.00651346892f, 0.00651752809f, 0.00652130833f, 0.00652480870f, 0.00652803015f, - 0.00653097173f, 0.00653363345f, 0.00653601484f, 0.00653811684f, 0.00653993897f, 0.00654148031f, 0.00654274225f, 0.00654372340f, 0.00654442422f, 0.00654484471f, - 0.00654498488f, 0.00654484471f, 0.00654442422f, 0.00654372340f, 0.00654274225f, 0.00654148031f, 0.00653993897f, 0.00653811684f, 0.00653601484f, 0.00653363345f, - 0.00653097173f, 0.00652802968f, 0.00652480870f, 0.00652130833f, 0.00651752809f, 0.00651346892f, 0.00650913082f, 0.00650451332f, 0.00649961783f, 0.00649444386f, - 0.00648899190f, 0.00648326147f, 0.00647725351f, 0.00647096802f, 0.00646440499f, 0.00645756535f, 0.00645044912f, 0.00644305674f, 0.00643538870f, 0.00642744405f, - 0.00641922466f, 0.00641073054f, 0.00640196120f, 0.00639291806f, 0.00638360064f, 0.00637400988f, 0.00636414625f, 0.00635401020f, 0.00634360174f, 0.00633292086f, - 0.00632196991f, 0.00631074747f, 0.00629925495f, 0.00628749235f, 0.00627546012f, 0.00626315968f, 0.00625059055f, 0.00623775413f, 0.00622465042f, 0.00621127989f, - 0.00619764347f, 0.00618374115f, 0.00616957434f, 0.00615514303f, 0.00614044769f, 0.00612549018f, 0.00611027004f, 0.00609478774f, 0.00607904419f, 0.00606304081f, - 0.00604677759f, 0.00603025500f, 0.00601347489f, 0.00599643635f, 0.00597914122f, 0.00596158998f, 0.00594378309f, 0.00592572149f, 0.00590740703f, 0.00588883879f, - 0.00587001862f, 0.00585094653f, 0.00583162392f, 0.00581205124f, 0.00579223037f, 0.00577216130f, 0.00575184496f, 0.00573128182f, 0.00571047282f, 0.00568941981f, - 0.00566812325f, 0.00564658316f, 0.00562480185f, 0.00560277933f, 0.00558051653f, 0.00555801531f, 0.00553527661f, 0.00551229948f, 0.00548908627f, 0.00546563789f, - 0.00544195622f, 0.00541804079f, 0.00539389299f, 0.00536951469f, 0.00534490682f, 0.00532006891f, 0.00529500330f, 0.00526971091f, 0.00524419360f, 0.00521845091f, - 0.00519248564f, 0.00516629778f, 0.00513988733f, 0.00511325756f, 0.00508640800f, 0.00505934190f, 0.00503205787f, 0.00500455871f, 0.00497684488f, 0.00494891871f, - 0.00492077926f, 0.00489242980f, 0.00486387173f, 0.00483510457f, 0.00480612973f, 0.00477694906f, 0.00474756444f, 0.00471797585f, 0.00468818471f, 0.00465819333f, - 0.00462800311f, 0.00459761359f, 0.00456702709f, 0.00453624595f, 0.00450526970f, 0.00447410066f, 0.00444273977f, 0.00441119028f, 0.00437944988f, 0.00434752181f, - 0.00431540795f, 0.00428310968f, 0.00425062748f, 0.00421796273f, 0.00418511871f, 0.00415209448f, 0.00411889143f, 0.00408551283f, 0.00405196007f, 0.00401823269f, - 0.00398433302f, 0.00395026430f, 0.00391602563f, 0.00388161885f, 0.00384704513f, 0.00381230796f, 0.00377740664f, 0.00374234305f, 0.00370711950f, 0.00367173809f, - 0.00363619835f, 0.00360050285f, 0.00356465275f, 0.00352865178f, 0.00349249784f, 0.00345619605f, 0.00341974595f, 0.00338314800f, 0.00334640522f, 0.00330951903f, - 0.00327249290f, 0.00323532452f, 0.00319801806f, 0.00316057424f, 0.00312299654f, 0.00308528380f, 0.00304743880f, 0.00300946319f, 0.00297135999f, 0.00293312967f, - 0.00289477245f, 0.00285629253f, 0.00281768874f, 0.00277896435f, 0.00274012075f, 0.00270116120f, 0.00266208476f, 0.00262289424f, 0.00258359103f, 0.00254417886f, - 0.00250465632f, 0.00246502645f, 0.00242529227f, 0.00238545449f, 0.00234551262f, 0.00230547064f, 0.00226533134f, 0.00222509331f, 0.00218476006f, 0.00214433344f, - 0.00210381625f, 0.00206320756f, 0.00202251016f, 0.00198172801f, 0.00194085937f, 0.00189990760f, 0.00185887585f, 0.00181776448f, 0.00177657383f, 0.00173530704f, - 0.00169396598f, 0.00165255368f, 0.00161106919f, 0.00156951568f, 0.00152789650f, 0.00148621027f, 0.00144446036f, 0.00140264863f, 0.00136077835f, 0.00131884834f, - 0.00127686316f, 0.00123482186f, 0.00119272911f, 0.00115058396f, 0.00110838923f, 0.00106614875f, 0.00102386111f, 0.000981529476f, 0.000939155812f, 0.000896743557f, - 0.000854291196f, 0.000811802340f, 0.000769278675f, 0.000726723636f, 0.000684137398f, 0.000641520426f, 0.000598877436f, 0.000556207204f, 0.000513513223f, 0.000470797240f, - 0.000428062631f, 0.000385308114f, 0.000342537096f, 0.000299751409f, 0.000256954430f, 0.000214144908f, 0.000171326188f, 0.000128500149f, 8.56717088e-05f, 4.28364874e-05f, - -5.72180747e-10f, -4.28360690e-05f, -8.56712868e-05f, -0.000128502856f, -0.000171328895f, -0.000214146057f, -0.000256955565f, -0.000299754087f, -0.000342539803f, -0.000385309249f, - -0.000428063737f, -0.000470799918f, -0.000513512816f, -0.000556206855f, -0.000598876970f, -0.000641521532f, -0.000684137049f, -0.000726724742f, -0.000769281352f, -0.000811805017f, - -0.000854292419f, -0.000896744605f, -0.000939158490f, -0.000981530524f, -0.00102386216f, -0.00106614991f, -0.00110839040f, -0.00115058350f, -0.00119272876f, -0.00123482291f, - -0.00127686432f, -0.00131884939f, -0.00136077951f, -0.00140265131f, -0.00144446141f, -0.00148621143f, -0.00152789755f, -0.00156951835f, -0.00161107024f, -0.00165255321f, - -0.00169396691f, -0.00173530797f, -0.00177657336f, -0.00181776413f, -0.00185887702f, -0.00189990853f, -0.00194086053f, -0.00198172918f, -0.00202251296f, -0.00206320873f, - -0.00210381718f, -0.00214433600f, -0.00218476262f, -0.00222509308f, -0.00226533087f, -0.00230547180f, -0.00234551216f, -0.00238545402f, -0.00242529344f, -0.00246502901f, - -0.00250465726f, -0.00254418002f, -0.00258359360f, -0.00262289657f, -0.00266208570f, -0.00270116236f, -0.00274012331f, -0.00277896388f, -0.00281768828f, -0.00285629206f, - -0.00289477338f, -0.00293312944f, -0.00297136139f, -0.00300946552f, -0.00304744113f, -0.00308528473f, -0.00312299770f, -0.00316057657f, -0.00319802039f, -0.00323532545f, - -0.00327249360f, -0.00330952019f, -0.00334640499f, -0.00338314800f, -0.00341974548f, -0.00345619721f, -0.00349249900f, -0.00352865248f, -0.00356465508f, -0.00360050471f, - -0.00363619928f, -0.00367173925f, -0.00370712159f, -0.00374234398f, -0.00377740758f, -0.00381230772f, -0.00384704629f, -0.00388161838f, -0.00391602563f, -0.00395026524f, - -0.00398433534f, -0.00401823409f, -0.00405196147f, -0.00408551469f, -0.00411889283f, -0.00415209495f, -0.00418511964f, -0.00421796506f, -0.00425062841f, -0.00428310968f, - -0.00431540888f, -0.00434752274f, -0.00437944988f, -0.00441119028f, -0.00444274163f, -0.00447410159f, -0.00450527063f, -0.00453624688f, -0.00456702895f, -0.00459761452f, - -0.00462800404f, -0.00465819519f, -0.00468818611f, -0.00471797585f, -0.00474756444f, -0.00477694953f, -0.00480612973f, -0.00483510410f, -0.00486387173f, -0.00489243167f, - -0.00492078019f, -0.00494891917f, -0.00497684628f, -0.00500456011f, -0.00503205974f, -0.00505934376f, -0.00508640893f, -0.00511325803f, -0.00513988826f, -0.00516629638f, - -0.00519248517f, -0.00521845184f, -0.00524419453f, -0.00526971230f, -0.00529500470f, -0.00532007031f, -0.00534490822f, -0.00536951516f, -0.00539389392f, -0.00541804126f, - -0.00544195529f, -0.00546563743f, -0.00548908627f, -0.00551229948f, -0.00553527614f, -0.00555801624f, -0.00558051793f, -0.00560278073f, -0.00562480185f, -0.00564658362f, - -0.00566812325f, -0.00568942074f, -0.00571047375f, -0.00573128276f, -0.00575184450f, -0.00577216130f, -0.00579223130f, -0.00581205264f, -0.00583162485f, -0.00585094653f, - -0.00587001862f, -0.00588883925f, -0.00590740610f, -0.00592572149f, -0.00594378309f, -0.00596158998f, -0.00597914122f, -0.00599643681f, -0.00601347489f, -0.00603025593f, - -0.00604677759f, -0.00606304081f, -0.00607904466f, -0.00609478820f, -0.00611027051f, -0.00612549065f, -0.00614044908f, -0.00615514303f, -0.00616957434f, -0.00618374161f, - -0.00619764347f, -0.00621128036f, -0.00622465089f, -0.00623775553f, -0.00625059241f, -0.00626316015f, -0.00627546106f, -0.00628749281f, -0.00629925542f, -0.00631074747f, - -0.00632197037f, -0.00633292180f, -0.00634360127f, -0.00635400973f, -0.00636414625f, -0.00637400988f, -0.00638360064f, -0.00639291806f, -0.00640196120f, -0.00641073007f, - -0.00641922466f, -0.00642744405f, -0.00643538870f, -0.00644305721f, -0.00645045005f, -0.00645756582f, -0.00646440592f, -0.00647096802f, -0.00647725351f, -0.00648326147f, - -0.00648899190f, -0.00649444433f, -0.00649961829f, -0.00650451379f, -0.00650913082f, -0.00651346892f, -0.00651752809f, -0.00652130833f, -0.00652480870f, -0.00652803015f, - -0.00653097173f, -0.00653363345f, -0.00653601484f, -0.00653811684f, -0.00653993897f, -0.00654148031f, -0.00654274225f, -0.00654372340f, -0.00654442422f, -0.00654484471f -}; const float Stereo_dmx_s_wnd_coef_16k[L_FRAME16k >> 4] = { 0.00154133327f, 0.0138150426f, 0.0380602330f, 0.0736799166f, 0.119797014f, 0.175276011f, 0.238750681f, 0.308658302f, 0.383277327f, 0.460770488f, diff --git a/lib_enc/ivas_rom_enc.h b/lib_enc/ivas_rom_enc.h index 71942642253d85741b0dc9949c7b640114837aef..d240fb69187fded50b89d4c3ae5056002b238f30 100644 --- a/lib_enc/ivas_rom_enc.h +++ b/lib_enc/ivas_rom_enc.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -120,9 +120,6 @@ extern const uint16_t ECSQ_tab_vals[ECSQ_PARAM_COUNT - 1][1 + ECSQ_TAB_VALS_SIZE * Stereo downmix to EVS ROM tables *----------------------------------------------------------------------------------*/ -extern const float Stereo_dmx_s_wnd_coef_eps_16k[L_FRAME16k * 3 / 4]; -extern const float Stereo_dmx_s_wnd_coef_eps_32k[L_FRAME32k * 3 / 4]; -extern const float Stereo_dmx_s_wnd_coef_eps_48k[L_FRAME48k * 3 / 4]; extern const float Stereo_dmx_s_wnd_coef_16k[L_FRAME16k >> 4]; extern const float Stereo_dmx_s_wnd_coef_32k[L_FRAME32k >> 4]; extern const float Stereo_dmx_s_wnd_coef_48k[L_FRAME48k >> 4]; diff --git a/lib_enc/ivas_sba_enc.c b/lib_enc/ivas_sba_enc.c index b28565ecacf16d36ce208a259fc66bb56f4475e5..8c37c6bf0fad126e70e4699e9379f4aedb49ce7b 100644 --- a/lib_enc/ivas_sba_enc.c +++ b/lib_enc/ivas_sba_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,12 +43,8 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" -/*-----------------------------------------------------------------------* - * Local function prototypes - *-----------------------------------------------------------------------*/ -static void ivas_sba_dmx_enc( float sba_data[][L_FRAME48k], const int16_t nchan_transport, const int16_t input_frame ); /*-------------------------------------------------------------------* * ivas_sba_getTCs() @@ -62,30 +58,25 @@ void ivas_sba_getTCs( const int16_t input_frame /* i : frame length */ ) { - ivas_sba_zero_vert_comp( sba_data, st_ivas->hEncoderConfig->sba_order, st_ivas->hEncoderConfig->sba_planar, input_frame ); - - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + if ( st_ivas->hEncoderConfig->sba_planar ) { - st_ivas->nchan_transport = ivas_get_spar_num_TCs( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->hEncoderConfig->sba_order ); + ivas_sba_zero_vert_comp( sba_data, st_ivas->sba_analysis_order, st_ivas->hEncoderConfig->sba_planar, input_frame ); + } + + st_ivas->nchan_transport = ivas_get_sba_num_TCs( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->sba_analysis_order ); - if ( st_ivas->nchan_transport >= 3 ) + if ( st_ivas->nchan_transport >= 3 ) + { + /*convert WYZX downmix to WYXZ*/ + int16_t i = 0; + float temp; + for ( i = 0; i < input_frame; i++ ) { - /*convert WYZX downmix to WYXZ*/ - int16_t i = 0; - float temp; - for ( i = 0; i < input_frame; i++ ) - { - temp = sba_data[2][i]; - sba_data[2][i] = sba_data[3][i]; - sba_data[3][i] = temp; - } + temp = sba_data[2][i]; + sba_data[2][i] = sba_data[3][i]; + sba_data[3][i] = temp; } } - else - { - st_ivas->nchan_transport = ivas_dirac_getNumTransportChannels( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->hEncoderConfig->sba_order, st_ivas->hEncoderConfig->sba_planar ); - ivas_sba_dmx_enc( sba_data, st_ivas->nchan_transport, input_frame ); - } #ifdef DEBUG_MODE_DIRAC for ( int16_t n = 0; n < st_ivas->nchan_transport; n++ ) @@ -105,107 +96,6 @@ void ivas_sba_getTCs( return; } - -/*-------------------------------------------------------------------* - * ivas_sba_dmx_enc() - * - * - *-------------------------------------------------------------------*/ - -static void ivas_sba_dmx_enc( - float sba_data[][L_FRAME48k], /* i : SBA signals */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int16_t input_frame /* i : frame length */ -) -{ - int16_t i; - float dmx_l, dmx_r; - float a, b; - float tmp_f[DIRAC_MAX_TRANS_CHANS]; - - if ( nchan_transport >= 7 ) - { - for ( i = 0; i < input_frame; i++ ) - { - tmp_f[0] = 0.282095f * sba_data[0][i] + 0.000000f * sba_data[1][i] + 0.420663f * sba_data[3][i] + 0.000000f * sba_data[4][i] + 0.334240f * sba_data[8][i] + 0.000000f * sba_data[9][i] + 0.179369f * sba_data[15][i]; - tmp_f[1] = 0.282095f * sba_data[0][i] + 0.328887f * sba_data[1][i] + 0.262279f * sba_data[3][i] + 0.325860f * sba_data[4][i] + -0.074375f * sba_data[8][i] + 0.077825f * sba_data[9][i] + -0.161606f * sba_data[15][i]; - tmp_f[2] = 0.282095f * sba_data[0][i] + 0.410116f * sba_data[1][i] + -0.093606f * sba_data[3][i] + -0.145021f * sba_data[4][i] + -0.301140f * sba_data[8][i] + -0.140237f * sba_data[9][i] + 0.111835f * sba_data[15][i]; - tmp_f[3] = 0.282095f * sba_data[0][i] + 0.182519f * sba_data[1][i] + -0.379004f * sba_data[3][i] + -0.261320f * sba_data[4][i] + 0.208395f * sba_data[8][i] + 0.174872f * sba_data[9][i] + -0.039913f * sba_data[15][i]; - tmp_f[4] = 0.282095f * sba_data[0][i] + -0.182519f * sba_data[1][i] + -0.379004f * sba_data[3][i] + 0.261320f * sba_data[4][i] + 0.208395f * sba_data[8][i] + -0.174872f * sba_data[9][i] + -0.039913f * sba_data[15][i]; - tmp_f[5] = 0.282095f * sba_data[0][i] + -0.410116f * sba_data[1][i] + -0.093606f * sba_data[3][i] + 0.145021f * sba_data[4][i] + -0.301140f * sba_data[8][i] + 0.140237f * sba_data[9][i] + 0.111835f * sba_data[15][i]; - tmp_f[6] = 0.282095f * sba_data[0][i] + -0.328887f * sba_data[1][i] + 0.262279f * sba_data[3][i] + -0.325860f * sba_data[4][i] + -0.074375f * sba_data[8][i] + -0.077825f * sba_data[9][i] + -0.161606f * sba_data[15][i]; - sba_data[7][i] = sba_data[2][i]; /* will be dropped for planarSBA */ - sba_data[0][i] = tmp_f[0]; - sba_data[1][i] = tmp_f[1]; - sba_data[2][i] = tmp_f[2]; - sba_data[3][i] = tmp_f[3]; - sba_data[4][i] = tmp_f[4]; - sba_data[5][i] = tmp_f[5]; - sba_data[6][i] = tmp_f[6]; - } - - return; - } - else if ( nchan_transport >= 5 ) - { - for ( i = 0; i < input_frame; i++ ) - { - tmp_f[0] = 0.282095f * sba_data[0][i] + 0.000000f * sba_data[1][i] + 0.378166f * sba_data[3][i] + 0.000000f * sba_data[4][i] + 0.217722f * sba_data[8][i]; - tmp_f[1] = 0.282095f * sba_data[0][i] + 0.359658f * sba_data[1][i] + 0.116860f * sba_data[3][i] + 0.127974f * sba_data[4][i] + -0.176140f * sba_data[8][i]; - tmp_f[2] = 0.282095f * sba_data[0][i] + 0.222281f * sba_data[1][i] + -0.305943f * sba_data[3][i] + -0.207066f * sba_data[4][i] + 0.067280f * sba_data[8][i]; - tmp_f[3] = 0.282095f * sba_data[0][i] + -0.222281f * sba_data[1][i] + -0.305943f * sba_data[3][i] + 0.207066f * sba_data[4][i] + 0.067280f * sba_data[8][i]; - tmp_f[4] = 0.282095f * sba_data[0][i] + -0.359658f * sba_data[1][i] + 0.116860f * sba_data[3][i] + -0.127974f * sba_data[4][i] + -0.176140f * sba_data[8][i]; - sba_data[5][i] = sba_data[2][i]; /* will be dropped for planarSBA */ - sba_data[0][i] = tmp_f[0]; - sba_data[1][i] = tmp_f[1]; - sba_data[2][i] = tmp_f[2]; - sba_data[3][i] = tmp_f[3]; - sba_data[4][i] = tmp_f[4]; - } - - return; - } - else if ( nchan_transport >= 3 ) - { - for ( i = 0; i < input_frame; i++ ) - { - dmx_l = 0.5f * sba_data[1][i]; - dmx_r = 0.5f * sba_data[2][i]; - a = 0.5f * sba_data[0][i]; - b = 0.25f * sba_data[3][i]; - - sba_data[0][i] = a + b; - sba_data[1][i] = sba_data[0][i] - dmx_l; - sba_data[0][i] += dmx_l; - - sba_data[2][i] = a - b; - sba_data[3][i] = sba_data[2][i] - dmx_r; /* will be dropped for planarSBA & irrelevant*/ - sba_data[2][i] += dmx_r; /* irrelevant for planarSBA*/ - } - - return; - } - else if ( nchan_transport == 2 ) - { - for ( i = 0; i < input_frame; i++ ) - { - dmx_l = 0.5f * ( sba_data[0][i] + sba_data[1][i] ); /* cardioid_left = W + Y */ - sba_data[1][i] = 0.5f * ( sba_data[0][i] - sba_data[1][i] ); /* cardioid_right = W - Y */ - sba_data[0][i] = dmx_l; - } - - return; - } - else if ( nchan_transport == 1 ) - { - /* do nothing; simply use omni */ - return; - } - - return; -} - - /*-------------------------------------------------------------------* * ivas_sba_enc_reconfigure() * @@ -216,314 +106,220 @@ ivas_error ivas_sba_enc_reconfigure( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ) { - int16_t ntransport; - int16_t ntransport_old; - int16_t nSCE_old; - int16_t nCPE_old; - int16_t sce_id; - int16_t cpe_id; - int16_t n; - Indice *ind_list_metadata; + int16_t n, nSCE_old, nCPE_old, nchan_transport_old; int32_t ivas_total_brate; ivas_error error; + ENCODER_CONFIG_HANDLE hEncoderConfig; error = IVAS_ERR_OK; + hEncoderConfig = st_ivas->hEncoderConfig; + ivas_total_brate = hEncoderConfig->ivas_total_brate; - ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; - - if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) + if ( ivas_total_brate != hEncoderConfig->last_ivas_total_brate ) { - ntransport = st_ivas->nchan_transport; - ntransport_old = st_ivas->nchan_transport; + DIRAC_ENC_HANDLE hDirAC = st_ivas->hDirAC; + SPAR_ENC_HANDLE hSpar; + SBA_MODE sba_mode_old; + int16_t analysis_order_old; + int16_t spar_reconfig_flag; + + spar_reconfig_flag = 0; + nchan_transport_old = st_ivas->nchan_transport; nCPE_old = st_ivas->nCPE; nSCE_old = st_ivas->nSCE; - ind_list_metadata = NULL; + sba_mode_old = st_ivas->sba_mode; - ivas_dirac_enc_reconfigure( st_ivas ); - ntransport = st_ivas->nchan_transport; + st_ivas->sba_analysis_order = ivas_sba_get_analysis_order( ivas_total_brate, hEncoderConfig->sba_order ); +#ifndef LBR_SBA + st_ivas->sba_mode = ivas_sba_mode_select( ivas_total_brate ); +#else + st_ivas->sba_mode = ivas_sba_mode_select(); +#endif + analysis_order_old = ivas_sba_get_analysis_order( hEncoderConfig->last_ivas_total_brate, hEncoderConfig->sba_order ); - if ( ntransport == ntransport_old ) + if ( analysis_order_old != st_ivas->sba_analysis_order ) { - for ( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) - { - copy_encoder_config( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 ); - st_ivas->hSCE[sce_id]->element_brate = ivas_total_brate / st_ivas->nchan_transport; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ - } + int16_t i, n_old; + float **old_mem_hp20_in; - for ( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + n_old = ivas_sba_get_nchan_metadata( analysis_order_old ); + n = ivas_sba_get_nchan_metadata( st_ivas->sba_analysis_order ); + + if ( n > n_old ) { - st_ivas->hCPE[cpe_id]->element_brate = ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS; - /* prepare bitstream buffers */ - for ( n = 0; n < CPE_CHANNELS; n++ ) + /* save old mem_hp_20 pointer */ + old_mem_hp20_in = st_ivas->mem_hp20_in; + st_ivas->mem_hp20_in = NULL; + + if ( ( st_ivas->mem_hp20_in = (float **) malloc( n * sizeof( float * ) ) ) == NULL ) { - copy_encoder_config( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); + } - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + for ( i = 0; i < n_old; i++ ) + { + st_ivas->mem_hp20_in[i] = old_mem_hp20_in[i]; + old_mem_hp20_in[i] = NULL; + } + /* create additional hp20 memories */ + for ( ; i < n; i++ ) + { + if ( ( st_ivas->mem_hp20_in[i] = (float *) malloc( L_HP20_MEM * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); + } + + set_f( st_ivas->mem_hp20_in[i], 0.0f, L_HP20_MEM ); } - } - if ( st_ivas->nCPE > 1 ) + free( old_mem_hp20_in ); + old_mem_hp20_in = NULL; + } + else if ( n < n_old ) { - if ( ( error = mct_enc_reconfigure( st_ivas, 0 ) ) != IVAS_ERR_OK ) + /* save old mem_hp_20 pointer */ + old_mem_hp20_in = st_ivas->mem_hp20_in; + st_ivas->mem_hp20_in = NULL; + + if ( ( st_ivas->mem_hp20_in = (float **) malloc( n * sizeof( float * ) ) ) == NULL ) { - return error; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HP20 filter memory\n" ) ); + } + + for ( i = 0; i < n; i++ ) + { + st_ivas->mem_hp20_in[i] = old_mem_hp20_in[i]; + old_mem_hp20_in[i] = NULL; + } + /* remove superfluous hp20 memories */ + for ( ; i < n_old; i++ ) + { + free( old_mem_hp20_in[i] ); + old_mem_hp20_in[i] = NULL; } + + free( old_mem_hp20_in ); + old_mem_hp20_in = NULL; } } - else + + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - Indice *ind_list; - int16_t nb_bits_tot; - int16_t next_ind; - int16_t last_ind; - BSTR_ENC_HANDLE hBstr; - BSTR_ENC_HANDLE hMetaData; - - ind_list = NULL; - hBstr = NULL; - hMetaData = NULL; - - /* get the index list pointers */ - if ( nSCE_old ) - { - hBstr = st_ivas->hSCE[0]->hCoreCoder[0]->hBstr; - hMetaData = st_ivas->hSCE[0]->hMetaData; - } - else if ( nCPE_old ) - { - hBstr = st_ivas->hCPE[0]->hCoreCoder[0]->hBstr; - hMetaData = st_ivas->hCPE[nCPE_old - 1]->hMetaData; - } -#ifdef DEBUGGING - else + if ( st_ivas->hSpar == NULL ) { - assert( 0 && "At least one SCE or one CPE should have existed before!\n" ); + if ( ( error = ivas_spar_enc_open( st_ivas, spar_reconfig_flag ) ) != IVAS_ERR_OK ) + { + return error; + } } -#endif - /* save bitstream information */ - ind_list = hBstr->ind_list; - nb_bits_tot = hBstr->nb_bits_tot; - next_ind = hBstr->next_ind; - last_ind = hBstr->last_ind; - ind_list_metadata = hMetaData->ind_list; + ivas_spar_config( ivas_total_brate, min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ), + &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->hSpar->core_nominal_brate, -1 ); - /* destroy superfluous core coder elements */ - for ( sce_id = st_ivas->nSCE; sce_id < nSCE_old; sce_id++ ) + for ( n = 0; n < DIRAC_MAX_ANA_CHANS; n++ ) { - destroy_sce_enc( st_ivas->hSCE[sce_id] ); - st_ivas->hSCE[sce_id] = NULL; + if ( hDirAC->sba_synchro_buffer[n] != NULL ) + { + free( hDirAC->sba_synchro_buffer[n] ); + hDirAC->sba_synchro_buffer[n] = NULL; + } } + hDirAC->num_samples_synchro_delay = 0; + } + else + { + ivas_spar_enc_close( &( st_ivas->hSpar ), hEncoderConfig->input_Fs, hEncoderConfig->nchan_inp, spar_reconfig_flag ); + } - for ( cpe_id = st_ivas->nCPE; cpe_id < nCPE_old; cpe_id++ ) - { - destroy_cpe_enc( st_ivas->hCPE[cpe_id] ); - st_ivas->hCPE[cpe_id] = NULL; - } + hSpar = st_ivas->hSpar; - if ( st_ivas->nCPE <= 1 && st_ivas->hMCT != NULL ) - { - ivas_mct_enc_close( st_ivas->hMCT ); - st_ivas->hMCT = NULL; - } - - /* special case, if we have MCT now and had a single CPE before, remove the MDCT Stereo handles */ - if ( st_ivas->nCPE > 1 && nCPE_old == 1 ) - { - count_free( st_ivas->hCPE[0]->hStereoMdct ); - st_ivas->hCPE[0]->hStereoMdct = NULL; - } + if ( st_ivas->nchan_transport == 1 ) + { + hEncoderConfig->element_mode_init = IVAS_SCE; + } + else + { + hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + } - /* create missing core coder elements and set element bitrates for alrady existing ones */ - if ( st_ivas->nSCE > 0 ) + if ( ( sba_mode_old != st_ivas->sba_mode ) || ( nchan_transport_old != st_ivas->nchan_transport ) ) + { + /* FB mixer handle */ + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) { - int16_t nSCE_existing; - nSCE_existing = min( nSCE_old, st_ivas->nSCE ); - for ( sce_id = 0; sce_id < nSCE_existing; sce_id++ ) + if ( hDirAC->hFbMixer != NULL ) { - copy_encoder_config( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 ); - st_ivas->hSCE[sce_id]->element_brate = ivas_total_brate / st_ivas->nchan_transport; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + ivas_FB_mixer_close( &( hDirAC->hFbMixer ), hEncoderConfig->input_Fs, 0 ); + hDirAC->hFbMixer = NULL; } - for ( sce_id = nSCE_existing; sce_id < st_ivas->nSCE; sce_id++ ) - { - if ( ( error = create_sce_enc( st_ivas, sce_id, ivas_total_brate / st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) - { - return error; - } - /* prepare bitstream buffers */ - st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->ind_list = ind_list + sce_id * MAX_NUM_INDICES; + if ( sba_mode_old == SBA_MODE_SPAR ) + { + spar_reconfig_flag = 1; + ivas_spar_enc_close( &( st_ivas->hSpar ), hEncoderConfig->input_Fs, hEncoderConfig->nchan_inp, spar_reconfig_flag ); - /* only reset indices if it is not the first index list, this already contains the IVAS format bits */ - if ( sce_id > 0 ) - { - reset_indices_enc( st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr, MAX_NUM_INDICES ); - } - else + if ( ( error = ivas_spar_enc_open( st_ivas, spar_reconfig_flag ) ) != IVAS_ERR_OK ) { - st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->last_ind = last_ind; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->nb_bits_tot = nb_bits_tot; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->next_ind = next_ind; + return error; } - - st_ivas->hSCE[sce_id]->hMetaData->ind_list = ind_list_metadata + sce_id * MAX_BITS_METADATA; - reset_indices_enc( st_ivas->hSCE[sce_id]->hMetaData, MAX_BITS_METADATA ); } } - - if ( st_ivas->nCPE > 0 ) + else { - int16_t nCPE_existing; - nCPE_existing = min( nCPE_old, st_ivas->nCPE ); - for ( cpe_id = 0; cpe_id < nCPE_existing; cpe_id++ ) + if ( hDirAC->hFbMixer == NULL ) { - st_ivas->hCPE[cpe_id]->element_brate = ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS; + IVAS_FB_CFG *fb_cfg; - /* prepare bitstream buffers */ - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - copy_encoder_config( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 ); - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ - } - } - - for ( cpe_id = nCPE_existing; cpe_id < st_ivas->nCPE; cpe_id++ ) - { - if ( ( error = create_cpe_enc( st_ivas, cpe_id, ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_fb_set_cfg( &fb_cfg, SBA_FORMAT, SBA_MODE_DIRAC, DIRAC_MAX_ANA_CHANS, 0, 0, hEncoderConfig->input_Fs ) ) != IVAS_ERR_OK ) { return error; } - /* prepare bitstream buffers */ - for ( n = 0; n < CPE_CHANNELS; n++ ) + /* Allocate and initialize FB mixer handle */ + if ( ( error = ivas_FB_mixer_open( &( hDirAC->hFbMixer ), hEncoderConfig->input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->ind_list = ind_list + ( cpe_id * CPE_CHANNELS + n ) * MAX_NUM_INDICES; - if ( cpe_id * CPE_CHANNELS + n > 0 ) - { - reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, MAX_NUM_INDICES ); - } - else - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->last_ind = last_ind; - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->nb_bits_tot = nb_bits_tot; - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->next_ind = next_ind; - } - if ( st_ivas->hEncoderConfig->Opt_DTX_ON ) - { - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_spar_flag = 1; - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_dirac_flag = 1; - } - else - { - st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_dirac_flag = 1; - } - } + return error; } } - } - if ( st_ivas->nCPE > 1 && nCPE_old <= 1 ) - { - if ( nCPE_old == 1 ) + if ( hDirAC->num_samples_synchro_delay == 0 ) { - /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handles for MCT */ - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; - - st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[0]->element_brate / FRAMES_PER_SEC ); - st_ivas->hCPE[0]->hCoreCoder[n]->igf = getIgfPresent( st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, - st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal * FRAMES_PER_SEC, - st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, - st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode, - st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode ); + hDirAC->num_samples_synchro_delay = NS2SA( hEncoderConfig->input_Fs, IVAS_FB_ENC_DELAY_NS ); - if ( st_ivas->hCPE[0]->hCoreCoder[n]->igf ) + for ( n = 0; n < DIRAC_MAX_ANA_CHANS; n++ ) + { + if ( ( hDirAC->sba_synchro_buffer[n] = (float *) malloc( hDirAC->num_samples_synchro_delay * sizeof( float ) ) ) == NULL ) { - IGFEncSetMode( st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, - st_ivas->hCPE[0]->element_brate, - st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, - st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, - st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hDirAC synchro buffer\n" ) ); } + set_zero( hDirAC->sba_synchro_buffer[n], hDirAC->num_samples_synchro_delay ); } - } - - if ( ( error = create_mct_enc( st_ivas ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( st_ivas->hMCT != NULL && st_ivas->nCPE > 1 ) - { - if ( ( error = mct_enc_reconfigure( st_ivas, st_ivas->nCPE != nCPE_old ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - /* metadata handling for CPEs */ - if ( st_ivas->nCPE > 0 ) - { - if ( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData == NULL ) - { - if ( ( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData = (BSTR_ENC_HANDLE) count_malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) + for ( ; n < DIRAC_MAX_ANA_CHANS; n++ ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MetaData structure\n" ) ); - } - } - - st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData->ind_list = ind_list_metadata; - reset_indices_enc( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData, MAX_BITS_METADATA ); - - for ( cpe_id = 0; cpe_id < st_ivas->nCPE - 1; cpe_id++ ) - { - if ( st_ivas->hCPE[cpe_id]->hMetaData != NULL ) - { - count_free( st_ivas->hCPE[cpe_id]->hMetaData ); - st_ivas->hCPE[cpe_id]->hMetaData = NULL; + hDirAC->sba_synchro_buffer[n] = NULL; } } } + } - /* special case, if we have a single CPE and had MCT before we need to init the MDCT stereo handles here */ - if ( st_ivas->nCPE == 1 && nCPE_old > 1 ) - { - if ( ( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); - } - - /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handle */ - for ( n = 0; n < CPE_CHANNELS; n++ ) - { - st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; + if ( ( error = ivas_dirac_enc_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } - st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = (int16_t) ( st_ivas->hCPE[0]->element_brate / FRAMES_PER_SEC ); - st_ivas->hCPE[0]->hCoreCoder[n]->igf = getIgfPresent( st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, - st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal * FRAMES_PER_SEC, - st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, - st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode, - st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode ); + if ( st_ivas->sba_mode == SBA_MODE_SPAR ) + { + mvs2s( hDirAC->dirac_to_spar_md_bands, hSpar->dirac_to_spar_md_bands, DIRAC_MAX_NBANDS ); + hSpar->enc_param_start_band = hDirAC->hConfig->enc_param_start_band; + } - if ( st_ivas->hCPE[0]->hCoreCoder[n]->igf ) - { - IGFEncSetMode( st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, - st_ivas->hCPE[0]->element_brate, - st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, - st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, - st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); - } - /* reset mct_chan_mode */ - st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; - } + /*-----------------------------------------------------------------* + * Allocate, initialize, and configure SCE/CPE/MCT handles + *-----------------------------------------------------------------*/ - initMdctStereoEncData( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct, st_ivas->hEncoderConfig->ivas_format, st_ivas->hCPE[st_ivas->nCPE - 1]->element_mode, st_ivas->hCPE[st_ivas->nCPE - 1]->element_brate, st_ivas->hEncoderConfig->max_bwidth, 0, NULL, 1 ); - } + if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, ivas_total_brate / st_ivas->nchan_transport, ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS, MC_MODE_NONE ) ) != IVAS_ERR_OK ) + { + return error; } } diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index a8a43ccf2b790d36ce893ddcf809cff8a8d7330d..c8577a85bae41f124907bdd60809cca4d529b7d6 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -60,7 +60,6 @@ ivas_error ivas_sce_enc( { float old_inp_12k8[1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ float old_inp_16k[1][L_INP]; /* buffer of input signal @ 16kHz */ - float Etot[1]; /* total energy; correlation shift */ float ener[1]; /* residual energy from Levinson-Durbin */ float relE[1]; /* frame relative energy */ float A[1][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ @@ -91,7 +90,7 @@ ivas_error ivas_sce_enc( ivas_error error; int16_t flag_16k_smc; - wmops_sub_start( "ivas_sce_enc" ); + push_wmops( "ivas_sce_enc" ); error = IVAS_ERR_OK; @@ -155,7 +154,7 @@ ivas_error ivas_sce_enc( } else if ( st_ivas->hSpar != NULL ) { - st->bits_frame_nominal = (int16_t) ( st_ivas->hSpar->hSparFoa->core_nominal_brate / FRAMES_PER_SEC ); + st->bits_frame_nominal = (int16_t) ( st_ivas->hSpar->core_nominal_brate / FRAMES_PER_SEC ); } else { @@ -165,28 +164,28 @@ ivas_error ivas_sce_enc( /* set "total_brate" */ st->total_brate = hSCE->element_brate - nb_bits_metadata * FRAMES_PER_SEC; + /* set flag for sampling rate of OL S/M classifier */ + flag_16k_smc = 0; + if ( st_ivas->hEncoderConfig->ivas_format == SBA_FORMAT && ( st_ivas->hEncoderConfig->ivas_total_brate == IVAS_24k4 || st_ivas->hEncoderConfig->ivas_total_brate == IVAS_32k ) && hSCE->element_brate == hSCE->last_element_brate ) + { + flag_16k_smc = 1; + } + #ifdef DEBUG_MODE_INFO - dbgwrite( st->input - NS2SA( st->input_Fs, ACELP_LOOK_NS ), 4, input_frame, 1, "res/input_DMX" ); + dbgwrite( st->input - NS2SA( st->input_Fs, ACELP_LOOK_NS ), sizeof( float ), input_frame, 1, "res/input_DMX" ); + dbgwrite( &st->element_mode, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "element_mode", 0, st->id_element, ENC ) ); #endif - /* set flag for sampling rate of OL S/M classifier */ - flag_16k_smc = ( st_ivas->hEncoderConfig->ivas_format == SBA_FORMAT && ( st_ivas->hEncoderConfig->ivas_total_brate == IVAS_24k4 || st_ivas->hEncoderConfig->ivas_total_brate == IVAS_32k ) ); /*----------------------------------------------------------------* * Front Pre-processing *----------------------------------------------------------------*/ - if ( st_ivas->sba_mode == SBA_MODE_SPAR && st_ivas->hEncoderConfig->Opt_DTX_ON ) - { - st->dtx_sce_sba = 1; - } - error = pre_proc_front_ivas( hSCE, NULL, hSCE->element_brate, nb_bits_metadata, input_frame, 0, old_inp_12k8[0], old_inp_16k[0], - &Etot[0], &ener[0], &relE[0], A[0], Aw[0], epsP[0], lsp_new[0], lsp_mid[0], + &ener[0], &relE[0], A[0], Aw[0], epsP[0], lsp_new[0], lsp_mid[0], &vad_hover_flag[0], &attack_flag[0], realBuffer[0], imagBuffer[0], old_wsp[0], pitch_fr[0], voicing_fr[0], &loc_harm[0], &cor_map_sum[0], &vad_flag_dtx[0], enerBuffer[0], - fft_buff[0], A[0], lsp_new[0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, - flag_16k_smc, - st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->force_front_vad : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_dtx_flag : 0 ); - + fft_buff[0], A[0], lsp_new[0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, flag_16k_smc, + st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->force_front_vad : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_dtx_flag : 0, + st_ivas->hEncoderConfig->ivas_total_brate ); if ( error != IVAS_ERR_OK ) { return error; @@ -206,14 +205,13 @@ ivas_error ivas_sce_enc( * Reset metadata *----------------------------------------------------------------*/ - reset_metadata_spatial( ivas_format, hSCE->hMetaData, hSCE->element_brate, &st->total_brate, st->core_brate, nb_bits_metadata, st_ivas->sba_mode, - IVAS_SCE ); + reset_metadata_spatial( ivas_format, hSCE->hMetaData, hSCE->element_brate, &st->total_brate, st->core_brate, nb_bits_metadata, st_ivas->sba_mode ); /*----------------------------------------------------------------* - * Write IVAS format signalling in SID frames + * Write IVAS format signaling in SID frames *----------------------------------------------------------------*/ - if ( st->core_brate == SID_2k40 && ( ivas_format != SBA_FORMAT || st_ivas->sba_mode != SBA_MODE_SPAR ) ) + if ( st->core_brate == SID_2k40 ) { ivas_write_format_sid( ivas_format, IVAS_SCE, st->hBstr ); } @@ -239,13 +237,11 @@ ivas_error ivas_sce_enc( * Encoder *----------------------------------------------------------------*/ - if ( ( error = ivas_core_enc( hSCE, NULL, NULL, 1, old_inp_12k8, old_inp_16k, Etot, ener, A, Aw, epsP, lsp_new, lsp_mid, vad_hover_flag, attack_flag, realBuffer, imagBuffer, old_wsp, loc_harm, cor_map_sum, vad_flag_dtx, enerBuffer, fft_buff, 0, - flag_16k_smc ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_core_enc( hSCE, NULL, NULL, 1, old_inp_12k8, old_inp_16k, ener, A, Aw, epsP, lsp_new, lsp_mid, vad_hover_flag, attack_flag, realBuffer, imagBuffer, old_wsp, loc_harm, cor_map_sum, vad_flag_dtx, enerBuffer, fft_buff, 0, ivas_format, flag_16k_smc ) ) != IVAS_ERR_OK ) { return error; } - /*----------------------------------------------------------------* * Common updates *----------------------------------------------------------------*/ @@ -253,7 +249,19 @@ ivas_error ivas_sce_enc( /* update input samples buffer */ mvr2r( st->input, st->old_input_signal, input_frame ); - wmops_sub_end(); + hSCE->last_element_brate = hSCE->element_brate; + + /* Store previous attack detection flag */ + st->hTranDet->transientDetector.prev_bIsAttackPresent = st->hTranDet->transientDetector.bIsAttackPresent; + +#ifdef DEBUG_MODE_INFO + { + float tmpF = hSCE->element_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "element_brate", 0, sce_id, ENC ) ); + } +#endif + + pop_wmops(); return error; } @@ -281,7 +289,7 @@ ivas_error create_sce_enc( * Allocate SCE handle *-----------------------------------------------------------------*/ - if ( ( hSCE = (SCE_ENC_HANDLE) count_malloc( sizeof( SCE_ENC_DATA ) ) ) == NULL ) + if ( ( hSCE = (SCE_ENC_HANDLE) malloc( sizeof( SCE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SCE\n" ) ); } @@ -292,6 +300,7 @@ ivas_error create_sce_enc( hSCE->sce_id = sce_id; hSCE->element_brate = element_brate; + hSCE->last_element_brate = hSCE->element_brate; /*-----------------------------------------------------------------* * Metadata: allocate and initialize @@ -299,7 +308,7 @@ ivas_error create_sce_enc( if ( st_ivas->hEncoderConfig->ivas_format != MONO_FORMAT ) { - if ( ( hSCE->hMetaData = (BSTR_ENC_HANDLE) count_malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) + if ( ( hSCE->hMetaData = (BSTR_ENC_HANDLE) malloc( sizeof( BSTR_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MetaData structure\n" ) ); } @@ -313,7 +322,7 @@ ivas_error create_sce_enc( * Core Coder, 1 instance: allocate and initialize *-----------------------------------------------------------------*/ - if ( ( st = (ENC_CORE_HANDLE) count_malloc( sizeof( Encoder_State ) ) ) == NULL ) + if ( ( st = (ENC_CORE_HANDLE) malloc( sizeof( Encoder_State ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); } @@ -323,7 +332,7 @@ ivas_error create_sce_enc( st->total_brate = hSCE->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; - if ( ( error = init_encoder( st, 0, st_ivas->hEncoderConfig->var_SID_rate_flag, st_ivas->hEncoderConfig->interval_SID, 0 ) ) != IVAS_ERR_OK ) + if ( ( error = init_encoder( st, 0, st_ivas->hEncoderConfig->var_SID_rate_flag, st_ivas->hEncoderConfig->interval_SID, 0, st_ivas->ism_mode ) ) != IVAS_ERR_OK ) { return error; } @@ -358,11 +367,11 @@ void destroy_sce_enc( if ( hSCE->hMetaData != NULL ) { - count_free( hSCE->hMetaData ); + free( hSCE->hMetaData ); hSCE->hMetaData = NULL; } - count_free( hSCE ); + free( hSCE ); return; } diff --git a/lib_enc/ivas_sns_enc.c b/lib_enc/ivas_sns_enc.c index 1aeac19c571d46400258a5d66c564f5e4cf68711..9eeb4d87605cc97362ea2ffbb5bcc34f96512fd1 100644 --- a/lib_enc/ivas_sns_enc.c +++ b/lib_enc/ivas_sns_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,177 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" - -#ifndef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT -#define SNS_NPTS 16 /* Number of downsampled SNS parameters */ - -/*------------------------------------------------------------------- - * sns_compute_scf() - * - * - *-------------------------------------------------------------------*/ - -void sns_compute_scf( - float spectrum[], - const PsychoacousticParameters *pPsychParams, - const int16_t L_frame, - float *scf ) -{ - int16_t i, n, k; - float x[FDNS_NPTS], xs[FDNS_NPTS], sum, mean, xl4[SNS_NPTS], nf, xl[FDNS_NPTS]; - float tilt; - const uint8_t nBands = pPsychParams->nBands; - const uint8_t *bandLengths = pPsychParams->bandLengths; - int8_t bw = 0; - - - const float w_0 = 1.0f / 12.0f; - const float w_1 = 2.0f / 12.0f; - const float w_2 = 0.25f; /* 3.0f / 12.0f */ - const float w_3 = w_2; - const float w_4 = w_1; - const float w_5 = w_0; - - const float scale_log = INV_LOG_2 * 0.5f; - - assert( nBands == 64 ); - - set_f( x, 0.0f, FDNS_NPTS ); - - if ( bandLengths == NULL ) - { - bw = (int8_t) ( L_frame / nBands ); - /* Energy per band */ - k = 0; - for ( i = 0; i < nBands; ++i ) - { - x[i] = 0.0f; - for ( n = 0; n < bw; ++n, ++k ) - { - x[i] += spectrum[k]; - } - x[i] /= bw; - } - } - else - { - /* Energy per band */ - k = 0; - for ( i = 0; i < nBands; ++i ) - { - x[i] = 0.0f; - for ( n = 0; n < bandLengths[i]; ++n, ++k ) - { - x[i] += spectrum[k]; - } - x[i] /= bandLengths[i]; - } - } - - /* Smoothing */ - xs[0] = 0.75f * x[0] + 0.25f * x[1]; - - for ( i = 1; i < FDNS_NPTS - 1; i++ ) - { - xs[i] = 0.5f * x[i] + 0.25f * x[i - 1] + 0.25f * x[i + 1]; - } - - xs[FDNS_NPTS - 1] = 0.75f * x[FDNS_NPTS - 1] + 0.25f * x[FDNS_NPTS - 2]; - - /* Pre-emphasis */ - if ( L_frame == L_FRAME16k ) - { - tilt = 18.f; - } - else if ( L_frame == L_SPEC16k_EXT ) - { - tilt = 20.f; - } - else if ( L_frame == L_FRAME25_6k ) - { - tilt = 22.f; - } - else if ( L_frame == L_FRAME32k ) - { - tilt = 26.f; - } - else if ( L_frame == L_SPEC32k_EXT ) - { - tilt = 30.f; - } - else - { - tilt = 0.f; - assert( 0 && "illegal frame length in sns_compute_scf" ); - } - - for ( i = 0; i < FDNS_NPTS; i++ ) - { - xs[i] = xs[i] * powf( 10.0f, (float) i * (float) tilt / ( (float) FDNS_NPTS - 1.0f ) / 10.0f ); - } - - /* Noise floor at -40dB */ - sum = sum_f( xs, FDNS_NPTS ); - mean = sum / FDNS_NPTS; - - nf = mean * powf( 10.0f, -4.0f ); - nf = max( nf, powf( 2.0f, -32.0f ) ); - - - for ( i = 0; i < FDNS_NPTS; i++ ) - { - if ( xs[i] < nf ) - { - xs[i] = nf; - } - } - - /* Log-domain */ - for ( i = 0; i < FDNS_NPTS; i++ ) - { - xl[i] = logf( xs[i] ) * scale_log; - } - - /* Downsampling */ - xl4[0] = w_0 * xl[0] + - w_1 * xl[0] + - w_2 * xl[1] + - w_3 * xl[2] + - w_4 * xl[3] + - w_5 * xl[4]; - - - for ( n = 1; n < SNS_NPTS - 1; n++ ) - { - int16_t n4 = 4 * n; - xl4[n] = w_0 * xl[n4 - 1] + - w_1 * xl[n4] + - w_2 * xl[n4 + 1] + - w_3 * xl[n4 + 2] + - w_4 * xl[n4 + 3] + - w_5 * xl[n4 + 4]; - } - - xl4[SNS_NPTS - 1] = w_0 * xl[FDNS_NPTS - 5] + - w_1 * xl[FDNS_NPTS - 4] + - w_2 * xl[FDNS_NPTS - 3] + - w_3 * xl[FDNS_NPTS - 2] + - w_4 * xl[FDNS_NPTS - 1] + - w_5 * xl[FDNS_NPTS - 1]; - - /* Remove mean and scaling */ - sum = sum_f( xl4, SNS_NPTS ); - mean = sum / SNS_NPTS; - - for ( i = 0; i < SNS_NPTS; i++ ) - { - scf[i] = 0.85f * ( xl4[i] - mean ); - } - - return; -} -#endif +#include "wmc_auto.h" /*------------------------------------------------------------------- diff --git a/lib_enc/ivas_spar_encoder.c b/lib_enc/ivas_spar_encoder.c index fd80a4d6db0408c96dfc0879603529e1a408396f..9530b0d385cc0dfc16a0a502f54b18a8e3cc2ebd 100644 --- a/lib_enc/ivas_spar_encoder.c +++ b/lib_enc/ivas_spar_encoder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,92 +39,184 @@ #include "ivas_rom_com.h" #include "ivas_stat_com.h" #include "prot.h" +#include "math.h" #include -#include "wmops.h" +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * Local function prototypes + *--------------------------------------------------------------------*/ + +static ivas_error ivas_spar_enc_process( Encoder_Struct *st_ivas, const ENCODER_CONFIG_HANDLE hEncoderConfig, BSTR_ENC_HANDLE hMetaData, const int16_t front_vad_flag, float data_f[][L_FRAME48k] ); /*------------------------------------------------------------------------- * ivas_spar_enc_open() * - * Allocate and initialize SPAR encoder handle + * Allocate and initialize SPAR encoder handle and sub-handles *------------------------------------------------------------------------*/ ivas_error ivas_spar_enc_open( - Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ + Encoder_Struct *st_ivas, /* i/o: IVAS encoder handle */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ) { SPAR_ENC_HANDLE hSpar; ENCODER_CONFIG_HANDLE hEncoderConfig; + IVAS_FB_CFG *fb_cfg; + int16_t nchan_inp, nchan_transport, sba_order_internal; + int16_t table_idx, active_w_mixing; + int32_t input_Fs, ivas_total_brate; ivas_error error; hEncoderConfig = st_ivas->hEncoderConfig; error = IVAS_ERR_OK; + hSpar = st_ivas->hSpar; - /*-----------------------------------------------------------------* - * Allocate and initialize SPAR handle - *-----------------------------------------------------------------*/ + if ( !spar_reconfig_flag ) + { + /* SPAR encoder handle */ + if ( ( hSpar = (SPAR_ENC_HANDLE) malloc( sizeof( SPAR_ENC_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR encoder" ); + } + } + + input_Fs = hEncoderConfig->input_Fs; + sba_order_internal = min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ); + nchan_inp = ivas_sba_get_nchan_metadata( sba_order_internal ); + assert( nchan_inp <= hEncoderConfig->nchan_inp ); + ivas_total_brate = hEncoderConfig->ivas_total_brate; + + nchan_transport = ivas_get_sba_num_TCs( hEncoderConfig->ivas_total_brate, sba_order_internal ); + + // bw = ivas_get_bw_idx_from_sample_rate(pCfg->input_Fs); + table_idx = ivas_get_spar_table_idx( ivas_total_brate, sba_order_internal, SPAR_CONFIG_BW, NULL, NULL ); + // ivas_set_bitrate_config(&hSpar->hMdEnc->spar_md_cfg, table_idx); + + /* MD handle */ + if ( ( error = ivas_spar_md_enc_open( &( hSpar->hMdEnc ), hEncoderConfig, sba_order_internal ) ) != IVAS_ERR_OK ) + { + return error; + } - if ( ( hSpar = (SPAR_ENC_HANDLE) count_malloc( sizeof( SPAR_ENC_DATA ) ) ) == NULL ) + /* set FB config. */ + active_w_mixing = ivas_spar_br_table_consts[table_idx].active_w; + ivas_fb_set_cfg( &fb_cfg, SBA_FORMAT, SBA_MODE_SPAR, nchan_inp, nchan_transport, active_w_mixing, input_Fs ); + fb_cfg->remix_order = remix_order_set[hSpar->hMdEnc->spar_md_cfg.remix_unmix_order]; + + /* FB mixer handle */ + if ( ( error = ivas_FB_mixer_open( &( hSpar->hFbMixer ), input_Fs, fb_cfg, spar_reconfig_flag ) ) != IVAS_ERR_OK ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR encoder" ); + return error; } - if ( ( error = ivas_spar_foa_enc_open( &hSpar->hSparFoa, hEncoderConfig ) ) != IVAS_ERR_OK ) + /* Covariance handle */ +#ifdef LBR_SBA_EXTRA_COV_SMOOTH + if ( ( error = ivas_spar_covar_enc_open( &( hSpar->hCovEnc ), hSpar->hFbMixer->pFb, input_Fs, nchan_inp, hEncoderConfig->ivas_total_brate ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_spar_covar_enc_open( &( hSpar->hCovEnc ), hSpar->hFbMixer->pFb, input_Fs, nchan_inp ) ) != IVAS_ERR_OK ) +#endif { return error; } + if ( !spar_reconfig_flag ) + { + /* Transient Detector handle */ + if ( ( error = ivas_transient_det_open( &( hSpar->hTranDet ), input_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* initialization */ + hSpar->hMdEnc->table_idx = -1; + + /* AGC handle */ +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + hSpar->AGC_Enable = ivas_agc_enc_get_flag( hEncoderConfig->Opt_AGC_ON, nchan_transport ); +#else + hSpar->AGC_Enable = ivas_agc_enc_get_flag( nchan_transport ); +#endif + + hSpar->hAgcEnc = NULL; + if ( hSpar->AGC_Enable ) + { + if ( ( error = ivas_spar_agc_enc_open( &hSpar->hAgcEnc, input_Fs, nchan_inp ) ) != IVAS_ERR_OK ) + { + return error; + } + } + /* PCA handle */ + hSpar->hPCA = NULL; + if ( hEncoderConfig->Opt_PCA_ON ) + { + if ( ( hSpar->hPCA = (PCA_ENC_STATE *) malloc( sizeof( PCA_ENC_STATE ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR PCA encoder" ); + } + ivas_pca_enc_init( hSpar->hPCA ); + } + + /* initialization */ + hSpar->hMdEnc->table_idx = -1; + /*-----------------------------------------------------------------* * Configuration - set SPAR high-level parameters *-----------------------------------------------------------------*/ - ivas_spar_config( hEncoderConfig->ivas_total_brate, min( hEncoderConfig->sba_order, IVAS_MAX_SBA_ORDER ), - &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &hSpar->hSparFoa->core_nominal_brate, -1 ); + ivas_spar_config( hEncoderConfig->ivas_total_brate, min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ), + &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &hSpar->core_nominal_brate, -1 ); if ( st_ivas->nchan_transport == 1 ) { - st_ivas->hEncoderConfig->element_mode_init = IVAS_SCE; + hEncoderConfig->element_mode_init = IVAS_SCE; } else { - st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; } /*-----------------------------------------------------------------* * Allocate and initialize Front-VAD handle *-----------------------------------------------------------------*/ - hSpar->front_vad_flag = 0; - hSpar->front_vad_dtx_flag = 0; - hSpar->force_front_vad = 0; - - if ( hEncoderConfig->Opt_DTX_ON ) + if ( !spar_reconfig_flag ) { - if ( ( error = front_vad_create( &( hSpar->hFrontVad ), hEncoderConfig ) ) != IVAS_ERR_OK ) - { - return error; - } + hSpar->front_vad_flag = 0; + hSpar->front_vad_dtx_flag = 0; + hSpar->force_front_vad = 0; - if ( ( hSpar->hCoreCoderVAD = (ENC_CORE_HANDLE) count_malloc( sizeof( Encoder_State ) ) ) == NULL ) + if ( hEncoderConfig->Opt_DTX_ON ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); - } + if ( ( error = front_vad_create( &( hSpar->hFrontVad ), hEncoderConfig ) ) != IVAS_ERR_OK ) + { + return error; + } - copy_encoder_config( st_ivas, hSpar->hCoreCoderVAD, 1 ); + if ( ( hSpar->hCoreCoderVAD = (ENC_CORE_HANDLE) malloc( sizeof( Encoder_State ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); + } - hSpar->hCoreCoderVAD->total_brate = hEncoderConfig->ivas_total_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ - hSpar->hCoreCoderVAD->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + copy_encoder_config( st_ivas, hSpar->hCoreCoderVAD, 1 ); - if ( ( error = init_encoder( hSpar->hCoreCoderVAD, 0, hEncoderConfig->var_SID_rate_flag, hEncoderConfig->interval_SID, 1 ) ) != IVAS_ERR_OK ) + hSpar->hCoreCoderVAD->total_brate = hEncoderConfig->ivas_total_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + hSpar->hCoreCoderVAD->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + + if ( ( error = init_encoder( hSpar->hCoreCoderVAD, 0, hEncoderConfig->var_SID_rate_flag, hEncoderConfig->interval_SID, 1, st_ivas->ism_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else { - return error; + hSpar->hCoreCoderVAD = NULL; + hSpar->hFrontVad = NULL; } } - else - { - hSpar->hCoreCoderVAD = NULL; - hSpar->hFrontVad = NULL; - } /*-----------------------------------------------------------------* * Final assignment @@ -143,33 +235,67 @@ ivas_error ivas_spar_enc_open( *------------------------------------------------------------------------*/ void ivas_spar_enc_close( - SPAR_ENC_HANDLE hSpar, /* i/o: SPAR encoder handle */ - const int32_t input_Fs, /* i : input sampling rate */ - const int16_t nchan_inp /* i : number of input channels */ + SPAR_ENC_HANDLE *hSpar, /* i/o: SPAR encoder handle */ + const int32_t input_Fs, /* i : input sampling rate */ + const int16_t nchan_inp, /* i : number of input channels */ + const int16_t spar_reconfig_flag /* i : SPAR reconfiguration flag */ ) { - if ( hSpar != NULL ) + int16_t num_chans; + + if ( hSpar == NULL || *hSpar == NULL ) + { + return; + } + + if ( !spar_reconfig_flag ) { /* core-coder-VAD handle */ - if ( hSpar->hCoreCoderVAD != NULL ) + if ( ( *hSpar )->hCoreCoderVAD != NULL ) { - destroy_core_enc( hSpar->hCoreCoderVAD ); - hSpar->hCoreCoderVAD = NULL; + destroy_core_enc( ( *hSpar )->hCoreCoderVAD ); + ( *hSpar )->hCoreCoderVAD = NULL; } /* front-VAD handle */ - if ( hSpar->hFrontVad != NULL ) + if ( ( *hSpar )->hFrontVad != NULL ) { - front_vad_destroy( &hSpar->hFrontVad ); - hSpar->hFrontVad = NULL; + front_vad_destroy( &( *hSpar )->hFrontVad ); + ( *hSpar )->hFrontVad = NULL; } + } + + num_chans = ( *hSpar )->hFbMixer->fb_cfg->num_in_chans; + assert( num_chans <= nchan_inp ); + + /* MD handle */ + ivas_spar_md_enc_close( &( *hSpar )->hMdEnc ); + + /* Covar. State handle */ + ivas_spar_covar_enc_close( &( *hSpar )->hCovEnc, num_chans ); - ivas_spar_foa_enc_close( &hSpar->hSparFoa, input_Fs, nchan_inp ); + /* FB mixer handle */ + ivas_FB_mixer_close( &( *hSpar )->hFbMixer, input_Fs, spar_reconfig_flag ); - count_free( hSpar ); - hSpar = NULL; + /* AGC */ + ivas_spar_agc_enc_close( &( *hSpar )->hAgcEnc ); + + /* PCA */ + if ( ( *hSpar )->hPCA != NULL ) + { + free( ( *hSpar )->hPCA ); + ( *hSpar )->hPCA = NULL; } + if ( !spar_reconfig_flag ) + { + /* Trans Det handle */ + ivas_transient_det_close( &( *hSpar )->hTranDet ); + free( ( *hSpar ) ); + ( *hSpar ) = NULL; + } + + return; } @@ -189,49 +315,626 @@ ivas_error ivas_spar_enc( ) { ENCODER_CONFIG_HANDLE hEncoderConfig; - int16_t i, ch; ivas_error error; error = IVAS_ERR_OK; hEncoderConfig = st_ivas->hEncoderConfig; + // VE2DB: can hFbMixer->ppFilterbank_prior_input be replaced by st->input ? + + /* check last sba_mode */ +#ifndef LBR_SBA + if ( ivas_sba_mode_select( st_ivas->hEncoderConfig->last_ivas_total_brate ) == SBA_MODE_DIRAC ) +#else + if ( ivas_sba_mode_select( ) == SBA_MODE_DIRAC ) +#endif + { + Encoder_State *sts[MCT_MAX_BLOCKS]; + + /* initializations */ + for ( int16_t sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + sts[sce_id] = st_ivas->hSCE[sce_id]->hCoreCoder[0]; + } + + for ( int16_t cpe_id = 0, i = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + for ( int16_t ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts[i] = st_ivas->hCPE[cpe_id]->hCoreCoder[ch]; + i++; + } + } + + /* update FB prior input */ + // VE: last 1ms of 'ppFilterbank_prior_input' is not correct + for ( int16_t i = 0; i < st_ivas->nchan_transport; i++ ) + { + mvr2r( ( sts[i]->input_buff + NS2SA( hEncoderConfig->input_Fs, IVAS_FB_ENC_DELAY_NS ) ), + ( st_ivas->hSpar->hFbMixer->ppFilterbank_prior_input[i] + st_ivas->hSpar->hFbMixer->fb_cfg->prior_input_length - input_frame ), input_frame ); + } + } + /* front VAD */ - if ( ( error = front_vad_spar( st_ivas->hSpar, data_f[0], st_ivas->hEncoderConfig, input_frame ) ) != IVAS_ERR_OK ) + if ( ( error = front_vad_spar( st_ivas->hSpar, data_f[0], hEncoderConfig, input_frame ) ) != IVAS_ERR_OK ) { return error; } - /* normalize input channels */ - for ( ch = 0; ch < hEncoderConfig->nchan_inp; ch++ ) + if ( hEncoderConfig->sba_planar ) + { + ivas_sba_zero_vert_comp( data_f, st_ivas->sba_analysis_order, hEncoderConfig->sba_planar, input_frame ); + } + + if ( ( error = ivas_spar_enc_process( st_ivas, hEncoderConfig, hMetaData, st_ivas->hSpar->front_vad_flag, data_f ) ) != IVAS_ERR_OK ) + { + return error; + } + + *nb_bits_metadata = hMetaData->nb_bits_tot; + + /* Force IVAS front pre-proc decision for higher bitrates */ + if ( hEncoderConfig->ivas_total_brate > SBA_DTX_BITRATE_THRESHOLD || hEncoderConfig->Opt_DTX_ON == 0 ) + { + st_ivas->hSpar->front_vad_flag = 0; + } + + return error; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_spar_enc_process() + * + * Process call for SPAR encoder + *-----------------------------------------------------------------------------------------*/ + +static ivas_error ivas_spar_enc_process( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + BSTR_ENC_HANDLE hMetaData, /* i/o: MetaData handle */ + const int16_t front_vad_flag, /* i : front-VAD decision */ + float data_f[][L_FRAME48k] /* i/o: input/transport audio channels */ +) +{ + float pcm_tmp[IVAS_SPAR_MAX_CH][L_FRAME48k * 2]; + float *p_pcm_tmp[IVAS_SPAR_MAX_CH]; + int16_t i, j, b, i_ts, input_frame, dtx_vad; + int16_t transient_det[2]; + int32_t ivas_total_brate, input_Fs; + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; + float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; + int16_t nchan_inp, nchan_transport, sba_order; + int16_t table_idx; + int16_t in_out_mixer_map[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH]; + ivas_error error; + const int16_t *order; + SPAR_ENC_HANDLE hSpar = st_ivas->hSpar; + IVAS_QMETADATA_HANDLE hQMetaData = st_ivas->hQMetaData; + int16_t ts, l_ts, orig_dirac_bands, num_del_samples; + float *ppIn_FR_real[IVAS_SPAR_MAX_CH], *ppIn_FR_imag[IVAS_SPAR_MAX_CH]; + float w_del_buf[IVAS_FB_1MS_48K_SAMP]; + float dir[3], avg_dir[3]; + float energySum, vecLen; + + push_wmops( "ivas_spar_enc_process" ); + + /*-----------------------------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------------------------------*/ + + error = IVAS_ERR_OK; + + input_Fs = hEncoderConfig->input_Fs; + ivas_total_brate = hEncoderConfig->ivas_total_brate; + num_del_samples = hSpar->hFbMixer->fb_cfg->fb_latency; + + input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); + sba_order = min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ); + nchan_inp = ivas_sba_get_nchan_metadata( sba_order ); + assert( nchan_inp <= hEncoderConfig->nchan_inp ); +#ifdef LBR_SBA + int16_t active_w_vlbr; + active_w_vlbr = ( hEncoderConfig->ivas_total_brate < IVAS_24k4 ) ? 1 : 0; +#endif + for ( i = FOA_CHANNELS + 1; i < nchan_inp; i++ ) + { + mvr2r( data_f[HOA_keep_ind[i]], data_f[i], input_frame ); + } + + /*-----------------------------------------------------------------------------------------* + * Transient detector + *-----------------------------------------------------------------------------------------*/ + + ivas_transient_det_process( hSpar->hTranDet, data_f[0], input_frame, transient_det ); + if ( sba_order == 1 ) { - for ( i = 0; i < input_frame; i++ ) + transient_det[1] = transient_det[0]; + } + + /* store previous input samples for W in local buffer */ + assert( num_del_samples <= IVAS_FB_1MS_48K_SAMP ); + mvr2r( &hSpar->hFbMixer->ppFilterbank_prior_input[0][hSpar->hFbMixer->fb_cfg->prior_input_length - num_del_samples], w_del_buf, num_del_samples ); + + /*-----------------------------------------------------------------------------------------* + * FB mixer ingest + *-----------------------------------------------------------------------------------------*/ + + for ( i = 0; i < nchan_inp; i++ ) + { + p_pcm_tmp[i] = pcm_tmp[i]; + } + + /* run Filter Bank overlapping MDFT analysis first, then we can use the temporary buffer for Parameter MDFT analysis*/ + ivas_fb_mixer_pcm_ingest( hSpar->hFbMixer, data_f, p_pcm_tmp, input_frame ); + + /* prepare Parameter MDFT analysis */ + for ( i = 0; i < nchan_inp; i++ ) + { + ppIn_FR_real[i] = p_pcm_tmp[i]; + ppIn_FR_imag[i] = p_pcm_tmp[i] + input_frame; + p_pcm_tmp[i] = &data_f[i][0]; + } + + l_ts = input_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + ivas_fb_mixer_get_windowed_fr( hSpar->hFbMixer, p_pcm_tmp, ppIn_FR_real, ppIn_FR_imag, l_ts, l_ts ); + ivas_fb_mixer_update_prior_input( hSpar->hFbMixer, p_pcm_tmp, l_ts ); + + for ( i = 0; i < nchan_inp; i++ ) { - data_f[ch][i] *= ( 1.0 / PCM16_TO_FLT_FAC ); + p_pcm_tmp[i] += l_ts; + ppIn_FR_real[i] += l_ts; + ppIn_FR_imag[i] += l_ts; } } - if ( hEncoderConfig->sba_planar ) + /* turn pointers back to the local buffer, needed for the following processing */ + for ( i = 0; i < nchan_inp; i++ ) + { + ppIn_FR_real[i] = pcm_tmp[i]; + ppIn_FR_imag[i] = pcm_tmp[i] + input_frame; + p_pcm_tmp[i] = pcm_tmp[i]; + } + + dtx_vad = ( hEncoderConfig->Opt_DTX_ON == 1 ) ? front_vad_flag : 1; + + /*-----------------------------------------------------------------------------------------* + * DirAC encoding + *-----------------------------------------------------------------------------------------*/ + + ivas_dirac_param_est_enc( st_ivas->hDirAC, hQMetaData->q_direction, hQMetaData->useLowerRes, data_f, ppIn_FR_real, ppIn_FR_imag, input_frame, st_ivas->sba_mode ); + + if ( hQMetaData->q_direction->cfg.nbands > 0 ) { - ivas_sba_zero_vert_comp( data_f, hEncoderConfig->sba_order, hEncoderConfig->sba_planar, input_frame ); + orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; + + if ( dtx_vad == 1 ) + { + /* WB 4TC mode bit : disable for now*/ + push_next_indice( hMetaData, 0, 1 ); +#ifdef LBR_SBA_PLANAR + /* force planar for LBR SPAR+DirAC, then encode parameters */ + if ( hQMetaData->useLowerRes ) + { + for ( i = hQMetaData->q_direction[0].cfg.start_band; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) + { + /* Make sure elevation is really zero */ + set_zero( hQMetaData->q_direction[0].band_data[i].elevation, hQMetaData->q_direction[0].cfg.nblocks ); + } + } +#endif + ivas_qmetadata_enc_encode( hMetaData, hQMetaData ); + } + else + { + hQMetaData->q_direction[0].cfg.nbands = DIRAC_DTX_BANDS; + + /* compute directions */ + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + set_zero( dir, 3 ); + set_zero( avg_dir, 3 ); + energySum = 0.0f; + + /* combine all DirAC bands except the last one, handle last band separately, last band covers BW above WB */ + for ( j = 0; j < orig_dirac_bands - 1; j++ ) + { + ivas_qmetadata_azimuth_elevation_to_direction_vector( hQMetaData->q_direction[0].band_data[j].azimuth[i], hQMetaData->q_direction[0].band_data[j].elevation[i], &dir[0] ); + vecLen = hQMetaData->q_direction[0].band_data[j].energy_ratio[i] * st_ivas->hDirAC->buffer_energy[i * orig_dirac_bands + j]; + + avg_dir[0] += dir[0] * vecLen; + avg_dir[1] += dir[1] * vecLen; + avg_dir[2] += dir[2] * vecLen; + + energySum += st_ivas->hDirAC->buffer_energy[i * orig_dirac_bands + j]; + } + + ivas_qmetadata_direction_vector_to_azimuth_elevation( &avg_dir[0], &hQMetaData->q_direction[0].band_data[0].azimuth[i], &hQMetaData->q_direction[0].band_data[0].elevation[i] ); + hQMetaData->q_direction[0].band_data[0].energy_ratio[i] = sqrtf( dotp( avg_dir, avg_dir, 3 ) ) / ( energySum + EPSILON ); + + hQMetaData->q_direction[0].band_data[1].azimuth[i] = hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i]; + hQMetaData->q_direction[0].band_data[1].elevation[i] = hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i]; + hQMetaData->q_direction[0].band_data[1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i]; + } + + /* 1 bit to indicate mode MD coding : temp solution*/ + push_next_indice( hMetaData, 1, 1 ); + + /* encode SID parameters */ + ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, -1, SBA_FORMAT, st_ivas->sba_mode ); + } + + for ( b = hQMetaData->q_direction->cfg.start_band; b < hQMetaData->q_direction->cfg.nbands; b++ ) + { + for ( i_ts = 0; i_ts < ( ( dtx_vad == 1 ) ? hQMetaData->q_direction[0].cfg.nblocks : 1 ); i_ts++ ) + { + hQMetaData->q_direction->band_data[b].azimuth[i_ts] = hQMetaData->q_direction->band_data[b].q_azimuth[i_ts]; + hQMetaData->q_direction->band_data[b].elevation[i_ts] = hQMetaData->q_direction->band_data[b].q_elevation[i_ts]; + hQMetaData->q_direction[0].band_data[b].energy_ratio[0] = 1.0f - diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; + } + } + + if ( dtx_vad == 0 ) + { + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i] = hQMetaData->q_direction[0].band_data[1].elevation[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio[0]; + } + + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + for ( j = orig_dirac_bands - 2; j >= 0; j-- ) + { + hQMetaData->q_direction[0].band_data[j].azimuth[i] = hQMetaData->q_direction[0].band_data[0].azimuth[0]; + hQMetaData->q_direction[0].band_data[j].elevation[i] = hQMetaData->q_direction[0].band_data[0].elevation[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio[0]; + } + } + + hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; + } } + /*-----------------------------------------------------------------------------------------* + * Set SPAR bitrates + *-----------------------------------------------------------------------------------------*/ + + table_idx = ivas_get_spar_table_idx( ivas_total_brate, sba_order, SPAR_CONFIG_BW, NULL, NULL ); - if ( ( error = ivas_spar_foa_enc_process( st_ivas, hEncoderConfig, hMetaData, st_ivas->hSpar->front_vad_flag, data_f ) ) != IVAS_ERR_OK ) + if ( hSpar->hMdEnc->table_idx != table_idx ) { - return error; + hSpar->hMdEnc->table_idx = table_idx; + if ( ivas_total_brate != hEncoderConfig->last_ivas_total_brate ) + { + if ( ( error = ivas_spar_md_enc_init( hSpar->hMdEnc, hEncoderConfig, sba_order ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + ivas_spar_set_bitrate_config( &hSpar->hMdEnc->spar_md_cfg, table_idx, ( hSpar->hMdEnc->spar_hoa_md_flag ) ? IVAS_MAX_NUM_BANDS : SPAR_DIRAC_SPLIT_START_BAND ); + } } + /*-----------------------------------------------------------------------------------------* + * Covariance process + *-----------------------------------------------------------------------------------------*/ - if ( hEncoderConfig->sba_planar ) + for ( i = 0; i < nchan_inp; i++ ) { - ivas_sba_zero_vert_comp( data_f, hEncoderConfig->sba_order, hEncoderConfig->sba_planar, input_frame ); // TODO tmu: do we need a second call to this function ? + for ( j = 0; j < nchan_inp; j++ ) + { + cov_real[i][j] = hSpar->hMdEnc->cov_real[i][j]; + cov_dtx_real[i][j] = hSpar->hMdEnc->cov_dtx_real[i][j]; + } } - *nb_bits_metadata = hMetaData->nb_bits_tot; + ivas_enc_cov_handler_process( hSpar->hCovEnc, ppIn_FR_real, ppIn_FR_imag, cov_real, cov_dtx_real, hSpar->hFbMixer->pFb, 0, hSpar->hFbMixer->pFb->filterbank_num_bands, nchan_inp, dtx_vad, transient_det ); + nchan_transport = st_ivas->nchan_transport; + + /*-----------------------------------------------------------------------------------------* + * MetaData encoder + *-----------------------------------------------------------------------------------------*/ - /* temp hack to not force IVAS front pre-proc decision for higher bitrates */ - if ( hEncoderConfig->ivas_total_brate > IVAS_64k || hEncoderConfig->Opt_DTX_ON == 0 ) + if ( hSpar->hMdEnc->spar_hoa_md_flag == 0 ) { - st_ivas->hSpar->front_vad_flag = 0; + ivas_spar_md_enc_process( hSpar->hMdEnc, hEncoderConfig, cov_real, cov_dtx_real, hMetaData, dtx_vad, nchan_inp, sba_order +#ifdef LBR_SBA + , hSpar->hFbMixer->prior_mixer +#endif + ); + } + + { + float azi_dirac[IVAS_MAX_NUM_BANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + float ele_dirac[IVAS_MAX_NUM_BANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + float diffuseness[IVAS_MAX_NUM_BANDS]; + float Wscale_d[IVAS_MAX_NUM_BANDS]; + int16_t d_start_band, d_end_band; + int16_t dirac_band_idx; + + d_start_band = hSpar->enc_param_start_band; + d_end_band = IVAS_MAX_NUM_BANDS; + + for ( b = d_start_band; b < d_end_band; b++ ) + { + dirac_band_idx = hSpar->dirac_to_spar_md_bands[b] - d_start_band; + for ( i_ts = 0; i_ts < hQMetaData->q_direction->cfg.nblocks; i_ts++ ) + { + azi_dirac[b][i_ts] = hQMetaData->q_direction->band_data[dirac_band_idx].azimuth[i_ts]; + ele_dirac[b][i_ts] = hQMetaData->q_direction->band_data[dirac_band_idx].elevation[i_ts]; + } + diffuseness[b] = 1.0f - hQMetaData->q_direction->band_data[dirac_band_idx].energy_ratio[0]; + } + + if ( d_start_band >= 6 && dtx_vad == 1 ) + { + mvr2r( hSpar->hMdEnc->spar_md.band_coeffs[d_start_band - 1].P_quant_re, hSpar->hMdEnc->spar_md.band_coeffs[d_start_band - 1].P_re, IVAS_SPAR_MAX_CH - 1 ); + } + + for ( b = d_start_band; b < d_end_band; b++ ) + { + Wscale_d[b] = 1.0f; + for ( i = 1; i < nchan_inp; i++ ) + { + Wscale_d[b] += cov_real[i][i][b] / max( EPSILON, cov_real[0][0][b] ); + } + Wscale_d[b] = Wscale_d[b] / ( 1.0f + (float) sba_order ); /*DirAC normalized signal variance sums to 1 + order*/ + Wscale_d[b] = sqrtf( Wscale_d[b] ); + Wscale_d[b] = min( 2.0f, max( Wscale_d[b], 1.0f ) ); + } + + ivas_get_spar_md_from_dirac( azi_dirac, ele_dirac, diffuseness, 1, hSpar->hMdEnc->mixer_mat, &hSpar->hMdEnc->spar_md, &hSpar->hMdEnc->spar_md_cfg, d_start_band, d_end_band, ( hSpar->hMdEnc->spar_hoa_md_flag ) ? 1 : sba_order, dtx_vad, Wscale_d +#ifdef LBR_SBA + , hQMetaData->useLowerRes, active_w_vlbr +#endif + ); } + if ( hSpar->hMdEnc->spar_hoa_md_flag ) + { + ivas_spar_md_enc_process( hSpar->hMdEnc, hEncoderConfig, cov_real, cov_dtx_real, hMetaData, dtx_vad, nchan_inp, sba_order +#ifdef LBR_SBA + , hSpar->hFbMixer->prior_mixer +#endif + ); + } +#ifdef DEBUG_LBR_SBA + /* Dumping SPAR Coefficients */ + char f_name[100]; + int16_t nbands = 6; + int16_t num_subframes = 1; + int16_t num_elements = 6; + int16_t num_block_group = 1; + int16_t byte_size = sizeof( float ); + + sprintf( f_name, "SBA_MD_values.bin" ); + ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + + for ( b = 0; b < nbands; b++ ) + { + for ( int16_t sf = 0; sf < num_subframes; sf++ ) + { + for ( int16_t bl = 0; bl < num_block_group; bl++ ) + { + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_re[0], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_re[1], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_re[2], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_re[0], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_re[1], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_re[2], byte_size, 1, 1, f_name ); + // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); + } + } + } +#endif +#ifdef DEBUG_LBR_SBA + /* Dumping SPAR Coefficients */ + nbands = 6; + num_subframes = 1; + num_elements = 6; + num_block_group = 1; + byte_size = sizeof( float ); + + sprintf( f_name, "SBA_MD_values_quant.bin" ); + ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + + for ( b = 0; b < nbands; b++ ) + { + for ( int16_t sf = 0; sf < num_subframes; sf++ ) + { + for ( int16_t bl = 0; bl < num_block_group; bl++ ) + { + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_quant_re[0], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_quant_re[1], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_quant_re[2], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_quant_re[0], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_quant_re[1], byte_size, 1, 1, f_name ); + dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_quant_re[2], byte_size, 1, 1, f_name ); + // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); + } + } + } +#endif + /*-----------------------------------------------------------------------------------------* + * FB mixer + *-----------------------------------------------------------------------------------------*/ + + ivas_fb_mixer_get_in_out_mapping( hSpar->hFbMixer->fb_cfg, nchan_transport, ENC, remix_order_set[hSpar->hMdEnc->spar_md_cfg.remix_unmix_order], in_out_mixer_map ); + +#ifdef DEBUG_SBA_MD_DUMP + { + int16_t k; + static FILE *f_mat = 0; + + if ( f_mat == 0 ) + f_mat = fopen( "mixer_mat_enc", "w" ); + + for ( i = 0; i < hSpar->hFbMixer->fb_cfg->num_out_chans; i++ ) + { + for ( j = 0; j < hSpar->hFbMixer->fb_cfg->num_in_chans; j++ ) + { + for ( k = 0; k < hSpar->hFbMixer->pFb->filterbank_num_bands; k++ ) + { + fprintf( f_mat, "%f\n", hSpar->hMdEnc->mixer_mat[i][j][k] ); + + if ( ( in_out_mixer_map[i][j] == 0 ) && ( fabs( hSpar->hMdEnc->mixer_mat[i][j][k] ) > 1e-20 ) ) + { + assert( 0 && "Non zero value in unexpected mixer map!!!" ); + } + } + } + } + } +#endif +#ifdef DEBUG_SPAR_DIRAC_WRITE_OUT_PRED_PARS + { + static FILE *fid = 0; + int16_t band = 9; + if ( !fid ) + { + fid = fopen( "pred_coeffs_enc.txt", "wt" ); + } + fprintf( fid, "%.6f\n", hSpar->hMdEnc->mixer_mat[1][0][band] ); + } +#endif + + ivas_fb_mixer_process( hSpar->hFbMixer, hSpar->hMdEnc->mixer_mat, p_pcm_tmp, input_frame, in_out_mixer_map ); + +#ifdef DEBUG_SBA_AUDIO_DUMP + ivas_spar_dump_signal_wav( input_frame, p_pcm_tmp, NULL, nchan_transport, spar_foa_enc_wav[1], "ivas_fb_mixer_process()" ); +#endif + + /* move delayed W into output buffer unless activeW operation*/ + if ( hSpar->hFbMixer->fb_cfg->active_w_mixing == 0 ) + { + mvr2r( w_del_buf, p_pcm_tmp[0], num_del_samples ); + mvr2r( data_f[0], p_pcm_tmp[0] + num_del_samples, input_frame - num_del_samples ); + } + + /*-----------------------------------------------------------------------------------------* + * PCA encoder + *-----------------------------------------------------------------------------------------*/ + + if ( hSpar->hPCA != NULL ) + { + ivas_pca_enc( hEncoderConfig, hSpar->hPCA, hMetaData, p_pcm_tmp, input_frame, FOA_CHANNELS ); + } + else + { + if ( ivas_total_brate == PCA_BRATE && sba_order == SBA_FOA_ORDER ) + { + /* write PCA bypass bit */ + push_next_indice( hMetaData, PCA_MODE_INACTIVE, 1 ); + } + } + +#ifdef DEBUG_SBA_AUDIO_DUMP + ivas_spar_dump_signal_wav( input_frame, p_pcm_tmp, NULL, nchan_transport, spar_foa_enc_wav[0], "ivas_pca_enc()" ); +#endif + +#ifdef SPAR_HOA_DBG + /*FILE *fp = fopen("int_enc_dmx.raw", "ab"); + for (int16_t t = 0; t < 960; t++) + { + for (int16_t c = 0; c < hSpar->hFbMixer->filterbank_num_out_chans; c++) + { + for ( k = 0; k < 2; k++ ) + { + fb_mixer_in_buf.ppMixer[i][j][k] = hSpar->hMdEnc->mixer_mat[i][j]; + } + } + } + fclose( fp );*/ +#endif + /*-----------------------------------------------------------------------------------------* + * AGC + *-----------------------------------------------------------------------------------------*/ + + if ( dtx_vad == 1 ) + { + if ( hSpar->AGC_Enable != 0 ) + { + ivas_agc_enc_process( hSpar->hAgcEnc, hMetaData, p_pcm_tmp, p_pcm_tmp, hSpar->hFbMixer->fb_cfg->num_out_chans, hEncoderConfig ); + } + else + { + /* IVAS_fmToDo: This AGC on/off bit should be removed when the command line option to force enable/disable AGC is + * removed. + * On the decoder side, ivas_agc_enc_get_flag could be used instead to determine if AGC is on or not. The + * ivas_agc_enc_get_flag function should be moved to ivas_agc_com.c and renamed when this occurs. */ + push_next_indice( hMetaData, 0, 1 ); + } + } +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after ivas_agc_enc_process */ + ivas_spar_dump_signal_wav( input_frame, p_pcm_tmp, NULL, nchan_transport, spar_foa_enc_wav[2], "ivas_agc_enc_process()" ); +#endif + +#ifdef DEBUG_SPAR_BYPASS_EVS_CODEC + { + static FILE *fid_enc = 0; + static float delay_buf[576 * 4] = { 0 }; + int16_t smp, ch, buf_idx, framelen = input_frame, delay = 576; + if ( !fid_enc ) + { + fid_enc = fopen( "evs_input_float.raw", "wb" ); + } + + /* write out buffer */ + for ( smp = 0; smp < delay * nchan_transport; smp++ ) + { + fwrite( &delay_buf[smp], sizeof( float ), 1, fid_enc ); + } + + for ( smp = 0; smp < framelen - delay; smp++ ) + { + for ( ch = 0; ch < nchan_transport; ch++ ) + { + fwrite( &p_pcm_tmp[ch][smp], sizeof( float ), 1, fid_enc ); + } + } + + /* update delay buffer*/ + buf_idx = 0; + for ( ; smp < framelen; smp++ ) + { + for ( ch = 0; ch < nchan_transport; ch++ ) + { + delay_buf[buf_idx++] = p_pcm_tmp[ch][smp]; + } + } + } +#endif + + /*-----------------------------------------------------------------------------------------* + * Re-order the dmx back to ACN/SN3D format + *-----------------------------------------------------------------------------------------*/ + + order = remix_order_set[hSpar->hMdEnc->spar_md_cfg.remix_unmix_order]; + + for ( j = 0; j < nchan_transport; j++ ) + { + mvr2r( p_pcm_tmp[j], data_f[order[j]], input_frame ); + } + for ( ; j < IVAS_SPAR_MAX_DMX_CHS; j++ ) + { + set_f( data_f[order[j]], 0.0f, input_frame ); + } + + pop_wmops(); + return error; } diff --git a/lib_enc/ivas_spar_foa_enc.c b/lib_enc/ivas_spar_foa_enc.c deleted file mode 100644 index 0762b4d0ea4e633fede64d9792964e6c92c91898..0000000000000000000000000000000000000000 --- a/lib_enc/ivas_spar_foa_enc.c +++ /dev/null @@ -1,906 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include -#include "options.h" -#ifdef DEBUGGING -#include "debug.h" -#endif -#include "ivas_prot.h" -#include "prot.h" -#include "ivas_rom_com.h" -#include "ivas_stat_com.h" -#include "math.h" -#include -#include "wmops.h" - -#ifdef DEBUG_SPAR_FOA -extern FILE *fEvs_enc_in; -extern FILE *fFb_out[4]; -#endif - - -/*------------------------------------------------------------------------- - * ivas_spar_foa_enc_open() - * - * Allocate and initialize SPAR encoder handle for static memory - *------------------------------------------------------------------------*/ - -ivas_error ivas_spar_foa_enc_open( - ivas_spar_foa_enc_state_t **hSparFoa, /* i/o: SPAR FOA encoder handle */ - const ENCODER_CONFIG_HANDLE hEncoderConfig /* i : configuration structure */ -) -{ - ivas_spar_foa_enc_state_t *pState; - IVAS_FB_CFG *fb_cfg; - int16_t nchan_inp, nchan_transport, sba_order_internal; - int16_t table_idx, active_w_mixing; - int32_t input_Fs, ivas_total_brate; - ivas_error error; - - error = IVAS_ERR_OK; - - input_Fs = hEncoderConfig->input_Fs; - - sba_order_internal = min( hEncoderConfig->sba_order, IVAS_MAX_SBA_ORDER ); - nchan_inp = ivas_sba_get_nchan_metadata( sba_order_internal ); - assert( nchan_inp <= hEncoderConfig->nchan_inp ); - ivas_total_brate = hEncoderConfig->ivas_total_brate; - nchan_transport = ivas_get_spar_num_TCs( hEncoderConfig->ivas_total_brate, sba_order_internal ); - - // bw = ivas_get_bw_idx_from_sample_rate(pCfg->input_Fs); - table_idx = ivas_get_spar_table_idx( ivas_total_brate, sba_order_internal, SPAR_CONFIG_BW, NULL, NULL ); - - /* FOA encoder handle */ - if ( ( pState = (ivas_spar_foa_enc_state_t *) count_malloc( sizeof( ivas_spar_foa_enc_state_t ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR encoder" ); - } - - /* MD handle */ - if ( ( error = ivas_spar_foa_md_enc_open( &( pState->hMdEnc ), hEncoderConfig ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* set FB config. */ - active_w_mixing = ivas_spar_br_table_consts[table_idx].active_w; // VE: this parameter is different between enc and dec - ivas_fb_set_cfg( &fb_cfg, SBA_FORMAT, SBA_MODE_SPAR, nchan_inp, nchan_transport, active_w_mixing, input_Fs ); - fb_cfg->remix_order = remix_order_set[pState->hMdEnc->spar_md_cfg.remix_unmix_order]; - - /* FB mixer handle */ - if ( ( error = ivas_FB_mixer_open( &( pState->hFbMixer ), input_Fs, fb_cfg ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* Covariance handle */ -#ifdef LBR_SBA_EXTRA_COV_SMOOTH - if ( ( error = ivas_spar_covar_enc_open( &( pState->hCovEnc ), pState->hFbMixer->pFb, input_Fs, nchan_inp, hEncoderConfig->ivas_total_brate ) ) != IVAS_ERR_OK ) -#else - if ( ( error = ivas_spar_covar_enc_open( &( pState->hCovEnc ), pState->hFbMixer->pFb, input_Fs, nchan_inp ) ) != IVAS_ERR_OK ) -#endif - { - return error; - } - - /* Transient Detector handle */ - if ( ( error = ivas_spar_transient_det_open( &( pState->hTranDet ), input_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* AGC */ - if ( ( error = ivas_spar_agc_enc_open( &pState->hAgcEnc, input_Fs, nchan_inp ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* PCA */ - pState->hPCA = NULL; - if ( hEncoderConfig->Opt_PCA_ON ) - { - if ( ( pState->hPCA = (PCA_ENC_STATE *) count_malloc( sizeof( PCA_ENC_STATE ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR PCA encoder" ); - } - init_pca_enc( pState->hPCA ); - } - - /* initializations */ - pState->hMdEnc->table_idx = -1; - - *hSparFoa = pState; - - return error; -} - - -/*------------------------------------------------------------------------- - * ivas_spar_foa_enc_close() - * - * Deallocate SPAR encoder handle for static memory - *------------------------------------------------------------------------*/ - -void ivas_spar_foa_enc_close( - ivas_spar_foa_enc_state_t **hSparFoa, /* i/o: SPAR FOA encoder handle */ - const int32_t input_Fs, /* i : input sampling rate */ - const int16_t nchan_inp /* i : number of input channels */ -) -{ - ivas_spar_foa_enc_state_t *pState; - int16_t num_chans; - - pState = *hSparFoa; - num_chans = pState->hFbMixer->fb_cfg->num_in_chans; - assert( num_chans <= nchan_inp ); - - if ( pState != NULL ) - { - /* MD handle */ - ivas_spar_foa_md_enc_close( &pState->hMdEnc ); - - /* Covar. State handle */ - ivas_spar_covar_enc_close( &pState->hCovEnc, num_chans ); - - /* FB mixer handle */ - ivas_FB_mixer_close( &pState->hFbMixer, input_Fs ); - - /* Trans Det handle */ - ivas_spar_transient_det_close( &pState->hTranDet ); - - /* AGC */ - ivas_spar_agc_enc_close( &pState->hAgcEnc ); - - /* PCA */ - if ( pState->hPCA != NULL ) - { - count_free( pState->hPCA ); - pState->hPCA = NULL; - } - - count_free( pState ); - pState = NULL; - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_enc_get_windowed_fr() - * - * Get windowed FRs - *-----------------------------------------------------------------------------------------*/ - -static void ivas_spar_foa_enc_get_windowed_fr( - IVAS_FB_MIXER_HANDLE hFbMixer, - float *pIn_blocks[IVAS_SPAR_MAX_CH], - ivas_enc_cov_handler_in_buf_t *pCov_in_buf, - const int16_t input_frame, - const int16_t nchan_inp, - const int16_t num_past_samples ) -{ - int16_t i, j, rev_offset; - - for ( i = 0; i < nchan_inp; i++ ) - { - const int16_t stride = hFbMixer->pFb->fb_bin_to_band.short_stride; - float tmp_buf[MDFT_FB_BANDS_240 * 2]; - int16_t win_len = (int16_t) hFbMixer->ana_window_offset; - float *mdft_in_ptr = tmp_buf + stride - win_len; - float tmp_in_block[L_FRAME48k + MDFT_FB_BANDS_240]; - float *data_ptr = tmp_in_block; - float *fr_re_ptr = pCov_in_buf->ppIn_FR_real[i]; - float *fr_im_ptr = pCov_in_buf->ppIn_FR_imag[i]; - - set_f( tmp_buf, 0, MDFT_FB_BANDS_240 * 2 ); - - /* copy input data, because pIn_blocks and fr_re_ptr + fr_im_ptr use the same memory */ - mvr2r( &pIn_blocks[i][input_frame - num_past_samples], tmp_in_block, input_frame + win_len ); - - for ( int16_t blk = 0; blk < input_frame / stride; blk++ ) - { - - for ( j = 0; j < win_len; j++ ) - { - mdft_in_ptr[j] = data_ptr[j] * hFbMixer->pAna_window[j]; - } - - for ( j = win_len; j < stride; j++ ) - { - mdft_in_ptr[j] = data_ptr[j]; - } - - rev_offset = win_len - 1; - for ( j = stride; j < stride + win_len; j++ ) - { - mdft_in_ptr[j] = data_ptr[j] * hFbMixer->pAna_window[rev_offset--]; - } - - ivas_mdft( tmp_buf, fr_re_ptr, fr_im_ptr, stride << 1, stride ); - - data_ptr += stride; - fr_re_ptr += stride; - fr_im_ptr += stride; - } - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_enc_process() - * - * Process call for SPAR FOA encoder - *-----------------------------------------------------------------------------------------*/ - -ivas_error ivas_spar_foa_enc_process( - Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ - const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ - BSTR_ENC_HANDLE hMetaData, /* i/o: MetaData handle */ - const int16_t front_vad_flag, /* i : front-VAD decision */ - float data_f[][L_FRAME48k] /* i/o: input/transport audio channels */ -) -{ - float pcm_tmp[IVAS_SPAR_MAX_CH][L_FRAME48k * 2]; - float *p_pcm_tmp[IVAS_SPAR_MAX_CH]; - int16_t i, j, k, b, i_ts, input_frame, num_bands_bw; - int16_t dtx_vad, dtx_cov_flag, dtx_silence_mode; - int32_t ivas_total_brate, input_Fs; - ivas_enc_cov_handler_in_buf_t cov_in_buf; - float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - ivas_spar_foa_md_enc_in_buf_t md_in_buf; - int16_t nchan_inp, nchan_transport, bwidth, sba_order; - int16_t table_idx; - int16_t in_out_mixer_map[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH]; - ivas_error error; - const int16_t *order; - ivas_spar_foa_enc_state_t *pState = st_ivas->hSpar->hSparFoa; - IVAS_QMETADATA_HANDLE hQMetaData = st_ivas->hQMetaData; - int16_t ts, l_ts, orig_dirac_bands, num_del_samples; - float *ppIn_FR_real[IVAS_SPAR_MAX_CH], *ppIn_FR_imag[IVAS_SPAR_MAX_CH]; - float w_del_buf[IVAS_FB_1MS_48K_SAMP]; - float dir[3], avg_dir[3]; - float energySum, vecLen; - - wmops_sub_start( "spar_foa_enc_process" ); - - /*-----------------------------------------------------------------------------------------* - * Initialization - *-----------------------------------------------------------------------------------------*/ - - error = IVAS_ERR_OK; - - input_Fs = hEncoderConfig->input_Fs; - ivas_total_brate = hEncoderConfig->ivas_total_brate; - num_del_samples = pState->hFbMixer->fb_cfg->fb_latency; - - input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); - sba_order = min( hEncoderConfig->sba_order, IVAS_MAX_SBA_ORDER ); - nchan_inp = ivas_sba_get_nchan_metadata( sba_order ); - assert( nchan_inp <= hEncoderConfig->nchan_inp ); -#ifdef LBR_SBA - int16_t active_w_vlbr; - active_w_vlbr = ( hEncoderConfig->ivas_total_brate < IVAS_24k4 ) ? 1 : 0; -#endif - for ( i = FOA_CHANNELS + 1; i < nchan_inp; i++ ) - { - mvr2r( data_f[HOA_keep_ind[i]], data_f[i], input_frame ); - } - - table_idx = ivas_get_spar_table_idx( ivas_total_brate, sba_order, SPAR_CONFIG_BW, NULL, NULL ); - - /*-----------------------------------------------------------------------------------------* - * Transient detector - *-----------------------------------------------------------------------------------------*/ - - cov_in_buf.transient_det = ivas_transient_det_process( pState->hTranDet, data_f[0], input_frame ); - - /* store previous input samples for W in local buffer */ - assert( num_del_samples <= IVAS_FB_1MS_48K_SAMP ); - mvr2r( &pState->hFbMixer->ppFilterbank_prior_input[0][pState->hFbMixer->fb_cfg->prior_input_length - num_del_samples], w_del_buf, num_del_samples ); - - /*-----------------------------------------------------------------------------------------* - * FB mixer ingest - *-----------------------------------------------------------------------------------------*/ - - for ( i = 0; i < nchan_inp; i++ ) - { - p_pcm_tmp[i] = pcm_tmp[i]; - } - - /* run Filter Bank overlapping MDFT analysis first, then we can use the temporary buffer for Parameter MDFT analysis*/ - ivas_fb_mixer_pcm_ingest( pState->hFbMixer, data_f, p_pcm_tmp, input_frame ); - - /* prepare Parameter MDFT analysis */ - for ( i = 0; i < nchan_inp; i++ ) - { - cov_in_buf.ppIn_FR_real[i] = p_pcm_tmp[i]; - cov_in_buf.ppIn_FR_imag[i] = p_pcm_tmp[i] + input_frame; - } - - for ( i = 0; i < nchan_inp; i++ ) - { - p_pcm_tmp[i] = &data_f[i][0]; - ppIn_FR_real[i] = cov_in_buf.ppIn_FR_real[i]; - ppIn_FR_imag[i] = cov_in_buf.ppIn_FR_imag[i]; - } - - l_ts = input_frame / MAX_PARAM_SPATIAL_SUBFRAMES; - - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) - { - ivas_fb_mixer_get_windowed_fr( pState->hFbMixer, p_pcm_tmp, ppIn_FR_real, ppIn_FR_imag, l_ts, l_ts ); - ivas_fb_mixer_update_prior_input( pState->hFbMixer, p_pcm_tmp, l_ts ); - - for ( i = 0; i < nchan_inp; i++ ) - { - p_pcm_tmp[i] += l_ts; - ppIn_FR_real[i] += l_ts; - ppIn_FR_imag[i] += l_ts; - } - } - - /* turn pointers back to the local buffer, needed for the following processing */ - for ( i = 0; i < nchan_inp; i++ ) - { - p_pcm_tmp[i] = pcm_tmp[i]; - } - - cov_in_buf.num_ch = nchan_inp; - - dtx_vad = ( hEncoderConfig->Opt_DTX_ON == 1 ) ? front_vad_flag : 1; - - /*-----------------------------------------------------------------------------------------* - * DirAC encoding - *-----------------------------------------------------------------------------------------*/ - - ivas_dirac_param_est_enc( st_ivas->hDirAC, hQMetaData->q_direction, hQMetaData->useLowerRes, - data_f, cov_in_buf.ppIn_FR_real, cov_in_buf.ppIn_FR_imag, input_frame ); - - if ( hQMetaData->q_direction->cfg.nbands > 0 ) - { - orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; - - if ( dtx_vad == 1 ) - { - /* WB 4TC mode bit : disable for now*/ - push_next_indice( hMetaData, 0, 1 ); -#ifdef LBR_SBA_PLANAR - /* force planar for LBR SPAR+DirAC, then encode parameters */ - if ( hQMetaData->useLowerRes ) - { - for ( i = hQMetaData->q_direction[0].cfg.start_band; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) - { - /* Make sure elevation is really zero */ - set_zero( hQMetaData->q_direction[0].band_data[i].elevation, hQMetaData->q_direction[0].cfg.nblocks ); - } - } -#endif - ivas_qmetadata_enc_encode( hMetaData, hQMetaData ); - -#ifdef DEBUG_LBR_SBA - /* char f_name[100]; - int16_t nB = 1; - int16_t num_subframes = 1; - int16_t num_elem_per_subframe = 1; - int16_t num_block_group = 1; - int16_t byte_size = sizeof( int16_t ); - - sprintf( f_name, "DIRAC_MD_bitrate.bin" ); - ( frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elem_per_subframe, sizeof( num_elem_per_subframe ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; - dbgwrite( &hMetaData->nb_bits_tot, sizeof( int16_t ), 1, 1, f_name );*/ -#endif - } - else - { - hQMetaData->q_direction[0].cfg.nbands = DIRAC_DTX_BANDS; - - /* compute directions */ - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - set_zero( dir, 3 ); - set_zero( avg_dir, 3 ); - energySum = 0.0f; - - /*combine all dirac bands except the last one, handle last band separately, last band covers BW above WB*/ - for ( j = 0; j < orig_dirac_bands - 1; j++ ) - { - ivas_qmetadata_azimuth_elevation_to_direction_vector( hQMetaData->q_direction[0].band_data[j].azimuth[i], hQMetaData->q_direction[0].band_data[j].elevation[i], &dir[0] ); - vecLen = hQMetaData->q_direction[0].band_data[j].energy_ratio[i] * st_ivas->hDirAC->buffer_energy[i * orig_dirac_bands + j]; - - avg_dir[0] += dir[0] * vecLen; - avg_dir[1] += dir[1] * vecLen; - avg_dir[2] += dir[2] * vecLen; - - energySum += st_ivas->hDirAC->buffer_energy[i * orig_dirac_bands + j]; - } - - ivas_qmetadata_direction_vector_to_azimuth_elevation( &avg_dir[0], &hQMetaData->q_direction[0].band_data[0].azimuth[i], &hQMetaData->q_direction[0].band_data[0].elevation[i] ); - hQMetaData->q_direction[0].band_data[0].energy_ratio[i] = sqrtf( dotp( avg_dir, avg_dir, 3 ) ) / ( energySum + EPSILON ); - - hQMetaData->q_direction[0].band_data[1].azimuth[i] = hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i]; - hQMetaData->q_direction[0].band_data[1].elevation[i] = hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i]; - hQMetaData->q_direction[0].band_data[1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i]; - } - - /* 1 bit to indicate mode MD coding : temp solution*/ - push_next_indice( hMetaData, 1, 1 ); - - /* encode SID parameters */ - ivas_qmetadata_enc_sid_encode( hMetaData, hQMetaData, -1, SBA_FORMAT, st_ivas->sba_mode ); - } - - for ( b = hQMetaData->q_direction->cfg.start_band; b < hQMetaData->q_direction->cfg.nbands; b++ ) - { - for ( i_ts = 0; i_ts < ( ( dtx_vad == 1 ) ? hQMetaData->q_direction[0].cfg.nblocks : 1 ); i_ts++ ) - { - hQMetaData->q_direction->band_data[b].azimuth[i_ts] = hQMetaData->q_direction->band_data[b].q_azimuth[i_ts]; - hQMetaData->q_direction->band_data[b].elevation[i_ts] = hQMetaData->q_direction->band_data[b].q_elevation[i_ts]; - hQMetaData->q_direction[0].band_data[b].energy_ratio[0] = 1.0f - diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; - } - } - - if ( dtx_vad == 0 ) - { - - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth[i] = hQMetaData->q_direction[0].band_data[1].azimuth[0]; - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation[i] = hQMetaData->q_direction[0].band_data[1].elevation[0]; - hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio[0]; - } - - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - for ( j = orig_dirac_bands - 2; j >= 0; j-- ) - { - hQMetaData->q_direction[0].band_data[j].azimuth[i] = hQMetaData->q_direction[0].band_data[0].azimuth[0]; - hQMetaData->q_direction[0].band_data[j].elevation[i] = hQMetaData->q_direction[0].band_data[0].elevation[0]; - hQMetaData->q_direction[0].band_data[j].energy_ratio[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio[0]; - } - } - - hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; - } - } - - - /*-----------------------------------------------------------------------------------------* - * Pre-proc flags - *-----------------------------------------------------------------------------------------*/ - - /* use just VAD function to get VAD flags */ - dtx_vad = ( hEncoderConfig->Opt_DTX_ON == 1 ) ? front_vad_flag : 1; - dtx_cov_flag = ( dtx_vad == 1 ) ? 0 : 1; - dtx_silence_mode = 0; - bwidth = ivas_get_bw_idx_from_sample_rate( input_Fs ); - bwidth = min( bwidth, hEncoderConfig->max_bwidth ); - - /*-----------------------------------------------------------------------------------------* - * Covariance process - *-----------------------------------------------------------------------------------------*/ - - cov_in_buf.num_ch = nchan_inp; - - for ( i = 0; i < nchan_inp; i++ ) - { - for ( j = 0; j < nchan_inp; j++ ) - { - cov_real[i][j] = pState->hMdEnc->cov_real[i][j]; - cov_dtx_real[i][j] = pState->hMdEnc->cov_dtx_real[i][j]; - } - } - - cov_in_buf.dtx_cov_flag = dtx_cov_flag; - ivas_enc_cov_handler_process( pState->hCovEnc, &cov_in_buf, cov_real, cov_dtx_real, pState->hFbMixer->pFb, 0, pState->hFbMixer->pFb->filterbank_num_bands ); - - if ( pState->hMdEnc->table_idx != table_idx ) - { - pState->hMdEnc->table_idx = table_idx; - ivas_spar_set_bitrate_config( &pState->hMdEnc->spar_md_cfg, table_idx, SPAR_DIRAC_SPLIT_START_BAND ); - } - - nchan_transport = pState->hMdEnc->spar_md_cfg.nchan_transport; - - /*-----------------------------------------------------------------------------------------* - * MetaData encoder - *-----------------------------------------------------------------------------------------*/ - - num_bands_bw = ivas_get_num_bands_from_bw_idx( bwidth ); - - if ( dtx_vad == 0 ) - { - for ( i = 0; i < nchan_inp; i++ ) - { - for ( j = 0; j < nchan_inp; j++ ) - { - md_in_buf.cov_real[i][j] = cov_dtx_real[i][j]; - for ( k = num_bands_bw; k < IVAS_MAX_NUM_BANDS; k++ ) - { - md_in_buf.cov_real[i][j][k] = 0; - } - } - } - } - else - { - for ( i = 0; i < nchan_inp; i++ ) - { - for ( j = 0; j < nchan_inp; j++ ) - { - md_in_buf.cov_real[i][j] = cov_real[i][j]; - for ( k = num_bands_bw; k < IVAS_MAX_NUM_BANDS; k++ ) - { - md_in_buf.cov_real[i][j][k] = 0; - } - } - } - } - - md_in_buf.num_bands = ivas_get_num_bands_from_bw_idx( SPAR_CONFIG_BW ); - md_in_buf.num_bands = min( md_in_buf.num_bands, SPAR_DIRAC_SPLIT_START_BAND ); - - md_in_buf.dtx_vad = dtx_vad; - - ivas_spar_foa_md_enc_process( pState->hMdEnc, hEncoderConfig, &md_in_buf, hMetaData, dtx_silence_mode -#ifdef LBR_SBA - , pState->hFbMixer->prior_mixer -#endif - ); - - if ( st_ivas->sba_mode == SBA_MODE_SPAR ) - { - float azi_dirac[IVAS_MAX_NUM_BANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; - float ele_dirac[IVAS_MAX_NUM_BANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; - float diffuseness[IVAS_MAX_NUM_BANDS]; - float Wscale_d[IVAS_MAX_NUM_BANDS]; - int16_t d_start_band, d_end_band; - int16_t dirac_band_idx; - - d_start_band = st_ivas->hSpar->hSparFoa->enc_param_start_band; - d_end_band = IVAS_MAX_NUM_BANDS; - - for ( b = d_start_band; b < d_end_band; b++ ) - { - dirac_band_idx = st_ivas->hSpar->hSparFoa->dirac_to_spar_md_bands[b] - d_start_band; - for ( i_ts = 0; i_ts < hQMetaData->q_direction->cfg.nblocks; i_ts++ ) - { - azi_dirac[b][i_ts] = hQMetaData->q_direction->band_data[dirac_band_idx].azimuth[i_ts]; - ele_dirac[b][i_ts] = hQMetaData->q_direction->band_data[dirac_band_idx].elevation[i_ts]; - } - diffuseness[b] = 1.0f - hQMetaData->q_direction->band_data[dirac_band_idx].energy_ratio[0]; - } - - if ( ( d_start_band >= 6 ) && ( dtx_vad == 1 ) ) - { - for ( i = 0; i < IVAS_SPAR_MAX_CH - 1; i++ ) - { - pState->hMdEnc->spar_md.band_coeffs[d_start_band - 1].P_re[i] = - pState->hMdEnc->spar_md.band_coeffs[d_start_band - 1].P_quant_re[i]; - } - } - - for ( b = d_start_band; b < d_end_band; b++ ) - { - Wscale_d[b] = 1.0f; - for ( i = 1; i < nchan_inp; i++ ) - { - Wscale_d[b] += md_in_buf.cov_real[i][i][b] / max( EPSILON, md_in_buf.cov_real[0][0][b] ); - } - Wscale_d[b] = Wscale_d[b] / ( 1.0f + (float) sba_order ); /*DirAC normalized signal variance sums to 1 + order*/ - Wscale_d[b] = sqrtf( Wscale_d[b] ); - Wscale_d[b] = min( 2.0f, max( Wscale_d[b], 1.0f ) ); - } - - ivas_get_spar_md_from_dirac( azi_dirac, ele_dirac, diffuseness, 1, pState->hMdEnc->mixer_mat, &pState->hMdEnc->spar_md, &pState->hMdEnc->spar_md_cfg, - d_start_band, d_end_band, sba_order, dtx_vad, Wscale_d -#ifdef LBR_SBA - , hQMetaData->useLowerRes, active_w_vlbr -#endif - ); - } -#ifdef DEBUG_LBR_SBA - /* Dumping SPAR Coefficients */ - char f_name[100]; - int16_t nbands = 6; - int16_t num_subframes = 1; - int16_t num_elements = 6; - int16_t num_block_group = 1; - int16_t byte_size = sizeof( float ); - - sprintf( f_name, "SBA_MD_values.bin" ); - ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; - - for ( b = 0; b < nbands; b++ ) - { - for ( int16_t sf = 0; sf < num_subframes; sf++ ) - { - for ( int16_t bl = 0; bl < num_block_group; bl++ ) - { - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_re[0], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_re[1], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_re[2], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_re[0], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_re[1], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_re[2], byte_size, 1, 1, f_name ); - // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); - } - } - } -#endif -#ifdef DEBUG_LBR_SBA - /* Dumping SPAR Coefficients */ - nbands = 6; - num_subframes = 1; - num_elements = 6; - num_block_group = 1; - byte_size = sizeof( float ); - - sprintf( f_name, "SBA_MD_values_quant.bin" ); - ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; - - for ( b = 0; b < nbands; b++ ) - { - for ( int16_t sf = 0; sf < num_subframes; sf++ ) - { - for ( int16_t bl = 0; bl < num_block_group; bl++ ) - { - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_quant_re[0], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_quant_re[1], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].pred_quant_re[2], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_quant_re[0], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_quant_re[1], byte_size, 1, 1, f_name ); - dbgwrite( &pState->hMdEnc->spar_md.band_coeffs[b].P_quant_re[2], byte_size, 1, 1, f_name ); - // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); - } - } - } -#endif - /*-----------------------------------------------------------------------------------------* - * FB mixer - *-----------------------------------------------------------------------------------------*/ - - ivas_fb_mixer_get_in_out_mapping( pState->hFbMixer->fb_cfg, nchan_transport, ENC, remix_order_set[pState->hMdEnc->spar_md_cfg.remix_unmix_order], in_out_mixer_map ); - -#ifdef DEBUG_SPAR_FOA - { - static FILE *f_mat = 0; - - if ( f_mat == 0 ) - f_mat = fopen( "mixer_mat_enc", "w" ); - - for ( i = 0; i < pState->hFbMixer->fb_cfg->num_out_chans; i++ ) - { - for ( j = 0; j < pState->hFbMixer->fb_cfg->num_in_chans; j++ ) - { - for ( k = 0; k < pState->hFbMixer->pFb->filterbank_num_bands; k++ ) - { - fprintf( f_mat, "%f\n", pState->hMdEnc->mixer_mat[i][j][k] ); - - if ( ( in_out_mixer_map[i][j] == 0 ) && ( fabs( pState->hMdEnc->mixer_mat[i][j][k] ) > 1e-20 ) ) - { - assert( 0 && "Non zero value in unexpected mixer map!!!" ); - } - } - } - } - } -#endif -#ifdef DEBUG_SPAR_DIRAC_WRITE_OUT_PRED_PARS - { - static FILE *fid = 0; - int16_t band = 9; - if ( !fid ) - { - fid = fopen( "pred_coeffs_enc.txt", "wt" ); - } - fprintf( fid, "%.6f\n", pState->hMdEnc->mixer_mat[1][0][band] ); - } -#endif - - ivas_fb_mixer_process( pState->hFbMixer, pState->hMdEnc->mixer_mat, p_pcm_tmp, input_frame, in_out_mixer_map ); - - /* move delayed W into output buffer unless activeW operation*/ - if ( pState->hFbMixer->fb_cfg->active_w_mixing == 0 ) - { - mvr2r( w_del_buf, p_pcm_tmp[0], num_del_samples ); - mvr2r( data_f[0], p_pcm_tmp[0] + num_del_samples, input_frame - num_del_samples ); - } - - /*-----------------------------------------------------------------------------------------* - * PCA encoder - *-----------------------------------------------------------------------------------------*/ - - if ( pState->hPCA != NULL ) - { - ivas_pca_enc( hEncoderConfig, pState->hPCA, hMetaData, p_pcm_tmp, input_frame, FOA_CHANNELS ); - } - else - { - if ( ( ivas_total_brate == PCA_BRATE ) && ( sba_order == 1 ) ) - { - /* write PCA bypass bit */ - push_next_indice( hMetaData, PCA_MODE_INACTIVE, 1 ); - } - } - - -#ifdef DEBUG_LBR_SBA - for ( int t = 0; t < 960; t++ ) - { - for ( int c = 0; c < pState->hFbMixer->fb_cfg->num_out_chans; c++ ) - { - float val = p_pcm_tmp[c][t]; // / MAX16B_FLT; - dbgwrite( &val, sizeof( float ), 1, 1, "int_enc_dmx.raw" ); - } - } -#endif - /*-----------------------------------------------------------------------------------------* - * AGC - *-----------------------------------------------------------------------------------------*/ - - if ( dtx_vad == 1 ) - { - if ( hEncoderConfig->Opt_AGC_ON > 0 ) - { - ivas_agc_enc_process( pState->hAgcEnc, hMetaData, p_pcm_tmp, p_pcm_tmp, pState->hFbMixer->fb_cfg->num_out_chans, hEncoderConfig ); - } - else - { - push_next_indice( hMetaData, 0, 1 ); - } - } - -#ifdef DEBUG_SPAR_BYPASS_EVS_CODEC - { - static FILE *fid_enc = 0; - static float delay_buf[576 * 4] = { 0 }; - int16_t smp, ch, buf_idx, framelen = input_frame, delay = 576; - if ( !fid_enc ) - { - fid_enc = fopen( "evs_input_float.raw", "wb" ); - } - - /* write out buffer */ - for ( smp = 0; smp < delay * nchan_transport; smp++ ) - { - fwrite( &delay_buf[smp], sizeof( float ), 1, fid_enc ); - } - - for ( smp = 0; smp < framelen - delay; smp++ ) - { - for ( ch = 0; ch < nchan_transport; ch++ ) - { - fwrite( &p_pcm_tmp[ch][smp], sizeof( float ), 1, fid_enc ); - } - } - - /* update delay buffer*/ - buf_idx = 0; - for ( ; smp < framelen; smp++ ) - { - for ( ch = 0; ch < nchan_transport; ch++ ) - { - delay_buf[buf_idx++] = p_pcm_tmp[ch][smp]; - } - } - } -#endif - -#ifdef DEBUG_SPAR_FOA - float tmp; - int16_t pcm; - - for ( j = 0; j < input_frame; j++ ) - { - for ( i = 0; i < nchan_transport; i++ ) - { - tmp = roundf( p_pcm_tmp[i][j] * PCM16_TO_FLT_FAC ); - pcm = ( tmp > MAX16B_FLT ) ? MAX16B : ( tmp < MIN16B_FLT ) ? MIN16B - : (short) tmp; - dbgwrite( &pcm, sizeof( int16_t ), 1, 1, "dmx.raw" ); - } - } - - /* Plug evs i/p from Matlab */ - if ( fEvs_enc_in != NULL ) - { - /*printf("evs enc in file found\n");*/ - float tmp_in = 0; - int16_t diff[FOA_CHANNELS][L_FRAME48k], tmp16; - int16_t max_diff = 0; - int16_t abs_tol = 8; - - for ( i = 0; i < input_frame; i++ ) - { - for ( j = 0; j < nchan_transport; j++ ) - { - tmp = p_pcm_tmp[j][i]; - tmp = roundf( tmp * PCM16_TO_FLT_FAC ); - tmp16 = ( tmp > MAX16B_FLT ) ? MAX16B : ( tmp < MIN16B_FLT ) ? MIN16B - : (int16_t) tmp; - fscanf( fEvs_enc_in, "%f\n", &tmp_in ); - p_pcm_tmp[j][i] = tmp_in; - - tmp = roundf( tmp_in * PCM16_TO_FLT_FAC ); - pcm = ( tmp > MAX16B_FLT ) ? MAX16B : ( tmp < MIN16B_FLT ) ? MIN16B - : (int16_t) tmp; - diff[j][i] = (int16_t) abs( tmp16 - pcm ); - max_diff = max( max_diff, diff[j][i] ); - } - } - - if ( max_diff > abs_tol ) - { - IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "SPAR FOA ENC fb mixer out mismatch, max diff = %d", max_diff ); - } - } -#endif - - /*-----------------------------------------------------------------------------------------* - * Re-order the dmx back to ACN/SN3D format - *-----------------------------------------------------------------------------------------*/ - - order = remix_order_set[pState->hMdEnc->spar_md_cfg.remix_unmix_order]; - - for ( i = 0; i < input_frame; i++ ) - { - for ( j = 0; j < nchan_transport; j++ ) - { - data_f[order[j]][i] = p_pcm_tmp[j][i] * PCM16_TO_FLT_FAC; - } - for ( ; j < IVAS_SPAR_MAX_DMX_CHS; j++ ) - { - data_f[order[j]][i] = 0; - } - } - - wmops_sub_end(); - - return error; -} diff --git a/lib_enc/ivas_spar_foa_md_enc.c b/lib_enc/ivas_spar_md_enc.c similarity index 60% rename from lib_enc/ivas_spar_foa_md_enc.c rename to lib_enc/ivas_spar_md_enc.c index 52b790e16b906d531d724caa0e98c551f2c03e75..23a67e9bc8f1c225a107b391a6575c71275c21c7 100644 --- a/lib_enc/ivas_spar_foa_md_enc.c +++ b/lib_enc/ivas_spar_md_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,28 +40,14 @@ #include "math.h" #include "ivas_rom_com.h" #include -#include "wmops.h" +#include "wmc_auto.h" -#ifdef DEBUG_SPAR_FOA -extern FILE *fMd_data; -extern float max_diff; -extern int32_t dbg_frm_num; -extern int32_t dbg_band; -extern int32_t dbg_type; -int32_t frm = 0; -#endif - /*------------------------------------------------------------------------------------------* * PreProcessor *------------------------------------------------------------------------------------------*/ #define IVAS_MAX_MD_BYTES ( 1000 ) -#ifdef DEBUG_SPAR_FOA -#define MD_TOL ( 0.00015f ) -#define MD_TOL_MAX ( 0.012f ) -#endif - static const float pr_boost_range[2] = { 0.1f, 0.4f }; typedef enum ivas_strats_t @@ -86,14 +72,14 @@ static void ivas_band_mixer( float *cov_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], static void ivas_get_band_differential_index( ivas_band_coeffs_ind_t *pBand_idx, const int16_t q_levels[2], const int16_t one_sided, const int16_t nB, const int16_t complex_cov, const int16_t dim, const ivas_coeffs_type_t coeff_type ); -static void ivas_get_huffman_coded_bs( ivas_spar_foa_md_enc_state_t *pState, BSTR_ENC_HANDLE hMetaData, const int16_t nB, const int16_t qsi, const int16_t planarCP +static void ivas_get_huffman_coded_bs( ivas_spar_md_enc_state_t *hMdEnc, BSTR_ENC_HANDLE hMetaData, const int16_t nB, const int16_t qsi, const int16_t planarCP #ifdef LBR_SBA , const int16_t bands_bw #endif ); -static void ivas_get_arith_coded_bs( ivas_spar_foa_md_enc_state_t *pState, BSTR_ENC_HANDLE hMetaData, const int16_t *pDo_diff, const int16_t bands_bw, const int16_t nB, const int16_t qsi, const int16_t planarCP +static void ivas_get_arith_coded_bs( ivas_spar_md_enc_state_t *hMdEnc, BSTR_ENC_HANDLE hMetaData, const int16_t *pDo_diff, const int16_t bands_bw, const int16_t nB, const int16_t qsi, const int16_t planarCP #ifdef LBR_SBA , const int16_t strat, @@ -101,25 +87,20 @@ static void ivas_get_arith_coded_bs( ivas_spar_foa_md_enc_state_t *pState, BSTR_ #endif ); -static ivas_error ivas_spar_foa_set_enc_config( ivas_spar_foa_md_enc_state_t *pState, int16_t *max_freq_per_chan, const int16_t nchan_transport, float *pFC, const int16_t nchan_inp ); +static ivas_error ivas_spar_set_enc_config( ivas_spar_md_enc_state_t *hMdEnc, int16_t *max_freq_per_chan, const int16_t nchan_transport, float *pFC, const int16_t nchan_inp ); static void ivas_select_next_strat( ivas_strats_t prior_strat, ivas_strats_t cs[MAX_QUANT_STRATS], const int16_t dmx_switch, const int16_t dtx_vad ); -static void ivas_store_prior_coeffs( ivas_spar_foa_md_enc_state_t *hMdEnc, const int16_t num_bands, +static void ivas_store_prior_coeffs( ivas_spar_md_enc_state_t *hMdEnc, const int16_t num_bands, #ifndef LBR_SBA const int16_t bands_bw, #endif - const int16_t strat, - const int16_t dtx_vad, - const int16_t qsi ); - -static void ivas_write_parameter_bitstream( ivas_spar_foa_md_enc_state_t *hMdEnc, const int16_t nB, const int16_t bands_bw, BSTR_ENC_HANDLE hMetaData, const int32_t ivas_total_brate, const int16_t dtx_silence_mode, const int16_t strat, const int16_t qsi, const int16_t planarCP ); + const int16_t strat, const int16_t dtx_vad, const int16_t qsi ); -static ivas_error ivas_spar_foa_md_enc_init( ivas_spar_foa_md_enc_state_t *pState, const ENCODER_CONFIG_HANDLE hEncoderConfig ); +static void ivas_write_spar_md_bitstream( ivas_spar_md_enc_state_t *hMdEnc, const int16_t nB, const int16_t bands_bw, BSTR_ENC_HANDLE hMetaData, const int32_t ivas_total_brate, const int16_t strat, const int16_t qsi, const int16_t planarCP ); +static void ivas_spar_quant_pred_coeffs_dtx( ivas_spar_md_t *pSpar_md, const float *pValues, const int16_t ndm, int16_t *pIndex, const int16_t dim1, float *pQuant ); -static void ivas_spar_foa_quant_pred_coeffs_dtx( ivas_spar_md_t *pSpar_md, float **ppValues, const int16_t ndm, int16_t **ppIndex, const int16_t dim1, float **ppQuant ); - -static void ivas_quant_p_per_band_dtx( float **ppP_mat, const int16_t num_dec, const int16_t num_dmx, int16_t *ppIdx_pd, float **ppP_out, const int16_t num_ch ); +static void ivas_quant_p_per_band_dtx( float *pP_mat, const int16_t num_dec, const int16_t num_dmx, int16_t *ppIdx_pd, float *pP_out, const int16_t num_ch ); static void ivas_write_parameter_bitstream_dtx( ivas_spar_md_t *pSpar_md, BSTR_ENC_HANDLE hMetaData, int16_t *num_dmx, int16_t *num_dec, const int16_t num_bands ); @@ -131,107 +112,111 @@ static void ivas_quant_pred_coeffs_per_band( ivas_band_coeffs_t *pband_coeffs, i /*------------------------------------------------------------------------- - * ivas_spar_foa_md_enc_open() + * ivas_spar_md_enc_open() * * Allocate and initialize SPAR MD encoder handle *------------------------------------------------------------------------*/ -ivas_error ivas_spar_foa_md_enc_open( - ivas_spar_foa_md_enc_state_t **hMdEnc_in, /* i/o: SPAR MD encoder handle */ - const ENCODER_CONFIG_HANDLE hEncoderConfig /* i : configuration structure */ +ivas_error ivas_spar_md_enc_open( + ivas_spar_md_enc_state_t **hMdEnc_in, /* i/o: SPAR MD encoder handle */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { - ivas_spar_foa_md_enc_state_t *hMdEnc; + ivas_spar_md_enc_state_t *hMdEnc; ivas_error error; - int16_t num_channels, i, j, order; - order = min( hEncoderConfig->sba_order, IVAS_MAX_SBA_ORDER ); + int16_t num_channels, i, j; error = IVAS_ERR_OK; - if ( ( hMdEnc = (ivas_spar_foa_md_enc_state_t *) count_malloc( sizeof( ivas_spar_foa_md_enc_state_t ) ) ) == NULL ) + if ( ( hMdEnc = (ivas_spar_md_enc_state_t *) malloc( sizeof( ivas_spar_md_enc_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD encoder" ); } - num_channels = 2 * order + 2; + num_channels = ivas_sba_get_nchan_metadata( sba_order ); - if ( ( hMdEnc->mixer_mat = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdEnc->spar_md.band_coeffs = (ivas_band_coeffs_t *) malloc( IVAS_MAX_NUM_BANDS * sizeof( ivas_band_coeffs_t ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for band_coeffs in SPAR MD" ); + } + if ( ( hMdEnc->mixer_mat = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdEnc->mixer_mat[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdEnc->mixer_mat[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdEnc->mixer_mat[i][j] = (float *) count_malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdEnc->mixer_mat[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( hMdEnc->cov_real = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdEnc->cov_real = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdEnc->cov_real[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdEnc->cov_real[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdEnc->cov_real[i][j] = (float *) count_malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdEnc->cov_real[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" ); } } } - if ( ( hMdEnc->cov_dtx_real = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdEnc->cov_dtx_real = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdEnc->cov_dtx_real[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdEnc->cov_dtx_real[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdEnc->cov_dtx_real[i][j] = (float *) count_malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdEnc->cov_dtx_real[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" ); } } } - if ( ( hMdEnc->mixer_mat_local = (float ***) count_malloc( num_channels * sizeof( float ** ) ) ) == NULL ) + if ( ( hMdEnc->mixer_mat_local = (float ***) malloc( num_channels * sizeof( float ** ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( i = 0; i < num_channels; i++ ) { - if ( ( hMdEnc->mixer_mat_local[i] = (float **) count_malloc( num_channels * sizeof( float * ) ) ) == NULL ) + if ( ( hMdEnc->mixer_mat_local[i] = (float **) malloc( num_channels * sizeof( float * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } for ( j = 0; j < num_channels; j++ ) { - if ( ( hMdEnc->mixer_mat_local[i][j] = (float *) count_malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) + if ( ( hMdEnc->mixer_mat_local[i][j] = (float *) malloc( IVAS_MAX_NUM_BANDS * sizeof( float ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR MD matrix" ); } } } - if ( ( error = ivas_spar_foa_md_enc_init( hMdEnc, hEncoderConfig ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_spar_md_enc_init( hMdEnc, hEncoderConfig, sba_order ) ) != IVAS_ERR_OK ) { return error; } @@ -243,60 +228,68 @@ ivas_error ivas_spar_foa_md_enc_open( /*------------------------------------------------------------------------- - * ivas_spar_foa_md_enc_close() + * ivas_spar_md_enc_close() * * Deallocate SPAR MD encoder handle *------------------------------------------------------------------------*/ -void ivas_spar_foa_md_enc_close( - ivas_spar_foa_md_enc_state_t **hMdEnc_in /* i/o: SPAR MD encoder handle */ +void ivas_spar_md_enc_close( + ivas_spar_md_enc_state_t **hMdEnc_in /* i/o: SPAR MD encoder handle */ ) { int16_t num_channels, i, j; - ivas_spar_foa_md_enc_state_t *hMdEnc; + ivas_spar_md_enc_state_t *hMdEnc; + + if ( hMdEnc_in == NULL || *hMdEnc_in == NULL ) + { + return; + } hMdEnc = *hMdEnc_in; num_channels = hMdEnc->num_umx_ch; + if ( hMdEnc->spar_md.band_coeffs != NULL ) + { + free( hMdEnc->spar_md.band_coeffs ); + hMdEnc->spar_md.band_coeffs = NULL; + } if ( hMdEnc->mixer_mat != NULL ) { for ( i = 0; i < num_channels; i++ ) { for ( j = 0; j < num_channels; j++ ) { - count_free( hMdEnc->mixer_mat[i][j] ); + free( hMdEnc->mixer_mat[i][j] ); } - count_free( hMdEnc->mixer_mat[i] ); + free( hMdEnc->mixer_mat[i] ); } - count_free( hMdEnc->mixer_mat ); + free( hMdEnc->mixer_mat ); } if ( hMdEnc->cov_real != NULL ) { for ( i = 0; i < num_channels; i++ ) { - for ( j = 0; j < num_channels; j++ ) { - count_free( hMdEnc->cov_real[i][j] ); + free( hMdEnc->cov_real[i][j] ); } - count_free( hMdEnc->cov_real[i] ); + free( hMdEnc->cov_real[i] ); } - count_free( hMdEnc->cov_real ); + free( hMdEnc->cov_real ); } if ( hMdEnc->cov_dtx_real != NULL ) { for ( i = 0; i < num_channels; i++ ) { - for ( j = 0; j < num_channels; j++ ) { - count_free( hMdEnc->cov_dtx_real[i][j] ); + free( hMdEnc->cov_dtx_real[i][j] ); } - count_free( hMdEnc->cov_dtx_real[i] ); + free( hMdEnc->cov_dtx_real[i] ); } - count_free( hMdEnc->cov_dtx_real ); + free( hMdEnc->cov_dtx_real ); } if ( hMdEnc->mixer_mat_local != NULL ) @@ -306,48 +299,42 @@ void ivas_spar_foa_md_enc_close( for ( j = 0; j < num_channels; j++ ) { - count_free( hMdEnc->mixer_mat_local[i][j] ); + free( hMdEnc->mixer_mat_local[i][j] ); } - count_free( hMdEnc->mixer_mat_local[i] ); + free( hMdEnc->mixer_mat_local[i] ); } - count_free( hMdEnc->mixer_mat_local ); + free( hMdEnc->mixer_mat_local ); } - if ( hMdEnc != NULL ) - { - count_free( hMdEnc ); - hMdEnc = NULL; - } + free( *hMdEnc_in ); + *hMdEnc_in = NULL; return; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_md_enc_init() + * Function ivas_spar_md_enc_init() * - * Init call for md gen process + * SPAR MD encoder initialization *-----------------------------------------------------------------------------------------*/ - -static ivas_error ivas_spar_foa_md_enc_init( - ivas_spar_foa_md_enc_state_t *pState, /* o : MD encoder handle */ - const ENCODER_CONFIG_HANDLE hEncoderConfig /* i : configuration structure */ +ivas_error ivas_spar_md_enc_init( + ivas_spar_md_enc_state_t *hMdEnc, /* o : MD encoder handle */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { float pFC[IVAS_MAX_NUM_BANDS]; int16_t table_idx; float PR_minmax[2]; - int16_t sba_order; int16_t num_channels, i, j, k; - sba_order = min( hEncoderConfig->sba_order, IVAS_MAX_SBA_ORDER ); - + hMdEnc->spar_hoa_md_flag = ivas_sba_get_spar_hoa_md_flag( sba_order, hEncoderConfig->ivas_total_brate ); num_channels = ivas_sba_get_nchan_metadata( sba_order ); table_idx = ivas_get_spar_table_idx( hEncoderConfig->ivas_total_brate, sba_order, SPAR_CONFIG_BW, NULL, NULL ); - pState->spar_md_cfg.gen_bs = 1; - ivas_spar_set_bitrate_config( &pState->spar_md_cfg, table_idx, SPAR_DIRAC_SPLIT_START_BAND ); + ivas_spar_set_bitrate_config( &hMdEnc->spar_md_cfg, table_idx, ( hMdEnc->spar_hoa_md_flag ) ? IVAS_MAX_NUM_BANDS : SPAR_DIRAC_SPLIT_START_BAND ); /* get FB coefficients */ for ( i = 0; i < IVAS_MAX_NUM_BANDS; i++ ) @@ -355,39 +342,26 @@ static ivas_error ivas_spar_foa_md_enc_init( pFC[i] = ivas_fb_fcs_12band_1ms[i] * hEncoderConfig->input_Fs * 0.5f; } - ivas_spar_foa_set_enc_config( pState, pState->spar_md_cfg.max_freq_per_chan, pState->spar_md_cfg.nchan_transport, pFC, num_channels ); - /* - if(pState->spar_md_cfg.quant_strat[0].C.q_levels[0] == 0 || pState->spar_md_cfg.quant_strat[0].C.q_levels[1] == 0 - || pState->spar_md_cfg.quant_strat[0].PR.q_levels[0] == 0 || pState->spar_md_cfg.quant_strat[0].PR.q_levels[1] == 0 - || pState->spar_md_cfg.quant_strat[0].P_c.q_levels[0] == 0 || pState->spar_md_cfg.quant_strat[0].P_c.q_levels[1] == 0 - || pState->spar_md_cfg.quant_strat[0].P_r.q_levels[0] == 0 || pState->spar_md_cfg.quant_strat[0].P_r.q_levels[1] == 0) - { - pState->spar_md_cfg.gen_bs = 0; - } - else if(0 != pState->spar_md_cfg.gen_bs) - { - pState->spar_md_cfg.quant_strat_bits = ivas_get_bits_to_encode(MAX_QUANT_STRATS); - } -*/ + ivas_spar_set_enc_config( hMdEnc, hMdEnc->spar_md_cfg.max_freq_per_chan, hMdEnc->spar_md_cfg.nchan_transport, pFC, num_channels ); - if ( pState->spar_md_cfg.nchan_transport != 2 && ( ( pState->spar_md_cfg.remix_unmix_order == 1 ) || ( pState->spar_md_cfg.remix_unmix_order == 2 ) ) ) + if ( hMdEnc->spar_md_cfg.nchan_transport != 2 && ( ( hMdEnc->spar_md_cfg.remix_unmix_order == 1 ) || ( hMdEnc->spar_md_cfg.remix_unmix_order == 2 ) ) ) { return IVAS_ERR_INTERNAL; } - ivas_arith_coeffs_enc_init( &pState->arith_coeffs, &pState->spar_md_cfg, table_idx ); - ivas_huff_coeffs_enc_init( &pState->huff_coeffs, table_idx ); + ivas_spar_arith_coeffs_com_init( &hMdEnc->arith_coeffs, &hMdEnc->spar_md_cfg, table_idx, ENC ); + ivas_spar_huff_coeffs_com_init( &hMdEnc->huff_coeffs, NULL, table_idx, ENC ); if ( hEncoderConfig->Opt_DTX_ON == 1 ) { /* DTX quant init */ - PR_minmax[0] = pState->spar_md_cfg.quant_strat[0].PR.min; - PR_minmax[1] = pState->spar_md_cfg.quant_strat[0].PR.max; - ivas_spar_quant_dtx_init( &pState->spar_md, PR_minmax ); + PR_minmax[0] = hMdEnc->spar_md_cfg.quant_strat[0].PR.min; + PR_minmax[1] = hMdEnc->spar_md_cfg.quant_strat[0].PR.max; + ivas_spar_quant_dtx_init( &hMdEnc->spar_md, PR_minmax ); } - pState->spar_md_cfg.prior_strat = START; - pState->spar_md_cfg.prev_quant_idx = -1; + hMdEnc->spar_md_cfg.prior_strat = START; + hMdEnc->spar_md_cfg.prev_quant_idx = -1; for ( i = 0; i < num_channels; i++ ) { @@ -395,7 +369,7 @@ static ivas_error ivas_spar_foa_md_enc_init( { for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ ) { - pState->mixer_mat[i][j][k] = 0; + hMdEnc->mixer_mat[i][j][k] = 0; } } } @@ -406,29 +380,29 @@ static ivas_error ivas_spar_foa_md_enc_init( { for ( k = 0; k < IVAS_MAX_NUM_BANDS; k++ ) { - pState->cov_real[i][j][k] = 0; - pState->cov_dtx_real[i][j][k] = 0; + hMdEnc->cov_real[i][j][k] = 0; + hMdEnc->cov_dtx_real[i][j][k] = 0; } } } - ivas_clear_band_coeffs( pState->spar_md.band_coeffs, IVAS_MAX_NUM_BANDS ); - ivas_clear_band_coeff_idx( pState->spar_md.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); - ivas_clear_band_coeff_idx( pState->spar_md_prior.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); - ivas_clear_band_coeff_idx( pState->spar_md_prior.band_coeffs_idx_mapped, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeffs( hMdEnc->spar_md.band_coeffs, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeff_idx( hMdEnc->spar_md.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeff_idx( hMdEnc->spar_md_prior.band_coeffs_idx, IVAS_MAX_NUM_BANDS ); + ivas_clear_band_coeff_idx( hMdEnc->spar_md_prior.band_coeffs_idx_mapped, IVAS_MAX_NUM_BANDS ); return IVAS_ERR_OK; } /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_set_enc_config() + * Function ivas_spar_set_enc_config() * - * Set configuration for SPAR FOA md gen + * Set configuration for SPAR MD encoder *-----------------------------------------------------------------------------------------*/ -static ivas_error ivas_spar_foa_set_enc_config( - ivas_spar_foa_md_enc_state_t *pState, +static ivas_error ivas_spar_set_enc_config( + ivas_spar_md_enc_state_t *hMdEnc, int16_t *max_freq_per_chan, const int16_t nchan_transport, float *pFC, @@ -441,29 +415,29 @@ static ivas_error ivas_spar_foa_set_enc_config( { if ( max_freq_per_chan != NULL ) { - pState->spar_md_cfg.max_freq_per_chan[i] = ( max_freq_per_chan[i] != 0 ) ? max_freq_per_chan[i] : max_freq_per_chan[0]; + hMdEnc->spar_md_cfg.max_freq_per_chan[i] = ( max_freq_per_chan[i] != 0 ) ? max_freq_per_chan[i] : max_freq_per_chan[0]; } else { - pState->spar_md_cfg.max_freq_per_chan[i] = IVAS_SPAR_FOA_DFLT_FREQ_PER_CHAN; + hMdEnc->spar_md_cfg.max_freq_per_chan[i] = IVAS_SPAR_FOA_DFLT_FREQ_PER_CHAN; } } - pState->num_umx_ch = nchan_inp; - pState->num_decorr = nchan_inp - 1; + hMdEnc->num_umx_ch = nchan_inp; + hMdEnc->num_decorr = nchan_inp - 1; for ( i = 0; i < IVAS_MAX_NUM_BANDS; i++ ) { tmp_dmx_ch = 0; for ( j = 0; j < nchan_transport; j++ ) { - if ( pFC[i] < pState->spar_md_cfg.max_freq_per_chan[j] ) + if ( pFC[i] < hMdEnc->spar_md_cfg.max_freq_per_chan[j] ) { tmp_dmx_ch += 1; } } - pState->spar_md_cfg.num_dmx_chans_per_band[i] = tmp_dmx_ch; - pState->spar_md_cfg.num_decorr_per_band[i] = pState->num_umx_ch - tmp_dmx_ch; + hMdEnc->spar_md_cfg.num_dmx_chans_per_band[i] = tmp_dmx_ch; + hMdEnc->spar_md_cfg.num_decorr_per_band[i] = hMdEnc->num_umx_ch - tmp_dmx_ch; } return IVAS_ERR_OK; @@ -477,7 +451,7 @@ static ivas_error ivas_spar_foa_set_enc_config( *-----------------------------------------------------------------------------------------*/ static void ivas_band_limit_dmx_matrix( - ivas_spar_foa_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ + ivas_spar_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ const int16_t num_ch, const int16_t num_bands, const int16_t bands_bw ) @@ -508,7 +482,7 @@ static void ivas_band_limit_dmx_matrix( *-----------------------------------------------------------------------------------------*/ static void ivas_band_mixing( - ivas_spar_foa_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ + ivas_spar_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ const int16_t num_ch, const int16_t num_bands, const int16_t nchan_transport, @@ -571,17 +545,20 @@ static void write_metadata_buffer( /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_md_enc_process() + * Function ivas_spar_md_enc_process() * * SPAR FoA Meta Data generation process *-----------------------------------------------------------------------------------------*/ -ivas_error ivas_spar_foa_md_enc_process( - ivas_spar_foa_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ +ivas_error ivas_spar_md_enc_process( + ivas_spar_md_enc_state_t *hMdEnc, /* i/o: SPAR MD encoder handle */ const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ - ivas_spar_foa_md_enc_in_buf_t *pIn_buf, - BSTR_ENC_HANDLE hMetaData, /* i/o: MetaData handle */ - const int16_t dtx_silence_mode + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + BSTR_ENC_HANDLE hMetaData, /* i/o: MetaData handle */ + const int16_t dtx_vad, + const int16_t nchan_inp, + const int16_t sba_order /* i : Ambisonic (SBA) order */ #ifdef LBR_SBA , const float *prior_mixer[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH] /* i : prior mixer_matrix */ @@ -590,12 +567,11 @@ ivas_error ivas_spar_foa_md_enc_process( { float pred_coeffs_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS]; float dm_fv_re[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS]; - - int16_t i, b, qsi, ndm, ndec, num_ch; + float pred_coeffs_re_local[IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS]; + int16_t i, b, qsi, ndm, ndec, num_ch, num_quant_strats; int16_t j, planarCP; - int16_t num_bands = pIn_buf->num_bands; - int16_t dtx_vad = pIn_buf->dtx_vad; - int16_t active_w, nchan_transport, dmx_switch, strat, sba_order; + int16_t k, bwidth, num_bands, num_bands_full, num_bands_bw; + int16_t active_w, nchan_transport, dmx_switch, strat; int16_t nB, bands_bw, packed_ok = 0; ivas_strats_t cs[MAX_CODING_STRATS]; int16_t code_strat; @@ -603,25 +579,49 @@ ivas_error ivas_spar_foa_md_enc_process( BSTR_ENC_DATA hMetaData_tmp; Indice ind_list_tmp[MAX_BITS_METADATA]; // IVAS_fmToDo: size to be optimized float Wscale[IVAS_MAX_NUM_BANDS]; - ivas_spar_foa_md_enc_state_t *pState = hMdEnc; - int16_t num_quant_strats = pState->spar_md_cfg.num_quant_strats; -#ifdef DEBUG_SPAR_FOA - int16_t count; - int16_t ii, jj; - float C_re_mat[IVAS_SPAR_MAX_CH - 1][IVAS_SPAR_MAX_CH - 1][IVAS_MAX_NUM_BANDS]; - float abs_diff; - frm++; -#endif - sba_order = min( hEncoderConfig->sba_order, IVAS_MAX_SBA_ORDER ); + num_quant_strats = hMdEnc->spar_md_cfg.num_quant_strats; num_ch = ivas_sba_get_nchan_metadata( sba_order ); - active_w = pState->spar_md_cfg.active_w; - nchan_transport = pState->spar_md_cfg.nchan_transport; + active_w = hMdEnc->spar_md_cfg.active_w; + nchan_transport = hMdEnc->spar_md_cfg.nchan_transport; + + bwidth = ivas_get_bw_idx_from_sample_rate( hEncoderConfig->input_Fs ); + bwidth = min( bwidth, hEncoderConfig->max_bwidth ); #ifdef LBR_SBA int16_t active_w_vlbr; active_w_vlbr = ( hEncoderConfig->ivas_total_brate < IVAS_24k4 ) ? 1 : 0; #endif - if ( hEncoderConfig->ivas_total_brate == BRATE_SPAR_Q_STRAT && sba_order == 1 ) + num_bands = ivas_get_num_bands_from_bw_idx( SPAR_CONFIG_BW ); + if ( hMdEnc->spar_hoa_md_flag == 0 ) + { + num_bands = min( num_bands, SPAR_DIRAC_SPLIT_START_BAND ); + } + num_bands_full = num_bands; + num_bands_bw = ivas_get_num_bands_from_bw_idx( bwidth ); + + if ( dtx_vad == 0 ) + { + for ( i = 0; i < nchan_inp; i++ ) + { + for ( j = 0; j < nchan_inp; j++ ) + { + cov_real[i][j] = cov_dtx_real[i][j]; + } + } + } + + for ( i = 0; i < nchan_inp; i++ ) + { + for ( j = 0; j < nchan_inp; j++ ) + { + for ( k = num_bands_bw; k < IVAS_MAX_NUM_BANDS; k++ ) + { + cov_real[i][j][k] = 0; + } + } + } + + if ( hEncoderConfig->ivas_total_brate == BRATE_SPAR_Q_STRAT && sba_order == SBA_FOA_ORDER ) { /* make sure that qsi is always 0 (temporary bits are '00') */ num_quant_strats = 1; @@ -634,11 +634,6 @@ ivas_error ivas_spar_foa_md_enc_process( next_ind_start = hMetaData->next_ind; last_ind_start = hMetaData->last_ind; - if ( hEncoderConfig->Opt_DTX_ON == 0 ) - { - dtx_vad = 1; - } - dmx_switch = 0; if ( dtx_vad == 0 ) @@ -646,7 +641,7 @@ ivas_error ivas_spar_foa_md_enc_process( nB = SPAR_DTX_BANDS; bands_bw = num_bands / nB; - ivas_band_mixer( pIn_buf->cov_real, num_ch, &num_bands, bands_bw ); + ivas_band_mixer( cov_real, num_ch, &num_bands, bands_bw ); } #ifdef LBR_SBA else if ( hEncoderConfig->ivas_total_brate < IVAS_24k4 ) @@ -654,7 +649,7 @@ ivas_error ivas_spar_foa_md_enc_process( bands_bw = 2; nB = num_bands / bands_bw; - ivas_band_mixer( pIn_buf->cov_real, num_ch, &num_bands, bands_bw ); + ivas_band_mixer( cov_real, num_ch, &num_bands, bands_bw ); } #endif else @@ -663,12 +658,23 @@ ivas_error ivas_spar_foa_md_enc_process( bands_bw = 1; } - ivas_compute_spar_params( pIn_buf->cov_real, dm_fv_re, 0, pState->mixer_mat, 0, nB, dtx_vad, num_ch, + if ( hMdEnc->spar_hoa_md_flag ) + { + for ( b = SPAR_DIRAC_SPLIT_START_BAND; b < num_bands; b++ ) + { + for ( i = 0; i < FOA_CHANNELS - 1; i++ ) + { + pred_coeffs_re_local[i][b] = hMdEnc->spar_md.band_coeffs[b].pred_re[i]; + } + } + } + + ivas_compute_spar_params( cov_real, dm_fv_re, 0, hMdEnc->mixer_mat, 0, nB, dtx_vad, num_ch, bands_bw, active_w, #ifdef LBR_SBA active_w_vlbr, #endif - &pState->spar_md_cfg, &pState->spar_md, Wscale, 0 ); + &hMdEnc->spar_md_cfg, &hMdEnc->spar_md, Wscale, 0 ); for ( i = 0; i < num_ch; i++ ) { @@ -676,16 +682,16 @@ ivas_error ivas_spar_foa_md_enc_process( { for ( b = 0; b < num_bands; b++ ) { - hMdEnc->mixer_mat_local[i][j][b] = pState->mixer_mat[i][j][b]; + hMdEnc->mixer_mat_local[i][j][b] = hMdEnc->mixer_mat[i][j][b]; } } } -#ifdef DEBUG_LBR_SBA - float dirac_md_kbps = (float) ( hMetaData->nb_bits_tot ) * 50 / 1000; -#endif planarCP = 0; code_strat = 0; +#ifdef DEBUG_SBA_MD_DUMP + ndec = -1; +#endif #ifdef DEBUG_SPAR_MD_TARGET_TUNING for ( qsi = 0; qsi < 1; qsi++ ) #else @@ -695,7 +701,7 @@ ivas_error ivas_spar_foa_md_enc_process( #ifdef SPAR_HOA_DBG fprintf( stdout, "qsi = %d\n", qsi ); #endif - if ( qsi == 2 && ivas_spar_br_table_consts[pState->table_idx].usePlanarCoeff ) + if ( qsi == 2 && ivas_spar_br_table_consts[hMdEnc->table_idx].usePlanarCoeff ) { planarCP = 1; #ifdef SPAR_HOA_DBG @@ -711,112 +717,18 @@ ivas_error ivas_spar_foa_md_enc_process( { for ( b = 0; b < num_bands; b++ ) { - ndm = pState->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; + ndm = hMdEnc->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; if ( ndm != num_ch ) { - ivas_calc_c_p_coeffs( &pState->spar_md, pIn_buf->cov_real, 0, hMdEnc->mixer_mat_local, num_ch, ndm, b, dtx_vad, 1, planarCP ); + ivas_calc_c_p_coeffs( &hMdEnc->spar_md, cov_real, 0, hMdEnc->mixer_mat_local, num_ch, ndm, b, dtx_vad, 1, planarCP ); } } } -#ifdef DEBUG_SPAR_FOA - count = 0; -#endif for ( b = 0; b < num_bands; b++ ) { - ndm = pState->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; - ndec = pState->spar_md_cfg.num_decorr_per_band[b * bands_bw]; -#ifdef DEBUG_SPAR_FOA - /* Plug Matlab values */ - - /* pred values */ - if ( fMd_data != NULL ) - { - /*printf("MD file found\n");*/ - float pred_mat; - for ( ii = 0; ii < num_ch - 1; ii++ ) - { - fscanf( fMd_data, "%f\n", &pred_mat ); - count++; - if ( qsi == 0 ) - { - if ( ( pState->spar_md.band_coeffs[b].pred_re[ii] > pState->spar_md_cfg.quant_strat[0].PR.max || pState->spar_md.band_coeffs[b].pred_re[ii] < pState->spar_md_cfg.quant_strat[0].PR.min ) && ( pred_mat > pState->spar_md_cfg.quant_strat[0].PR.max || pred_mat < pState->spar_md_cfg.quant_strat[0].PR.min ) ) - { - pState->spar_md.band_coeffs[b].pred_re[ii] = pred_mat; - } - else - { - abs_diff = fabsf( pState->spar_md.band_coeffs[b].pred_re[ii] - pred_mat ); - if ( abs_diff > max_diff ) - { - max_diff = abs_diff; - dbg_frm_num = frm; - dbg_band = b; - dbg_type = 0; - } - if ( abs_diff > MD_TOL_MAX ) - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "ERROR: pred coefffs Matlab MD & C MD values mismatch\n\n" ); - } - else - { - pState->spar_md.band_coeffs[b].pred_re[ii] = pred_mat; - } - } - } - } - } - - /* P values */ - if ( fMd_data != NULL ) - { - float P_re_mat; - for ( jj = 0; jj < num_ch - ndm; jj++ ) - { - fscanf( fMd_data, "%f\n", &P_re_mat ); - count++; - if ( ( pState->spar_md.band_coeffs[b].P_re[jj] > pState->spar_md_cfg.quant_strat[0].P_r.max || pState->spar_md.band_coeffs[b].P_re[jj] < pState->spar_md_cfg.quant_strat[0].P_r.min ) && ( P_re_mat > pState->spar_md_cfg.quant_strat[0].P_r.max || P_re_mat < pState->spar_md_cfg.quant_strat[0].P_r.min ) ) - { - pState->spar_md.band_coeffs[b].P_re[jj] = P_re_mat; - } - else - { - abs_diff = fabsf( pState->spar_md.band_coeffs[b].P_re[jj] - P_re_mat ); - if ( abs_diff > max_diff ) - { - max_diff = abs_diff; - dbg_frm_num = frm; - dbg_band = b; - dbg_type = 1; - } - if ( abs_diff > MD_TOL_MAX ) - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "ERROR: P mat Matlab MD & C MD values mismatch %f\n\n", abs_diff ); - } - else - { - pState->spar_md.band_coeffs[b].P_re[jj] = P_re_mat; - } - } - } - } - - /* C values */ - if ( fMd_data != NULL && ndm != 1 && ndm != num_ch ) - { - for ( jj = 0; jj < ndm - 1; jj++ ) - { - for ( ii = 0; ii < num_ch - ndm; ii++ ) - { - fscanf( fMd_data, "%f\n", &C_re_mat[ii][jj][b] ); - count++; -#ifdef SPAR_HOA_DBG - /*fprintf(stdout, "count: %d\n", count);*/ -#endif - } - } - } -#endif + ndm = hMdEnc->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; + ndec = hMdEnc->spar_md_cfg.num_decorr_per_band[b * bands_bw]; if ( dtx_vad == 1 ) { @@ -827,11 +739,11 @@ ivas_error ivas_spar_foa_md_enc_process( for (i = 0; i < ndec; i++) { - for (j = 0; j < ndec; j++) - { - fprintf(stderr, "%f, ", hMdEnc->spar_md.band_coeffs[b].P_re[i][j]);//, hMdEnc->spar_md.band_coeffs[b].P_im[i][j]); - } - fprintf(stderr, "\n"); + for (j = 0; j < ndec; j++) + { + fprintf(stderr, "%f, ", hMdEnc->spar_md.band_coeffs[b].P_re[i][j]);//, hMdEnc->spar_md.band_coeffs[b].P_im[i][j]); + } + fprintf(stderr, "\n"); } fprintf(stderr, "\n\n"); */ #endif @@ -850,11 +762,11 @@ ivas_error ivas_spar_foa_md_enc_process( /*fprintf(stderr, "\n\n Planar P coefficients: band %d\n", b); for (i = 0; i < ndec; i++) { - for (j = 0; j < ndec; j++) - { - fprintf(stderr, "%f, ", hMdEnc->spar_md.band_coeffs[b].P_re[i][j]); //, hMdEnc->spar_md.band_coeffs[b].C_im[i][j]); - } - fprintf(stderr, "\n"); + for (j = 0; j < ndec; j++) + { + fprintf(stderr, "%f, ", hMdEnc->spar_md.band_coeffs[b].P_re[i][j]); //, hMdEnc->spar_md.band_coeffs[b].C_im[i][j]); + } + fprintf(stderr, "\n"); } fprintf(stderr, "\n\n"); */ #endif @@ -865,7 +777,7 @@ ivas_error ivas_spar_foa_md_enc_process( pState->spar_md.band_coeffs[b].P_re[2] = 0.0f; } #endif - ivas_quant_p_per_band( &pState->spar_md.band_coeffs[b], &pState->spar_md.band_coeffs_idx[b], &pState->spar_md_cfg.quant_strat[qsi], num_ch ); + ivas_quant_p_per_band( &hMdEnc->spar_md.band_coeffs[b], &hMdEnc->spar_md.band_coeffs_idx[b], &hMdEnc->spar_md_cfg.quant_strat[qsi], num_ch ); } #ifdef LBR_SBA_PLANAR if ( active_w_vlbr ) /* SPAR PLANAR */ @@ -873,9 +785,8 @@ ivas_error ivas_spar_foa_md_enc_process( pState->spar_md.band_coeffs[b].pred_re[1] = 0.0f; } #endif - ivas_quant_pred_coeffs_per_band( &pState->spar_md.band_coeffs[b], &pState->spar_md.band_coeffs_idx[b], &pState->spar_md_cfg.quant_strat[qsi], num_ch ); + ivas_quant_pred_coeffs_per_band( &hMdEnc->spar_md.band_coeffs[b], &hMdEnc->spar_md.band_coeffs_idx[b], &hMdEnc->spar_md_cfg.quant_strat[qsi], num_ch ); #ifdef LBR_SBA - /* FIX here for PR coeffs ? */ if ( active_w_vlbr ) { for ( i = 0; i < 3; i++ ) @@ -900,27 +811,23 @@ ivas_error ivas_spar_foa_md_enc_process( i2 = 1; break; } - if ( ( pState->spar_md.band_coeffs_idx[b].pred_index_re[i] == 0 ) && ( pState->spar_md.band_coeffs_idx[b].decd_index_re[i2] == 0 ) - && ( pState->spar_md.band_coeffs[b].pred_re[i] != 0.0f ) && ( pIn_buf->cov_real[i + 1][i + 1][b] != 0.0f ) ) + if ( ( hMdEnc->spar_md.band_coeffs_idx[b].pred_index_re[i] == 0 ) && ( hMdEnc->spar_md.band_coeffs_idx[b].decd_index_re[i2] == 0 ) + && ( hMdEnc->spar_md.band_coeffs[b].pred_re[i] != 0.0f ) && ( cov_real[i + 1][i + 1][b] != 0.0f ) ) { -#ifdef LBR_SBA_DEBUG - fprintf( stdout, "\nbumped: PRED band %d, channel ind %d\n", b, i ); -#endif /* bump up the Pred coeff */ float PR_uq, PR_step; ivas_quant_strat_t qs; - qs = pState->spar_md_cfg.quant_strat[qsi]; - PR_uq = pState->spar_md.band_coeffs[b].pred_re[i]; + qs = hMdEnc->spar_md_cfg.quant_strat[qsi]; + PR_uq = hMdEnc->spar_md.band_coeffs[b].pred_re[i]; PR_step = ( qs.PR.max - qs.PR.min ) / ( qs.PR.q_levels[0] - 1 ); - int16_t PR_sign; PR_sign = ( PR_uq > 0 ) - ( PR_uq < 0 ); - pState->spar_md.band_coeffs_idx[b].pred_index_re[i] = PR_sign; + hMdEnc->spar_md.band_coeffs_idx[b].pred_index_re[i] = PR_sign; /* deindex the modified coefficient */ - pState->spar_md.band_coeffs[b].pred_quant_re[i] = PR_sign * PR_step; + hMdEnc->spar_md.band_coeffs[b].pred_quant_re[i] = PR_sign * PR_step; } } } @@ -928,49 +835,28 @@ ivas_error ivas_spar_foa_md_enc_process( } else { - float **ppPred_re, **ppPred_quant, *pPred_re, *pPred_quant; - int16_t **ppPred_idx, *pPred_re_idx; - if ( ndm != num_ch ) { - float *P_re[IVAS_SPAR_MAX_CH - 1], *P_re_quant[IVAS_SPAR_MAX_CH - 1]; - float **ppP_re = (float **) &P_re[0]; - float **ppP_re_quant = (float **) &P_re_quant[0]; - int16_t *ppP_idx = &pState->spar_md.band_coeffs_idx[b].decd_index_re[0]; - - for ( i = 0; i < ndec; i++ ) - { - ppP_re[i] = pState->spar_md.band_coeffs[b].P_re; - ppP_re_quant[i] = pState->spar_md.band_coeffs[b].P_quant_re; - } #ifdef LBR_SBA_PLANAR if ( active_w_vlbr ) /* SPAR PLANAR */ { - pState->spar_md.band_coeffs[b].P_re[2] = 0.0f; + hMdEnc->spar_md.band_coeffs[b].P_re[2] = 0.0f; } #endif - ivas_quant_p_per_band_dtx( ppP_re, ndec, ndm, ppP_idx, ppP_re_quant, num_ch ); + ivas_quant_p_per_band_dtx( hMdEnc->spar_md.band_coeffs[b].P_re, ndec, ndm, &hMdEnc->spar_md.band_coeffs_idx[b].decd_index_re[0], hMdEnc->spar_md.band_coeffs[b].P_quant_re, num_ch ); } - ppPred_idx = (int16_t **) &pPred_re_idx; - ppPred_re = (float **) &pPred_re; - ppPred_quant = (float **) &pPred_quant; - - ppPred_re[0] = pState->spar_md.band_coeffs[b].pred_re; - ppPred_idx[0] = pState->spar_md.band_coeffs_idx[b].pred_index_re; - ppPred_quant[0] = pState->spar_md.band_coeffs[b].pred_quant_re; - for ( i = 0; i < num_ch - 1; i++ ) { - pState->spar_md.band_coeffs[b].pred_quant_re[i] = 0; + hMdEnc->spar_md.band_coeffs[b].pred_quant_re[i] = 0; } #ifdef LBR_SBA_PLANAR if ( active_w_vlbr ) /* SPAR PLANAR */ { - pState->spar_md.band_coeffs[b].pred_re[1] = 0.0f; + hMdEnc->spar_md.band_coeffs[b].pred_re[1] = 0.0f; } #endif - ivas_spar_foa_quant_pred_coeffs_dtx( &pState->spar_md, ppPred_re, ndm, ppPred_idx, num_ch - 1, ppPred_quant ); + ivas_spar_quant_pred_coeffs_dtx( &hMdEnc->spar_md, hMdEnc->spar_md.band_coeffs[b].pred_re, ndm, hMdEnc->spar_md.band_coeffs_idx[b].pred_index_re, num_ch - 1, hMdEnc->spar_md.band_coeffs[b].pred_quant_re ); } } @@ -978,35 +864,49 @@ ivas_error ivas_spar_foa_md_enc_process( { for ( b = 0; b < num_bands; b++ ) { - pred_coeffs_re[i][b] = Wscale[b] * pState->spar_md.band_coeffs[b].pred_quant_re[i]; + pred_coeffs_re[i][b] = Wscale[b] * hMdEnc->spar_md.band_coeffs[b].pred_quant_re[i]; + } + } + + if ( hMdEnc->spar_hoa_md_flag ) + { + for ( b = SPAR_DIRAC_SPLIT_START_BAND; b < num_bands; b++ ) + { + for ( i = 0; i < FOA_CHANNELS - 1; i++ ) + { + /* Use the prediction coeffs computed based on DirAC MD to generate mixer matrix */ + pred_coeffs_re[i][b] = pred_coeffs_re_local[i][b]; + hMdEnc->spar_md.band_coeffs[b].pred_quant_re[i] = 0; + hMdEnc->spar_md.band_coeffs_idx[b].pred_index_re[i] = 0; + } } } - ivas_create_fullr_dmx_mat( pred_coeffs_re, dm_fv_re, pState->mixer_mat, num_ch, 0, num_bands, active_w, &pState->spar_md_cfg ); + ivas_create_fullr_dmx_mat( pred_coeffs_re, dm_fv_re, hMdEnc->mixer_mat, num_ch, 0, num_bands, active_w, &hMdEnc->spar_md_cfg ); for ( b = 0; b < num_bands; b++ ) { - ndm = pState->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; - ndec = pState->spar_md_cfg.num_decorr_per_band[b * bands_bw]; + ndm = hMdEnc->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; + ndec = hMdEnc->spar_md_cfg.num_decorr_per_band[b * bands_bw]; for ( i = 0; i < num_ch; i++ ) { - pState->mixer_mat[0][i][b] *= Wscale[b]; + hMdEnc->mixer_mat[0][i][b] *= Wscale[b]; } if ( ( ndm != num_ch ) && ( ndm != 1 ) ) { - ivas_calc_c_p_coeffs( &pState->spar_md, pIn_buf->cov_real, 0, pState->mixer_mat, num_ch, ndm, b, dtx_vad, 0, planarCP ); + ivas_calc_c_p_coeffs( &hMdEnc->spar_md, cov_real, 0, hMdEnc->mixer_mat, num_ch, ndm, b, dtx_vad, 0, planarCP ); #ifdef SPAR_HOA_DBG /*fprintf(stderr, "\n\n C coefficients: band %d\n", b); for (i = 0; i < num_ch - ndm; i++) { - for (j = 0; j < ndm - 1; j++) - { - fprintf(stderr, "%f, ", pState->spar_md.band_coeffs[b].C_re[i][j]); - } - fprintf(stderr, "\n"); + for (j = 0; j < ndm - 1; j++) + { + fprintf(stderr, "%f, ", hMdEnc->spar_md.band_coeffs[b].C_re[i][j]); + } + fprintf(stderr, "\n"); } fprintf(stderr, "\n\n"); */ #endif @@ -1018,7 +918,7 @@ ivas_error ivas_spar_foa_md_enc_process( { for ( j = 0; j < ndm - 1; j++ ) { - pState->spar_md.band_coeffs[b].C_re[i][j] = 0.0f; + hMdEnc->spar_md.band_coeffs[b].C_re[i][j] = 0.0f; } } } @@ -1027,58 +927,24 @@ ivas_error ivas_spar_foa_md_enc_process( for (i = 0; i < num_ch - ndm; i++) { - for (j = 0; j < ndm - 1; j++) - { - fprintf(stderr, "%f, ", pState->spar_md.band_coeffs[b].C_re[i][j]); // , pState->spar_md.band_coeffs[band_idx].C_im[i][j]); - } - fprintf(stderr, "\n"); + for (j = 0; j < ndm - 1; j++) + { + fprintf(stderr, "%f, ", hMdEnc->spar_md.band_coeffs[b].C_re[i][j]); // , hMdEnc->spar_md.band_coeffs[band_idx].C_im[i][j]); + } + fprintf(stderr, "\n"); } fprintf(stderr, "\n\n"); */ #endif } -#ifdef DEBUG_SPAR_FOA - if ( fMd_data != NULL ) - { - for ( jj = 0; jj < nchan_transport - 1; jj++ ) - { - for ( ii = 0; ii < num_ch - nchan_transport; ii++ ) - { - if ( ( pState->spar_md.band_coeffs[b].C_re[ii][jj] > pState->spar_md_cfg.quant_strat[0].C.max || pState->spar_md.band_coeffs[b].C_re[ii][jj] < pState->spar_md_cfg.quant_strat[0].C.min ) && ( C_re_mat[ii][jj][b] > pState->spar_md_cfg.quant_strat[0].C.max || C_re_mat[ii][jj][b] < pState->spar_md_cfg.quant_strat[0].C.min ) ) - { - pState->spar_md.band_coeffs[b].C_re[ii][jj] = C_re_mat[ii][jj][b]; - } - else - { - abs_diff = (float) fabs( pState->spar_md.band_coeffs[b].C_re[ii][jj] - C_re_mat[ii][jj][b] ); - if ( abs_diff > max_diff ) - { - max_diff = abs_diff; - dbg_frm_num = frm; - dbg_band = b; - dbg_type = 2; - } - if ( abs_diff > MD_TOL_MAX ) - { - return ( IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "\n Matlab MD & C MD values mismatch" ) ); - } - else - { - pState->spar_md.band_coeffs[b].C_re[ii][jj] = C_re_mat[ii][jj][b]; - } - } - } - } - } -#endif - ivas_quant_c_per_band( &pState->spar_md.band_coeffs[b], &pState->spar_md.band_coeffs_idx[b], - &pState->spar_md_cfg.quant_strat[qsi], ndec, ndm ); + ivas_quant_c_per_band( &hMdEnc->spar_md.band_coeffs[b], &hMdEnc->spar_md.band_coeffs_idx[b], + &hMdEnc->spar_md_cfg.quant_strat[qsi], ndec, ndm ); #ifdef SPAR_HOA_DBG /*fprintf(stderr, "\n\n quantised C indexes: band %d\n", b); for (i = 0; i < ndec * (ndm-1); i++) { - fprintf(stderr, "%d, ", pState->spar_md.band_coeffs_idx[b].drct_index_re[i]); + fprintf(stderr, "%d, ", hMdEnc->spar_md.band_coeffs_idx[b].drct_index_re[i]); } fprintf(stderr, "\n\n");*/ #endif @@ -1086,26 +952,21 @@ ivas_error ivas_spar_foa_md_enc_process( } /* band limit downmix matrix */ - ivas_band_limit_dmx_matrix( pState, num_ch, num_bands, bands_bw ); + ivas_band_limit_dmx_matrix( hMdEnc, num_ch, num_bands, bands_bw ); /* band mixing */ if ( bands_bw > 1 ) { - ivas_band_mixing( pState, num_ch, num_bands, nchan_transport, pIn_buf->num_bands ); - } - - if ( pState->spar_md_cfg.gen_bs == 0 ) - { - break; + ivas_band_mixing( hMdEnc, num_ch, num_bands, nchan_transport, num_bands_full ); } if ( dtx_vad == 0 ) { - ivas_write_parameter_bitstream_dtx( &pState->spar_md, hMetaData, pState->spar_md_cfg.num_dmx_chans_per_band, pState->spar_md_cfg.num_decorr_per_band, num_bands ); + ivas_write_parameter_bitstream_dtx( &hMdEnc->spar_md, hMetaData, hMdEnc->spar_md_cfg.num_dmx_chans_per_band, hMdEnc->spar_md_cfg.num_decorr_per_band, num_bands ); break; } - ivas_select_next_strat( pState->spar_md_cfg.prior_strat, cs, dmx_switch, dtx_vad ); + ivas_select_next_strat( hMdEnc->spar_md_cfg.prior_strat, cs, dmx_switch, dtx_vad ); for ( i = 0; i < MAX_CODING_STRATS; i++ ) { @@ -1114,13 +975,14 @@ ivas_error ivas_spar_foa_md_enc_process( { reset_indices_enc( &hMetaData_tmp, MAX_BITS_METADATA ); - ivas_write_parameter_bitstream( pState, num_bands, bands_bw, &hMetaData_tmp, hEncoderConfig->ivas_total_brate, dtx_silence_mode, strat, qsi, planarCP ); + ivas_write_spar_md_bitstream( hMdEnc, num_bands, bands_bw, &hMetaData_tmp, hEncoderConfig->ivas_total_brate, strat, qsi, planarCP ); + if ( hMetaData->nb_bits_tot == bit_pos_start || hMetaData_tmp.nb_bits_tot < ( hMetaData->nb_bits_tot - bit_pos_start ) ) { write_metadata_buffer( &hMetaData_tmp, hMetaData, bit_pos_start, next_ind_start, last_ind_start ); code_strat = strat; } - if ( hMetaData->nb_bits_tot - bit_pos_start + ( ( ( hEncoderConfig->ivas_total_brate == IVAS_256k ) && ( sba_order == 1 ) ) ? 1 : 0 ) <= pState->spar_md_cfg.tgt_bits_per_blk ) + if ( hMetaData->nb_bits_tot - bit_pos_start + ( ( ( hEncoderConfig->ivas_total_brate == IVAS_256k ) && ( sba_order == SBA_FOA_ORDER ) ) ? 1 : 0 ) <= hMdEnc->spar_md_cfg.tgt_bits_per_blk ) { packed_ok = 1; break; @@ -1133,7 +995,7 @@ ivas_error ivas_spar_foa_md_enc_process( break; } - if ( hMetaData->nb_bits_tot - bit_pos_start + ( ( ( hEncoderConfig->ivas_total_brate == IVAS_256k ) && ( sba_order == 1 ) ) ? 1 : 0 ) <= pState->spar_md_cfg.max_bits_per_blk ) + if ( hMetaData->nb_bits_tot - bit_pos_start + ( ( ( hEncoderConfig->ivas_total_brate == IVAS_256k ) && ( sba_order == SBA_FOA_ORDER ) ) ? 1 : 0 ) <= hMdEnc->spar_md_cfg.max_bits_per_blk ) { break; } @@ -1164,90 +1026,51 @@ ivas_error ivas_spar_foa_md_enc_process( } } #endif -#ifdef DEBUG_LBR_SBA - char f_name[100]; - int16_t nbands = 1; - int16_t num_subframes = 1; - int16_t num_elements = 6; - int16_t num_block_group = 1; - int16_t byte_size = sizeof( float ); - - float sba_md_kbps = (float) hMetaData->nb_bits_tot * 50 / 1000; - float spar_md_kbps = sba_md_kbps - dirac_md_kbps; - float corebr_kbps = (float) hEncoderConfig->ivas_total_brate / 1000 - sba_md_kbps; - - sprintf( f_name, "SBA_MD_bitrate.bin" ); - ( frame == 0 ) ? dbgwrite( &nbands, sizeof( nbands ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &num_block_group, sizeof( num_block_group ), 1, 1, f_name ) : false; - ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; - - for ( b = 0; b < nbands; b++ ) - { - for ( int16_t sf = 0; sf < num_subframes; sf++ ) - { - for ( int16_t bl = 0; bl < num_block_group; bl++ ) - { - float fqsi = (float) qsi; - float fcode = (float) code_strat; - - dbgwrite( &dirac_md_kbps, byte_size, 1, 1, f_name ); - dbgwrite( &spar_md_kbps, byte_size, 1, 1, f_name ); - dbgwrite( &sba_md_kbps, byte_size, 1, 1, f_name ); - dbgwrite( &fqsi, byte_size, 1, 1, f_name ); - dbgwrite( &fcode, byte_size, 1, 1, f_name ); - dbgwrite( &corebr_kbps, byte_size, 1, 1, f_name ); - // fprintf(stdout, "%f\t%f\t%f\t%d\t%d\n", dirac_md_kbps, spar_md_kbps, sba_md_kbps, qsi, code_strat ); - } - } - } -#endif #ifdef SPAR_HOA_DBG /*if ( strat >= 4 ) { - for ( b = 0; b < nB; b++ ) - { - b = 0; - fprintf( stdout, "\n\nMETADATA PR: band %d, qsi %d\n\n", b, qsi ); - for ( i = 0; i < num_ch - 1; i++ ) + for ( b = 0; b < nB; b++ ) { - fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, //pState->spar_md.band_coeffs[b].pred_re[i], - pState->spar_md.band_coeffs[b].pred_quant_re[i], - pState->spar_md_prior.band_coeffs_idx[b].pred_index_re[i], - pState->spar_md.band_coeffs_idx[b].pred_index_re[i] ); - } - fprintf( stdout, "\n\n METADATA C: band %d\n\n", b ); - int16_t k = 0; - for ( i = 0; i < ndec; i++ ) - { - for ( j = 0; j < ( ndm - 1 ); j++ ) - { - fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, // pState->spar_md.band_coeffs[b].C_re[i][j], - pState->spar_md.band_coeffs[b].C_quant_re[i][j], - pState->spar_md_prior.band_coeffs_idx[b].drct_index_re[k], - pState->spar_md.band_coeffs_idx[b].drct_index_re[k] ); - k++; - } - } - fprintf( stdout, "\n\n METADATA Pd: band %d\n\n", b ); - for ( i = 0; i < num_ch - ndm; i++ ) - { - fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, //pState->spar_md.band_coeffs[b].P_re[i][i], - pState->spar_md.band_coeffs[b].P_quant_re[i][i], - pState->spar_md_prior.band_coeffs_idx[b].decd_index_re[i], - pState->spar_md.band_coeffs_idx[b].decd_index_re[i] ); + b = 0; + fprintf( stdout, "\n\nMETADATA PR: band %d, qsi %d\n\n", b, qsi ); + for ( i = 0; i < num_ch - 1; i++ ) + { + fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, //hMdEnc->spar_md.band_coeffs[b].pred_re[i], + hMdEnc->spar_md.band_coeffs[b].pred_quant_re[i], + hMdEnc->spar_md_prior.band_coeffs_idx[b].pred_index_re[i], + hMdEnc->spar_md.band_coeffs_idx[b].pred_index_re[i] ); + } + fprintf( stdout, "\n\n METADATA C: band %d\n\n", b ); + int16_t k = 0; + for ( i = 0; i < ndec; i++ ) + { + for ( j = 0; j < ( ndm - 1 ); j++ ) + { + fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, // hMdEnc->spar_md.band_coeffs[b].C_re[i][j], + hMdEnc->spar_md.band_coeffs[b].C_quant_re[i][j], + hMdEnc->spar_md_prior.band_coeffs_idx[b].drct_index_re[k], + hMdEnc->spar_md.band_coeffs_idx[b].drct_index_re[k] ); + k++; + } + } + fprintf( stdout, "\n\n METADATA Pd: band %d\n\n", b ); + for ( i = 0; i < num_ch - ndm; i++ ) + { + fprintf( stdout, "i: %d -- %f\t %d\t %d\n", i, //hMdEnc->spar_md.band_coeffs[b].P_re[i][i], + hMdEnc->spar_md.band_coeffs[b].P_quant_re[i][i], + hMdEnc->spar_md_prior.band_coeffs_idx[b].decd_index_re[i], + hMdEnc->spar_md.band_coeffs_idx[b].decd_index_re[i] ); + } + fprintf( stdout, "\n\n" ); } - fprintf( stdout, "\n\n" ); - } }*/ b = 0; - ndm = pState->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; + ndm = hMdEnc->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; fprintf( stdout, "\n\n Metadata PR (15x1), C(15x15), P(15x15): band %d\n", b ); for ( i = 0; i < num_ch - 1; i++ ) { - fprintf( stdout, "i: %d -- %.2f\t|\t", i, pState->spar_md.band_coeffs[b].pred_quant_re[i] ); + fprintf( stdout, "i: %d -- %.2f\t|\t", i, hMdEnc->spar_md.band_coeffs[b].pred_quant_re[i] ); if ( i < num_ch - ndm ) { if ( keep_planar[i] == 1 ) @@ -1260,37 +1083,132 @@ ivas_error ivas_spar_foa_md_enc_process( } for ( j = 0; j < ndm - 1; j++ ) { - fprintf( stdout, "%.2f\t", pState->spar_md.band_coeffs[b].C_quant_re[i][j] ); + fprintf( stdout, "%.2f\t", hMdEnc->spar_md.band_coeffs[b].C_quant_re[i][j] ); } fprintf( stdout, "|\t" ); for ( j = 0; j < num_ch - ndm; j++ ) { - fprintf( stdout, "%.2f\t", pState->spar_md.band_coeffs[b].P_quant_re[i][j] ); + fprintf( stdout, "%.2f\t", hMdEnc->spar_md.band_coeffs[b].P_quant_re[j] ); } } fprintf( stdout, "\n" ); } fprintf( stdout, "\n" ); #endif +#ifdef DEBUG_SBA_MD_DUMP + { + char f_name[100]; + int16_t n_bands = 1, num_subframes = 1, num_block_groups = 1, num_elements = 1, byte_size = sizeof( int16_t ); + sprintf( f_name, "spar_qsi.bin" ); + ( frame == 0 ) ? dbgwrite( &n_bands, sizeof( nB ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + dbgwrite( &qsi, sizeof( int16_t ), 1, 1, f_name ); + sprintf( f_name, "spar_strat.bin" ); + ( frame == 0 ) ? dbgwrite( &n_bands, sizeof( nB ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + dbgwrite( &strat, sizeof( int16_t ), 1, 1, f_name ); + byte_size = sizeof( float ); + for ( b = 0; b < nB; b++ ) + { + ndm = hMdEnc->spar_md_cfg.num_dmx_chans_per_band[b * bands_bw]; + + sprintf( f_name, "spar_band_pred_coeffs.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; + num_elements = num_ch - 1; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( i = 0; i < num_ch - 1; i++ ) + { + dbgwrite( &hMdEnc->spar_md.band_coeffs[b].pred_re[i], sizeof( float ), 1, 1, f_name ); + } + sprintf( f_name, "spar_band_C_coeffs.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; + num_elements = ndec * ( ndm - 1 ); + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( i = 0; i < ndec; i++ ) + { + for ( j = 0; j < ( ndm - 1 ); j++ ) + { + dbgwrite( &hMdEnc->spar_md.band_coeffs[b].C_re[i][j], sizeof( float ), 1, 1, f_name ); + } + } + sprintf( f_name, "spar_band_P_coeffs.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; + num_elements = num_ch - ndm; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( i = 0; i < num_ch - ndm; i++ ) + { + dbgwrite( &hMdEnc->spar_md.band_coeffs[b].P_re[i], sizeof( float ), 1, 1, f_name ); + } + sprintf( f_name, "spar_band_pred_coeffs_quant.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; + num_elements = num_ch - 1; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( i = 0; i < num_ch - 1; i++ ) + { + dbgwrite( &hMdEnc->spar_md.band_coeffs[b].pred_quant_re[i], sizeof( float ), 1, 1, f_name ); + } + sprintf( f_name, "spar_band_C_coeffs_quant.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; + num_elements = ndec * ( ndm - 1 ); + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( i = 0; i < ndec; i++ ) + { + for ( j = 0; j < ( ndm - 1 ); j++ ) + { + dbgwrite( &hMdEnc->spar_md.band_coeffs[b].C_quant_re[i][j], sizeof( float ), 1, 1, f_name ); + } + } + sprintf( f_name, "spar_band_P_coeffs_quant.bin" ); + ( b == 0 && frame == 0 ) ? dbgwrite( &nB, sizeof( nB ), 1, 1, f_name ) : false; + num_elements = num_ch - ndm; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_elements, sizeof( num_elements ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_subframes, sizeof( num_subframes ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &num_block_groups, sizeof( num_block_groups ), 1, 1, f_name ) : false; + ( b == 0 && frame == 0 ) ? dbgwrite( &byte_size, sizeof( byte_size ), 1, 1, f_name ) : false; + for ( i = 0; i < num_ch - ndm; i++ ) + { + dbgwrite( &hMdEnc->spar_md.band_coeffs[b].P_quant_re[i], sizeof( float ), 1, 1, f_name ); + } + } + } +#endif #ifdef DEBUG_SPAR_MD_TARGET_TUNING - int16_t md_bits = hMetaData->nb_bits_tot - bit_pos_start + ( ( ( hEncoderConfig->ivas_total_brate == IVAS_256k ) && ( sba_order == 1 ) ) ? 1 : 0 ); + int16_t md_bits = hMetaData->nb_bits_tot - bit_pos_start + ( ( ( hEncoderConfig->ivas_total_brate == IVAS_256k ) && ( sba_order == SBA_FOA_ORDER ) ) ? 1 : 0 ); FILE *fp = fopen( "spar_md_bitrate.txt", "a" ); fprintf( fp, "%d\t %d \t %d\n", md_bits, qsi, code_strat ); fclose( fp ); #endif - if ( pState->spar_md_cfg.gen_bs == 1 ) - { - ivas_store_prior_coeffs( pState, num_bands, + ivas_store_prior_coeffs( hMdEnc, num_bands, #ifndef LBR_SBA - bands_bw, + bands_bw, #endif - code_strat, dtx_vad, qsi ); - } + code_strat, dtx_vad, qsi ); - pState->spar_md.dtx_vad = dtx_vad; - pState->spar_md.num_bands = num_bands; + hMdEnc->spar_md.dtx_vad = dtx_vad; + hMdEnc->spar_md.num_bands = num_bands; return IVAS_ERR_OK; } @@ -1303,7 +1221,7 @@ ivas_error ivas_spar_foa_md_enc_process( *-----------------------------------------------------------------------------------------*/ static void ivas_band_mixer( - float *cov_re[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], + float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH], const int16_t num_ch, int16_t *num_bands, int16_t red_band_fact ) @@ -1324,18 +1242,18 @@ static void ivas_band_mixer( avg_cov = 0.0f; for ( b = 0; b < red_band_fact; b++ ) { - avg_cov += cov_re[i][j][red_band_fact * k + b]; + avg_cov += cov_real[i][j][red_band_fact * k + b]; } - cov_re[i][j][k] = avg_cov; + cov_real[i][j][k] = avg_cov; } avg_cov = 0.0f; for ( b = 0; b < red_band_fact + rem_band; b++ ) { - avg_cov += cov_re[i][j][red_band_fact * ( *num_bands - 1 ) + b]; + avg_cov += cov_real[i][j][red_band_fact * ( *num_bands - 1 ) + b]; } - cov_re[i][j][*num_bands - 1] = avg_cov; + cov_real[i][j][*num_bands - 1] = avg_cov; } } @@ -1344,18 +1262,17 @@ static void ivas_band_mixer( /*-----------------------------------------------------------------------------------------* - * Function ivas_write_parameter_bitstream() + * Function ivas_write_spar_md_bitstream() * * Write MD parameters into bitstream *-----------------------------------------------------------------------------------------*/ -static void ivas_write_parameter_bitstream( - ivas_spar_foa_md_enc_state_t *hMdEnc, +static void ivas_write_spar_md_bitstream( + ivas_spar_md_enc_state_t *hMdEnc, const int16_t nB, const int16_t bands_bw, BSTR_ENC_HANDLE hMetaData, const int32_t ivas_total_brate, - const int16_t dtx_silence_mode, const int16_t strat, const int16_t qsi, const int16_t planarCP ) @@ -1369,7 +1286,7 @@ static void ivas_write_parameter_bitstream( } /* write quant strat */ - if ( dtx_silence_mode == 0 && ivas_total_brate >= BRATE_SPAR_Q_STRAT ) + if ( ivas_total_brate >= BRATE_SPAR_Q_STRAT ) { push_next_indice( hMetaData, qsi >> 1, hMdEnc->spar_md_cfg.quant_strat_bits - 1 ); } @@ -1379,6 +1296,7 @@ static void ivas_write_parameter_bitstream( } no_ec = 0; + #ifdef LBR_SBA if ( ivas_total_brate < IVAS_24k4 ) { @@ -1405,59 +1323,61 @@ static void ivas_write_parameter_bitstream( } } else -#endif { - switch ( strat ) - { - case BASE: - push_next_indice( hMetaData, bands_bw - 1, SPAR_NUM_CODING_STRAT_BITS ); - for ( i = 0; i < nB; i++ ) - { - do_diff[i] = 0; - } - break; - case BASE_NOEC: - push_next_indice( hMetaData, bands_bw + 1, SPAR_NUM_CODING_STRAT_BITS ); - for ( i = 0; i < nB; i++ ) - { - do_diff[i] = 0; - } - no_ec = 1; - break; - case FOUR_A: - push_next_indice( hMetaData, 4, SPAR_NUM_CODING_STRAT_BITS ); - for ( i = 0; i < nB; i++ ) - { - do_diff[i] = ( ( ( i + 1 ) & 3 ) != 0 ); - } - ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); - break; - case FOUR_B: - push_next_indice( hMetaData, 5, SPAR_NUM_CODING_STRAT_BITS ); - for ( i = 0; i < nB; i++ ) - { - do_diff[i] = ( ( ( i + 1 ) & 3 ) != 1 ); - } - ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); - break; - case FOUR_C: - push_next_indice( hMetaData, 6, SPAR_NUM_CODING_STRAT_BITS ); - for ( i = 0; i < nB; i++ ) - { - do_diff[i] = ( ( ( i + 1 ) & 3 ) != 2 ); - } - ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); - break; - case FOUR_D: - push_next_indice( hMetaData, 7, SPAR_NUM_CODING_STRAT_BITS ); - for ( i = 0; i < nB; i++ ) - { - do_diff[i] = ( ( ( i + 1 ) & 3 ) != 3 ); - } - ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); - break; - } - } +#endif + switch ( strat ) + { + case BASE: + push_next_indice( hMetaData, bands_bw - 1, SPAR_NUM_CODING_STRAT_BITS ); + for ( i = 0; i < nB; i++ ) + { + do_diff[i] = 0; + } + break; + case BASE_NOEC: + push_next_indice( hMetaData, bands_bw + 1, SPAR_NUM_CODING_STRAT_BITS ); + for ( i = 0; i < nB; i++ ) + { + do_diff[i] = 0; + } + no_ec = 1; + break; + case FOUR_A: + push_next_indice( hMetaData, 4, SPAR_NUM_CODING_STRAT_BITS ); + for ( i = 0; i < nB; i++ ) + { + do_diff[i] = ( ( ( i + 1 ) & 3 ) != 0 ); + } + ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); + break; + case FOUR_B: + push_next_indice( hMetaData, 5, SPAR_NUM_CODING_STRAT_BITS ); + for ( i = 0; i < nB; i++ ) + { + do_diff[i] = ( ( ( i + 1 ) & 3 ) != 1 ); + } + ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); + break; + case FOUR_C: + push_next_indice( hMetaData, 6, SPAR_NUM_CODING_STRAT_BITS ); + for ( i = 0; i < nB; i++ ) + { + do_diff[i] = ( ( ( i + 1 ) & 3 ) != 2 ); + } + ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); + break; + case FOUR_D: + push_next_indice( hMetaData, 7, SPAR_NUM_CODING_STRAT_BITS ); + for ( i = 0; i < nB; i++ ) + { + do_diff[i] = ( ( ( i + 1 ) & 3 ) != 3 ); + } + ivas_map_prior_coeffs_quant( &hMdEnc->spar_md_prior, &hMdEnc->spar_md_cfg, qsi, nB ); + break; + } +#ifdef LBR_SBA + } +#endif #ifdef SPAR_HOA_DBG if ( strat < 2 ) @@ -1472,7 +1392,7 @@ static void ivas_write_parameter_bitstream( , bands_bw #endif - ); + ); } else { @@ -1482,7 +1402,7 @@ static void ivas_write_parameter_bitstream( strat, ivas_total_brate #endif - ); + ); } return; @@ -1496,7 +1416,7 @@ static void ivas_write_parameter_bitstream( *-----------------------------------------------------------------------------------------*/ static void ivas_get_huffman_coded_bs( - ivas_spar_foa_md_enc_state_t *hMdEnc, + ivas_spar_md_enc_state_t *hMdEnc, BSTR_ENC_HANDLE hMetaData, const int16_t nB, const int16_t qsi, @@ -1505,9 +1425,10 @@ static void ivas_get_huffman_coded_bs( , const int16_t bands_bw #endif -) + ) { int16_t i, j; + int16_t pred_coeff_dim, pred_offset; for ( i = 0; i < nB; i++ ) { @@ -1521,9 +1442,20 @@ static void ivas_get_huffman_coded_bs( ndm = hMdEnc->spar_md_cfg.num_dmx_chans_per_band[i]; ndec = hMdEnc->spar_md_cfg.num_decorr_per_band[i]; #endif + + pred_coeff_dim = ndm + ndec - 1; + pred_offset = 0; + if ( hMdEnc->spar_hoa_md_flag ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + pred_offset = FOA_CHANNELS - 1; + } + } + if ( planarCP ) { - for ( j = 0; j < ndm + ndec - 1; j++ ) + for ( j = pred_offset; j < pred_coeff_dim; j++ ) { ivas_huffman_encode( &hMdEnc->huff_coeffs.pred_huff_re[qsi], hMdEnc->spar_md.band_coeffs_idx[i].pred_index_re[j], &code, &len ); push_next_indice( hMetaData, code, len ); @@ -1549,7 +1481,7 @@ static void ivas_get_huffman_coded_bs( } else { - for ( j = 0; j < ndm + ndec - 1; j++ ) + for ( j = pred_offset; j < pred_coeff_dim; j++ ) { #ifdef LBR_SBA_PLANAR if ( ( j == 1 ) && ( bands_bw == IVAS_RED_BAND_FACT ) ) @@ -1592,7 +1524,7 @@ static void ivas_get_huffman_coded_bs( *-----------------------------------------------------------------------------------------*/ static void ivas_get_arith_coded_bs( - ivas_spar_foa_md_enc_state_t *hMdEnc, + ivas_spar_md_enc_state_t *hMdEnc, BSTR_ENC_HANDLE hMetaData, const int16_t *pDo_diff, const int16_t bands_bw, @@ -1604,9 +1536,9 @@ static void ivas_get_arith_coded_bs( const int16_t strat, const int32_t ivas_total_brate #endif -) + ) { - int16_t i, any_diff; + int16_t i, j, any_diff; ivas_cell_dim_t pred_cell_dims[IVAS_MAX_NUM_BANDS]; ivas_cell_dim_t drct_cell_dims[IVAS_MAX_NUM_BANDS]; ivas_cell_dim_t decd_cell_dims[IVAS_MAX_NUM_BANDS]; @@ -1632,24 +1564,33 @@ static void ivas_get_arith_coded_bs( decx_cell_dims[i].dim2 = 0; } else -#endif { - pred_cell_dims[i].dim1 = ndm + ndec - 1; - pred_cell_dims[i].dim2 = 1; - drct_cell_dims[i].dim1 = ndec; - drct_cell_dims[i].dim2 = ndm - 1; - decd_cell_dims[i].dim1 = ndec; - decd_cell_dims[i].dim2 = 1; - decx_cell_dims[i].dim1 = ( ndec * ( ndec - 1 ) ) >> 1; - decx_cell_dims[i].dim2 = 1; +#endif + pred_cell_dims[i].dim1 = ndm + ndec - 1; + if ( hMdEnc->spar_hoa_md_flag ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + pred_cell_dims[i].dim1 -= ( FOA_CHANNELS - 1 ); + } + } + pred_cell_dims[i].dim2 = 1; + drct_cell_dims[i].dim1 = ndec; + drct_cell_dims[i].dim2 = ndm - 1; + decd_cell_dims[i].dim1 = ndec; + decd_cell_dims[i].dim2 = 1; + decx_cell_dims[i].dim1 = ( ndec * ( ndec - 1 ) ) >> 1; + decx_cell_dims[i].dim2 = 1; #ifdef LBR_SBA_PLANAR - if ( ivas_total_brate < IVAS_24k4 ) - { - pred_cell_dims[i].dim1 -= 1; - decd_cell_dims[i].dim1 -= 1; - } + if ( ivas_total_brate < IVAS_24k4 ) + { + pred_cell_dims[i].dim1 -= 1; + decd_cell_dims[i].dim1 -= 1; + } +#endif +#ifdef LBR_SBA + } #endif - } } any_diff = 0; @@ -1661,6 +1602,26 @@ static void ivas_get_arith_coded_bs( break; } } + if ( hMdEnc->spar_hoa_md_flag ) + { + for ( i = 0; i < nB; i++ ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + for ( j = 0; j < pred_cell_dims[i].dim1; j++ ) + { + hMdEnc->spar_md.band_coeffs_idx[i].pred_index_re[j] = + hMdEnc->spar_md.band_coeffs_idx[i].pred_index_re[j + ( FOA_CHANNELS - 1 )]; + + if ( any_diff == 1 ) + { + hMdEnc->spar_md_prior.band_coeffs_idx_mapped[i].pred_index_re[j] = + hMdEnc->spar_md_prior.band_coeffs_idx_mapped[i].pred_index_re[j + ( FOA_CHANNELS - 1 )]; + } + } + } + } + } #ifdef LBR_SBA_PLANAR if ( ivas_total_brate < IVAS_24k4 ) { @@ -1674,16 +1635,35 @@ static void ivas_get_arith_coded_bs( if ( any_diff == 1 ) { - ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md_prior.band_coeffs_idx_mapped, nB, - symbol_arr_old_re, pred_cell_dims, PRED_COEFF, planarCP ); + ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md_prior.band_coeffs_idx_mapped, nB, symbol_arr_old_re, pred_cell_dims, PRED_COEFF, planarCP ); } ivas_arith_encode_cmplx_cell_array( &hMdEnc->arith_coeffs.pred_arith_re[qsi], &hMdEnc->arith_coeffs.pred_arith_re_diff[qsi], pDo_diff, nB, symbol_arr_re, symbol_arr_old_re, pred_cell_dims, hMetaData, any_diff ); + + if ( hMdEnc->spar_hoa_md_flag ) + { + for ( i = 0; i < nB; i++ ) + { + if ( i >= SPAR_DIRAC_SPLIT_START_BAND ) + { + for ( j = pred_cell_dims[i].dim1 - 1; j >= 0; j-- ) + { + hMdEnc->spar_md.band_coeffs_idx[i].pred_index_re[j + ( FOA_CHANNELS - 1 )] = + hMdEnc->spar_md.band_coeffs_idx[i].pred_index_re[j]; + } + for ( j = 0; j < FOA_CHANNELS - 1; j++ ) + { + hMdEnc->spar_md.band_coeffs_idx[i].pred_index_re[j] = 0; + } + } + } + } + #ifdef SPAR_HOA_DBG /*fprintf(stderr, "\n\n band_indexes:\n"); for (int16_t j = 1; j < drct_cell_dims[0].dim1 * drct_cell_dims[0].dim2; j++) - fprintf(stderr, "%d, ", hMdEnc->spar_md.band_coeffs_idx[0].drct_index_re[j]); + fprintf(stderr, "%d, ", hMdEnc->spar_md.band_coeffs_idx[0].drct_index_re[j]); fprintf(stderr, "\n\n"); */ #endif ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md.band_coeffs_idx, nB, symbol_arr_re, drct_cell_dims, DRCT_COEFF, planarCP ); @@ -1708,8 +1688,7 @@ static void ivas_get_arith_coded_bs( if ( any_diff == 1 ) { - ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md_prior.band_coeffs_idx_mapped, nB, - symbol_arr_old_re, decd_cell_dims, DECD_COEFF, planarCP ); + ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md_prior.band_coeffs_idx_mapped, nB, symbol_arr_old_re, decd_cell_dims, DECD_COEFF, planarCP ); } if ( planarCP ) @@ -1723,13 +1702,11 @@ static void ivas_get_arith_coded_bs( ivas_arith_encode_cmplx_cell_array( &hMdEnc->arith_coeffs.decd_arith_re[qsi], &hMdEnc->arith_coeffs.decd_arith_re_diff[qsi], pDo_diff, nB, symbol_arr_re, symbol_arr_old_re, decd_cell_dims, hMetaData, any_diff ); - ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md.band_coeffs_idx, nB, symbol_arr_re, decx_cell_dims, DECX_COEFF, planarCP ); if ( any_diff == 1 ) { - ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md_prior.band_coeffs_idx_mapped, nB, - symbol_arr_old_re, decx_cell_dims, DECX_COEFF, planarCP ); + ivas_copy_band_coeffs_idx_to_arr( hMdEnc->spar_md_prior.band_coeffs_idx_mapped, nB, symbol_arr_old_re, decx_cell_dims, DECX_COEFF, planarCP ); } return; @@ -1794,7 +1771,7 @@ static void ivas_select_next_strat( *-----------------------------------------------------------------------------------------*/ static void ivas_store_prior_coeffs( - ivas_spar_foa_md_enc_state_t *hMdEnc, + ivas_spar_md_enc_state_t *hMdEnc, const int16_t num_bands, #ifndef LBR_SBA const int16_t bands_bw, @@ -1807,7 +1784,6 @@ static void ivas_store_prior_coeffs( #ifndef LBR_SBA float one_by_bands_bw = ( 1.0f / bands_bw ); #endif - if ( dtx_vad == 0 ) { hMdEnc->spar_md_cfg.prior_strat = START; @@ -1828,7 +1804,6 @@ static void ivas_store_prior_coeffs( #else b = (int16_t) floor( i * one_by_bands_bw ); #endif - for ( j = 0; j < IVAS_SPAR_MAX_CH - 1; j++ ) { hMdEnc->spar_md_prior.band_coeffs_idx[i].pred_index_re[j] = hMdEnc->spar_md.band_coeffs_idx[b].pred_index_re[j]; @@ -1845,42 +1820,30 @@ static void ivas_store_prior_coeffs( /*-----------------------------------------------------------------------------------------* - * Function ivas_spar_foa_quant_pred_coeffs_dtx() + * Function ivas_spar_quant_pred_coeffs_dtx() * * Calculate quantization pred coeffs *-----------------------------------------------------------------------------------------*/ -static void ivas_spar_foa_quant_pred_coeffs_dtx( +static void ivas_spar_quant_pred_coeffs_dtx( ivas_spar_md_t *pSpar_md, - float **ppValues, + const float *pValues, const int16_t ndm, - int16_t **ppIndex, + int16_t *pIndex, const int16_t dim1, - float **ppQuant ) + float *pQuant ) { int16_t i; int16_t q_lvl; - float *pVal, val, **ppVal; - int16_t *pIdx, idx, **ppIdx; float pr_min_max[2]; - ppVal = (float **) &pVal; - ppIdx = (int16_t **) &pIdx; - - ppVal[0] = (float *) &val; - ppIdx[0] = (int16_t *) &idx; - pr_min_max[0] = pSpar_md->min_max[0]; pr_min_max[1] = pSpar_md->min_max[1]; for ( i = 0; i < dim1; i++ ) { q_lvl = dtx_pr_real_q_levels[ndm - 1][i]; - ppVal[0][0] = ppValues[0][i]; - - ivas_quantise_real_values( ppVal, q_lvl, pr_min_max[0], pr_min_max[1], ppIdx, ppVal, 1, 1 ); - ppIndex[0][i] = ppIdx[0][0]; - ppQuant[0][i] = ppVal[0][0]; + ivas_quantise_real_values( &pValues[i], q_lvl, pr_min_max[0], pr_min_max[1], &pIndex[i], &pQuant[i], 1 ); } return; @@ -1894,30 +1857,23 @@ static void ivas_spar_foa_quant_pred_coeffs_dtx( *-----------------------------------------------------------------------------------------*/ static void ivas_quant_p_per_band_dtx( - float **ppP_mat, + float *pP_mat, const int16_t num_dec, const int16_t num_dmx, int16_t *ppIdx_pd, - float **ppP_out, + float *pP_out, const int16_t num_ch ) { int16_t i; - float **ppPd, *pPd, pd; - int16_t **ppIdx, *pIdx, idx; int16_t dim = num_ch - num_dmx; - ppPd = (float **) &pPd; - ppIdx = (int16_t **) &pIdx; - ppPd[0] = (float *) &pd; - ppIdx[0] = (int16_t *) &idx; - if ( num_dec == num_ch - 1 ) { for ( i = 0; i < dim; i++ ) { - if ( ppP_mat[i][i] < pr_boost_range[1] && ppP_mat[i][i] > pr_boost_range[0] ) + if ( pP_mat[i] < pr_boost_range[1] && pP_mat[i] > pr_boost_range[0] ) { - ppP_mat[i][i] = pr_boost_range[1]; + pP_mat[i] = pr_boost_range[1]; } } } @@ -1929,18 +1885,12 @@ static void ivas_quant_p_per_band_dtx( for ( i = 0; i < dim; i++ ) { - ppPd[0][0] = ppP_mat[i][i]; - - ivas_quantise_real_values( ppPd, dtx_pd_real_q_levels[num_ch - num_dec - 1][i], dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], ppIdx, ppPd, 1, 1 ); - - ppP_out[i][i] = ppPd[0][0]; - ppIdx_pd[i] = ppIdx[0][0]; + ivas_quantise_real_values( &pP_mat[i], dtx_pd_real_q_levels[num_ch - num_dec - 1][i], dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], &ppIdx_pd[i], &pP_out[i], 1 ); } return; } - /*-----------------------------------------------------------------------------------------* * Function ivas_write_parameter_bitstream_dtx() * @@ -1955,18 +1905,11 @@ static void ivas_write_parameter_bitstream_dtx( const int16_t num_bands ) { int16_t i, j; - float **ppVal, *pVal, val; - int16_t **ppIdx, *pIdx, idx; + float val; + int16_t idx; float pr_min_max[2]; int16_t zero_pad_bits, sid_bits_len; sid_bits_len = hMetaData->nb_bits_tot; - - ppVal = (float **) &pVal; - ppIdx = (int16_t **) &pIdx; - - ppVal[0] = (float *) &val; - ppIdx[0] = (int16_t *) &idx; - pr_min_max[0] = pSpar_md->min_max[0]; pr_min_max[1] = pSpar_md->min_max[1]; @@ -2004,17 +1947,15 @@ static void ivas_write_parameter_bitstream_dtx( pd_q_lvls = dtx_pd_real_q_levels[ndm - 1][pd_idx_2 - 1]; pd = pSpar_md->band_coeffs_idx[i].decd_index_re[pd_idx_2 - 1]; } + val = dtx_pd_real_min_max[0]; + ivas_quantise_real_values( &val, pd_q_lvls, dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], &idx, &val, 1 ); - ppVal[0][0] = dtx_pd_real_min_max[0]; - ivas_quantise_real_values( ppVal, pd_q_lvls, dtx_pd_real_min_max[0], dtx_pd_real_min_max[1], ppIdx, ppVal, 1, 1 ); + pd -= idx; - pd -= ppIdx[0][0]; - - ppVal[0][0] = pr_min_max[0]; - ivas_quantise_real_values( ppVal, pr_q_lvls, pr_min_max[0], pr_min_max[1], ppIdx, ppVal, 1, 1 ); - - pr -= ppIdx[0][0]; + val = pr_min_max[0]; + ivas_quantise_real_values( &val, pr_q_lvls, pr_min_max[0], pr_min_max[1], &idx, &val, 1 ); + pr -= idx; pr_pd_bits = ivas_get_bits_to_encode( pd_q_lvls * pr_q_lvls ); value = (uint16_t) ( pr * pd_q_lvls + pd ); @@ -2025,23 +1966,22 @@ static void ivas_write_parameter_bitstream_dtx( { int16_t pr_q_lvls1, pr_q_lvls2; int16_t pr_idx1, pr_idx2, pr_pr_bits; + pr_q_lvls1 = dtx_pr_real_q_levels[ndm - 1][pr_idx_1 - 1]; pr_q_lvls2 = dtx_pr_real_q_levels[ndm - 1][pr_idx_2 - 1]; - - ppVal[0][0] = pr_min_max[0]; - ivas_quantise_real_values( ppVal, pr_q_lvls1, pr_min_max[0], pr_min_max[1], ppIdx, ppVal, 1, 1 ); + val = pr_min_max[0]; + ivas_quantise_real_values( &val, pr_q_lvls1, pr_min_max[0], pr_min_max[1], &idx, &val, 1 ); pr_idx1 = pSpar_md->band_coeffs_idx[i].pred_index_re[pr_idx_1 - 1]; - pr_idx1 -= ppIdx[0][0]; + pr_idx1 -= idx; - ppVal[0][0] = pr_min_max[0]; - ivas_quantise_real_values( ppVal, pr_q_lvls2, pr_min_max[0], pr_min_max[1], ppIdx, ppVal, 1, 1 ); + val = pr_min_max[0]; + ivas_quantise_real_values( &val, pr_q_lvls2, pr_min_max[0], pr_min_max[1], &idx, &val, 1 ); pr_idx2 = pSpar_md->band_coeffs_idx[i].pred_index_re[pr_idx_2 - 1]; - pr_idx2 -= ppIdx[0][0]; - + pr_idx2 -= idx; value = (uint16_t) ( pr_idx2 * pr_q_lvls1 + pr_idx1 ); pr_pr_bits = ivas_get_bits_to_encode( pr_q_lvls1 * pr_q_lvls2 ); @@ -2078,17 +2018,7 @@ static void ivas_quant_pred_coeffs_per_band( ivas_quant_strat_t *pQs, const int16_t num_ch ) { - float *pQuant_re, *pCoeff_re; - int16_t *pIdx_re; - float **ppPred_coeffs_re = (float **) &pCoeff_re; - float **ppPred_quant_re = (float **) &pQuant_re; - int16_t **ppPred_idx_re = (int16_t **) &pIdx_re; - - ppPred_idx_re[0] = &pBand_coeffs_idx->pred_index_re[0]; - ppPred_coeffs_re[0] = &pband_coeffs->pred_re[0]; - ppPred_quant_re[0] = &pband_coeffs->pred_quant_re[0]; - - ivas_quantise_real_values( ppPred_coeffs_re, pQs->PR.q_levels[0], pQs->PR.min, pQs->PR.max, ppPred_idx_re, ppPred_quant_re, 1, ( num_ch - 1 ) ); + ivas_quantise_real_values( pband_coeffs->pred_re, pQs->PR.q_levels[0], pQs->PR.min, pQs->PR.max, pBand_coeffs_idx->pred_index_re, pband_coeffs->pred_quant_re, ( num_ch - 1 ) ); return; } @@ -2110,17 +2040,6 @@ static void ivas_quant_c_per_band( int16_t i; int16_t j, k; float C_re[IVAS_SPAR_MAX_C_COEFF]; - float *pC_re[IVAS_SPAR_MAX_C_COEFF]; - int16_t *pIdx_re[IVAS_SPAR_MAX_C_COEFF]; - float **ppC_re = (float **) &pC_re[0]; - int16_t **ppIdx_re = (int16_t **) &pIdx_re[0]; - - for ( i = 0; i < ndec * ( ndm - 1 ); i++ ) - { - ppC_re[i] = &C_re[i]; - ppIdx_re[i] = &pBand_coeffs_idx->drct_index_re[i]; - } - k = 0; for ( i = 0; i < ndec; i++ ) { @@ -2130,19 +2049,16 @@ static void ivas_quant_c_per_band( k++; } } - #ifdef SPAR_HOA_DBG /*for (i = 0; i < ndec; i++) { - for (j = 0; j < ndm - 1; j++) - { - ppIdx_re[i][j] = 100; - } + for (j = 0; j < ndm - 1; j++) + { + ppIdx_re[i][j] = 100; + } }*/ #endif - - ivas_quantise_real_values( ppC_re, pQs->C.q_levels[0], pQs->C.min, pQs->C.max, ppIdx_re, ppC_re, ndec * ( ndm - 1 ), 1 ); - + ivas_quantise_real_values( C_re, pQs->C.q_levels[0], pQs->C.min, pQs->C.max, pBand_coeffs_idx->drct_index_re, C_re, ndec * ( ndm - 1 ) ); k = 0; for ( i = 0; i < ndec; i++ ) { @@ -2157,11 +2073,11 @@ static void ivas_quant_c_per_band( k = 0; for (i = 0; i < ndec; i++) { - for (j = 0; j < ndm - 1; j++) - { - fprintf(stderr, "%d,%d: %f, %f, %d\n", i, j, pband_coeffs->C_re[i][j], pband_coeffs->C_quant_re[i][j], pBand_coeffs_idx->drct_index_re[k]); - k++; - } + for (j = 0; j < ndm - 1; j++) + { + fprintf(stderr, "%d,%d: %f, %f, %d\n", i, j, pband_coeffs->C_re[i][j], pband_coeffs->C_quant_re[i][j], pBand_coeffs_idx->drct_index_re[k]); + k++; + } }*/ #endif @@ -2181,40 +2097,15 @@ static void ivas_quant_p_per_band( ivas_quant_strat_t *pQs, const int16_t num_ch ) { - float P_re_diag[IVAS_SPAR_MAX_CH - 1]; - int16_t i; - int16_t dim = num_ch - 1; - float *pP_diag[IVAS_SPAR_MAX_CH - 1]; - int16_t *pDecd_idx[IVAS_SPAR_MAX_CH - 1]; - float **ppP_diag = (float **) &pP_diag[0]; - int16_t **ppDecd_idx = (int16_t **) &pDecd_idx[0]; - - for ( i = 0; i < dim; i++ ) - { - ppP_diag[i] = &P_re_diag[i]; - ppDecd_idx[i] = &pBand_coeffs_idx->decd_index_re[i]; - } - - for ( i = 0; i < dim; i++ ) - { - P_re_diag[i] = pband_coeffs->P_re[i]; - } - #ifdef SPAR_HOA_DBG /*fprintf(stderr, "\n\n P_d:\n"); for (i = 0; i < dim; i++) { - fprintf(stderr, "%f, ", P_re_diag[i]); + fprintf(stderr, "%f, ", P_re_diag[i]); } fprintf(stderr, "\n\n");*/ #endif - - ivas_quantise_real_values( ppP_diag, pQs->P_r.q_levels[0], pQs->P_r.min, pQs->P_r.max, ppDecd_idx, ppP_diag, num_ch - 1, 1 ); - - for ( i = 0; i < dim; i++ ) - { - pband_coeffs->P_quant_re[i] = P_re_diag[i]; - } + ivas_quantise_real_values( pband_coeffs->P_re, pQs->P_r.q_levels[0], pQs->P_r.min, pQs->P_r.max, pBand_coeffs_idx->decd_index_re, pband_coeffs->P_quant_re, num_ch - 1 ); return; } diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index f158d1174d4ec08031e4de15fa35ccdcb6084bb6..6638a8948893cd39c5278f7d59122448c75a1237 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -35,13 +35,11 @@ #include #include "options.h" -#include "ivas_cnst.h" #include "cnst.h" -#include "stat_enc.h" #include "ivas_cnst.h" +#include "stat_enc.h" #include "ivas_stat_com.h" - /*----------------------------------------------------------------------------------* * DFT Stereo encoder structures *----------------------------------------------------------------------------------*/ @@ -194,6 +192,8 @@ typedef struct stereo_dft_enc_data_struct float Spd_R_smooth[STEREO_DFT_N_32k_ENC / 2]; float sid_gipd; int16_t coh_fade_counter; + float prev_sid_gipd; + int16_t prev_sid_no_ipd_flag; /*IPD*/ float gipd[STEREO_DFT_ENC_DFT_NB]; @@ -209,6 +209,10 @@ typedef struct stereo_dft_enc_data_struct float sfm; float sum_dot_prod_real; float sum_dot_prod_img; + float dot_prod_real_smooth[STEREO_DFT_BAND_MAX]; + float dot_prod_img_smooth[STEREO_DFT_BAND_MAX]; + float ipd_buf[STEREO_DFT_BAND_MAX][STEREO_DFT_IPD_BUF_LEN]; + float prev_gipd; /*ITD*/ ITD_DATA_HANDLE hItd; @@ -232,6 +236,10 @@ typedef struct stereo_dft_enc_data_struct #endif + int16_t currentNumUpdates; + int16_t expectedNumUpdates; /* Expected number of frames before use of ITD estimate */ + int16_t resetFrames; + /* energy buffers for ICBWE */ float nrg_L[2]; float nrg_R[2]; @@ -278,6 +286,7 @@ typedef struct stereo_dft_enc_data_struct int16_t flip_sign; #ifdef DEBUG_MODE_DFT int16_t verbose; + int16_t res_cod_bits; #endif } STEREO_DFT_ENC_DATA, *STEREO_DFT_ENC_DATA_HANDLE; @@ -311,6 +320,8 @@ typedef struct stereo_mdct_enc_data_structure int16_t sw_uncorr; + int16_t isSBAStereoMode; + } STEREO_MDCT_ENC_DATA, *STEREO_MDCT_ENC_DATA_HANDLE; @@ -539,6 +550,26 @@ typedef struct ivas_stereo_classifier_data_structure } STEREO_CLASSIF_DATA, *STEREO_CLASSIF_HANDLE; +/*----------------------------------------------------------------------------------* + * ISM DTX structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + int16_t dtx_flag; + int16_t sce_id_dtx; + +#ifdef DISCRETE_ISM_DTX_CNG + int16_t cnt_SID_ISM; +#else + int16_t dtx_speech_buffer_enc[PARAM_ISM_HYS_BUF_SIZE]; +#endif + + float long_term_energy_stereo_dmx_enc[MAX_NUM_OBJECTS][PARAM_ISM_HYS_BUF_SIZE]; + float coh[MAX_NUM_OBJECTS]; + +} ISM_DTX_DATA, *ISM_DTX_HANDLE; + /*----------------------------------------------------------------------------------* * Front-VAD structure *----------------------------------------------------------------------------------*/ @@ -555,6 +586,7 @@ typedef struct front_vad_enc VAD_HANDLE hVAD; /* VAD handle */ float *delay_buf; int16_t delay_samples; + int16_t rem_dtx_ho; /* Remaining hangover frames */ } FRONT_VAD_ENC, *FRONT_VAD_ENC_HANDLE; @@ -569,7 +601,7 @@ typedef struct ivas_dirac_enc_data_structure PARAM_ISM_CONFIG_HANDLE hParamIsm; /* Parametric ISM handle */ IVAS_FB_MIXER_HANDLE hFbMixer; - float *sba_synchro_buffer[IVAS_MAX_NUM_CH]; // VE: all 16 buffers not needed ? + float *sba_synchro_buffer[DIRAC_MAX_ANA_CHANS]; int16_t num_samples_synchro_delay; /* DirAC parameter estimation */ @@ -593,7 +625,7 @@ typedef struct ivas_dirac_enc_data_structure * SPAR encoder structures *----------------------------------------------------------------------------------*/ -/* SPAR AGC structures */ +/* AGC structures */ typedef struct ivas_agc_enc_chan_state_t { int16_t lastExp; @@ -616,7 +648,7 @@ typedef struct ivas_agc_enc_state_t } ivas_agc_enc_state_t; -/* SPAR covariance structures */ +/* covariance structures */ typedef struct ivas_enc_cov_handler_state_t { ivas_cov_smooth_state_t *pCov_state; @@ -626,18 +658,9 @@ typedef struct ivas_enc_cov_handler_state_t } ivas_enc_cov_handler_state_t; -typedef struct ivas_enc_cov_handler_in_buf_t -{ - float *ppIn_FR_real[IVAS_SPAR_MAX_CH]; - float *ppIn_FR_imag[IVAS_SPAR_MAX_CH]; - int16_t num_ch; - int16_t transient_det; - int16_t dtx_cov_flag; - -} ivas_enc_cov_handler_in_buf_t; -/* SPAR FOA MD structures */ -typedef struct ivas_spar_foa_md_enc_state_t +/* SPAR MD structures */ +typedef struct ivas_spar_md_enc_state_t { ivas_spar_md_t spar_md; ivas_spar_md_prev_t spar_md_prior; @@ -648,21 +671,12 @@ typedef struct ivas_spar_foa_md_enc_state_t float ***cov_real; float ***cov_dtx_real; float ***mixer_mat_local; - ivas_spar_foa_md_com_cfg spar_md_cfg; + ivas_spar_md_com_cfg spar_md_cfg; ivas_arith_coeffs_t arith_coeffs; ivas_huff_coeffs_t huff_coeffs; int16_t table_idx; - -} ivas_spar_foa_md_enc_state_t; - -typedef struct ivas_spar_foa_md_enc_in_buf_t -{ - float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - int16_t num_bands; - int16_t dtx_vad; - -} ivas_spar_foa_md_enc_in_buf_t; - + int16_t spar_hoa_md_flag; +} ivas_spar_md_enc_state_t; /* PCA structure */ typedef struct @@ -677,28 +691,19 @@ typedef struct } PCA_ENC_STATE; - -/* SPAR FOA structures */ -typedef struct ivas_spar_foa_enc_state_t +/* SPAR main structure */ +typedef struct ivas_spar_enc_lib_t { - ivas_spar_foa_md_enc_state_t *hMdEnc; + ivas_spar_md_enc_state_t *hMdEnc; IVAS_FB_MIXER_HANDLE hFbMixer; ivas_enc_cov_handler_state_t *hCovEnc; ivas_trans_det_state_t *hTranDet; ivas_agc_enc_state_t *hAgcEnc; int16_t dirac_to_spar_md_bands[DIRAC_MAX_NBANDS]; int16_t enc_param_start_band; + int16_t AGC_Enable; PCA_ENC_STATE *hPCA; - int32_t core_nominal_brate; /* Nominal bitrate for core coding */ - -} ivas_spar_foa_enc_state_t; - - -/* SPAR main structure */ -typedef struct ivas_spar_enc_lib_t -{ - ivas_spar_foa_enc_state_t *hSparFoa; - + int32_t core_nominal_brate; /* Nominal bitrate for core coding */ FRONT_VAD_ENC_HANDLE hFrontVad; /* front-VAD handle */ ENC_CORE_HANDLE hCoreCoderVAD; /* core-coder handle for front-VAD module */ @@ -715,7 +720,6 @@ typedef struct ivas_spar_enc_lib_t typedef struct ivas_param_mc_enc_data_structure { - IVAS_FB_MIXER_HANDLE hFbMixer; int16_t transient_detector_delay; const float *dmx_factors; @@ -736,12 +740,25 @@ typedef struct ivas_param_mc_enc_data_structure * MASA encoder structures *----------------------------------------------------------------------------------*/ +#ifdef FIX_382_MASA_META_FRAMING_ASYNC +/* structure storing MASA framing sync detection and compensation data */ +typedef struct ivas_masa_sync_struct +{ + MASA_METADATA_FRAME previous_metadata; + uint8_t prev_sim_stop; + uint8_t prev_offset; + MASA_FRAME_MODE frame_mode; +} MASA_SYNC_STATE, *MASA_SYNC_HANDLE; +#endif + typedef struct ivas_masa_encoder_data_struct { float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; int16_t num_Cldfb_instances; HANDLE_CLDFB_FILTER_BANK cldfbAnaEnc[MAX_NUM_ENC_CLDFB_INSTANCES]; +#ifndef FIX_350_MASA_DELAY_COMP float *delay_buffer[MASA_MAX_TRANSPORT_CHANNELS]; +#endif int16_t band_mapping[MASA_FREQUENCY_BANDS + 1]; uint8_t twoDirBands[MASA_FREQUENCY_BANDS]; float importanceWeight[MASA_FREQUENCY_BANDS]; @@ -753,6 +770,9 @@ typedef struct ivas_masa_encoder_data_struct float onset_detector_1; float onset_detector_2; +#ifdef FIX_382_MASA_META_FRAMING_ASYNC + MASA_SYNC_STATE sync_state; +#endif } MASA_ENCODER_DATA; typedef struct ivas_masa_encoder_struct @@ -829,16 +849,17 @@ typedef struct ivas_mcmasa_enc_data_structure typedef struct stereo_cng_enc { - int16_t prev_sg_average_counter; /* Counter for sidegain averaging */ - int16_t sg_active_cnt; /* Counter for sidegain averaging */ - int16_t sg_average_counter; /* Counter for sidegain averaging */ - float sg_average[STEREO_DFT_ERB4_BANDS]; /* Sidegain average */ - float prev_sg_average[STEREO_DFT_ERB4_BANDS]; /* Previous sidegain average */ - float mem_cohBand[STEREO_DFT_BAND_MAX / 2]; /* Coherence memory */ - float coh_crossfade[STEREO_DFT_BAND_MAX / 2]; /* Coherence memory */ - int16_t td_active; /* TD-stereo indication */ - int16_t first_SID_after_TD; /* Set if first SID frame after TD stereo */ - int16_t first_SID; /* Set if first SID frame since codec start */ + int16_t prev_sg_average_counter; /* Counter for sidegain averaging */ + int16_t sg_active_cnt; /* Counter for sidegain averaging */ + int16_t sg_average_counter; /* Counter for sidegain averaging */ + float sg_average[STEREO_DFT_ERB4_BANDS]; /* Sidegain average */ + float prev_sg_average[STEREO_DFT_ERB4_BANDS]; /* Previous sidegain average */ + float mem_cohBand[STEREO_DFT_BAND_MAX / 2]; /* Coherence memory */ + float prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )]; /* Previous coherence */ + int16_t cng_counter; /* Counter for cng period length */ + int16_t td_active; /* TD-stereo indication */ + int16_t first_SID_after_TD; /* Set if first SID frame after TD stereo */ + int16_t first_SID; /* Set if first SID frame since codec start */ } STEREO_CNG_ENC, *STEREO_CNG_ENC_HANDLE; @@ -849,8 +870,9 @@ typedef struct stereo_cng_enc typedef struct sce_enc_data_structure { - int16_t sce_id; /* SCE # identifier */ - int32_t element_brate; /* SCE element total bitrate in bps */ + int16_t sce_id; /* SCE # identifier */ + int32_t element_brate; /* SCE element total bitrate in bps */ + int32_t last_element_brate; /* last SCE element bitrate in bps */ BSTR_ENC_HANDLE hMetaData; /* Metadata bitstream handle */ @@ -919,11 +941,14 @@ typedef struct mct_enc_data_structure float lastxCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS]; int16_t lowE_ch[MCT_MAX_CHANNELS]; +#ifndef ISSUE_24_CLEANUP_MCT_LFE int16_t LFE_off; +#endif uint16_t mc_global_ild[MCT_MAX_CHANNELS]; int16_t nBitsMCT; /* number of bits spent on mct side info */ +#ifndef ISSUE_24_CLEANUP_MCT_LFE int16_t num_lfe; - +#endif /* pointers to local buffers */ float *p_mdst_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS]; float *p_orig_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS]; @@ -983,6 +1008,7 @@ typedef struct ivas_lfe_enc_data_structure LFE_WINDOW_HANDLE pWindow_state; BSTR_ENC_HANDLE hBstr; /* pointer to encoder bitstream handle */ const uint16_t *cum_freq_models[IVAS_MAX_NUM_QUANT_STRATS][IVAS_MAX_NUM_DCT_COEF_GROUPS]; + int16_t lfe_enc_indices_coeffs_tbl[IVAS_MAX_NUM_QUANT_STRATS][IVAS_MAX_NUM_DCT_COEF_GROUPS]; int16_t lfe_bits; float *old_wtda_audio; @@ -1005,10 +1031,13 @@ typedef struct encoder_config_structure int16_t element_mode_init; /* element mode used at initialization */ int16_t stereo_dmx_evs; /* flag to indicate that stereo downmix for EVS encoder */ - +#ifdef NCHAN_ISM_PARAMETER + int16_t nchan_ism; /* number of ISM channels */ +#endif int16_t sba_order; /* Ambisonic (SBA) order */ int16_t sba_planar; /* Ambisonic (SBA) planar flag */ MC_LS_SETUP mc_input_setup; /* multichannel input ls setup */ + int16_t ism_extended_metadata_flag; /* flag indicating extended metadata encoding, including radius and orientation (yaw, pitch) in ISM format */ int16_t Opt_AMR_WB; /* flag indicating AMR-WB IO mode */ @@ -1024,7 +1053,6 @@ typedef struct encoder_config_structure int16_t last_Opt_SC_VBR; /* flag indicating prev frame's SC-VBR mode */ /* temp. development parameters */ - int16_t Opt_AGC_ON; /* flag indicating AGC operation in SBA */ int16_t Opt_PCA_ON; /* flag indicating PCA operation in SBA */ #ifdef DEBUGGING @@ -1032,6 +1060,9 @@ typedef struct encoder_config_structure int16_t stereo_mode_cmdl; /* stereo mode forced from the command-line */ int16_t force; /* parameter to force specific "core" of the Core-Coder*/ int16_t mdct_stereo_mode_cmdl; /* mdct stereo mode forced from command-line, employed only when DEBUG_FORCE_MDCT_STEREO_MODE is activated */ +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + int16_t Opt_AGC_ON; /* flag indicating AGC operation in SBA */ +#endif #endif @@ -1050,10 +1081,9 @@ typedef struct /* high-level encoder parameters */ int16_t nchan_transport; /* number of transport channels */ - + int16_t sba_analysis_order; /* Ambisonic (SBA) order used for analysis and coding */ int16_t codec_mode; /* Mode1 or Mode2 of core codec */ int16_t last_codec_mode; /* previous frame Mode 1 or 2 */ - float **mem_hp20_in; /* input signals HP filter memories */ /* core-encoder modules */ @@ -1064,6 +1094,7 @@ typedef struct /* multichannel modules */ ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS]; /* ISM metadata handles (storage for one frame of read ISM metadata) */ + ISM_DTX_HANDLE hISMDTX; /* ISM DTX handle */ DIRAC_ENC_HANDLE hDirAC; /* DirAC data handle */ SPAR_ENC_HANDLE hSpar; /* SPAR encoder handle */ MASA_ENCODER_HANDLE hMasa; /* MASA encoder data and configuration */ diff --git a/lib_enc/ivas_stereo_adapt_GR_enc.c b/lib_enc/ivas_stereo_adapt_GR_enc.c index 8f07441920a8506b175eeb558e29f8c58a868e9f..087ecda8e0553e06e075aaad3c8254e79ec15ac7 100644 --- a/lib_enc/ivas_stereo_adapt_GR_enc.c +++ b/lib_enc/ivas_stereo_adapt_GR_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,7 @@ #include "ivas_prot.h" #include "prot.h" #include "stat_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_rom_com.h" #ifdef DEBUGGING #include "debug.h" diff --git a/lib_enc/ivas_stereo_classifier.c b/lib_enc/ivas_stereo_classifier.c index 6d41221dcf66942fdc74a0454ec55c840c32c8c1..d4d0b310b67e228da0bf9f526929fb64be8e7ec9 100644 --- a/lib_enc/ivas_stereo_classifier.c +++ b/lib_enc/ivas_stereo_classifier.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -1092,7 +1092,7 @@ static void edge_detect( for ( j = 1; j <= i; j++ ) { y = inp_max - edge_slope * j; - err = y - thr_f( inp[j], inp_min, inp_max ); + err = y - check_bounds( inp[j], inp_min, inp_max ); edge[i] += err * err; } @@ -1130,7 +1130,7 @@ static void edge_detect( for ( j = 1; j < i; j++ ) { y = inp_min + edge_slope * j; - err = y - thr_f( inp[j], inp_min, inp_max ); + err = y - check_bounds( inp[j], inp_min, inp_max ); edge[i] += err * err; } diff --git a/lib_enc/ivas_stereo_cng_enc.c b/lib_enc/ivas_stereo_cng_enc.c index 860cdbe88ffb782420c8c41456c4abc816e40aa8..784ec10807aa6a92c0eb8a6d64c0afde1f342805 100644 --- a/lib_enc/ivas_stereo_cng_enc.c +++ b/lib_enc/ivas_stereo_cng_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,6 +32,7 @@ #include #include "options.h" +#include #include "cnst.h" #include "rom_enc.h" #include "rom_com.h" @@ -42,14 +43,15 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------- * Local constants *-------------------------------------------------------------------*/ -#define COH_FADE_MAX 4 +#define COH_FADE_MAX 4 +#define COH_FADE_UPDATES 2 /*--------------------------------------------------------------- @@ -59,17 +61,17 @@ * ---------------------------------------------------------------*/ void stereo_dft_enc_sid_calc_coh( - STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ - float coh_crossfade[STEREO_DFT_BAND_MAX / 2], /* i/o: Coherence crossfade memory */ - int16_t *td_active, /* i/o: TD stereo mode indicator */ - int16_t *first_SID, /* i/o: First SID indicator */ - float *cohBand /* i/o: Coherence per band */ + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ + float prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence */ + int16_t *td_active, /* i/o: TD stereo mode indicator */ + int16_t *first_SID, /* i/o: First SID indicator */ + float *cohBand /* i/o: Coherence per band */ ) { int16_t b, k; float coh_weight; float coh_weight_sum; - + float xspec_scale; /* Cluster the coherence into bands using a weighted average. The coherence is weighted with the energy spectrum of the mixdown signal. */ for ( b = 0; b < hStereoDft->nbands; b++ ) @@ -77,36 +79,59 @@ void stereo_dft_enc_sid_calc_coh( cohBand[b] = 0; coh_weight_sum = 0; - for ( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ ) + if ( hStereoDft->coh_fade_counter == 0 && !*first_SID ) { - coh_weight = hStereoDft->DFT[0][2 * k] * hStereoDft->DFT[0][2 * k] + hStereoDft->DFT[0][2 * k + 1] * hStereoDft->DFT[0][2 * k + 1]; - cohBand[b] += coh_weight * ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] ) / ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] + EPSILON ); - coh_weight_sum += coh_weight; + for ( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ ) + { + xspec_scale = sqrtf( ( prev_cohBand[b] * ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] ) ) / ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] + EPSILON ) ); + hStereoDft->xspec_smooth[2 * k] *= xspec_scale; + hStereoDft->xspec_smooth[2 * k + 1] *= xspec_scale; + } + + cohBand[b] = prev_cohBand[b]; } - if ( coh_weight_sum > 0 ) + else { - cohBand[b] = cohBand[b] / coh_weight_sum; + for ( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ ) + { + coh_weight = hStereoDft->DFT[0][2 * k] * hStereoDft->DFT[0][2 * k] + hStereoDft->DFT[0][2 * k + 1] * hStereoDft->DFT[0][2 * k + 1]; + cohBand[b] += coh_weight * ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] ) / ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] + EPSILON ); + coh_weight_sum += coh_weight; + } + if ( coh_weight_sum > 0 ) + { + cohBand[b] = cohBand[b] / coh_weight_sum; + } } } if ( *first_SID ) { - mvr2r( cohBand, coh_crossfade, hStereoDft->nbands ); + mvr2r( cohBand, prev_cohBand, hStereoDft->nbands ); + mvr2r( prev_cohBand, &( prev_cohBand[STEREO_DFT_BAND_MAX / 2] ), hStereoDft->nbands ); *first_SID = 0; } - if ( hStereoDft->coh_fade_counter < COH_FADE_MAX && *td_active ) + if ( hStereoDft->coh_fade_counter < COH_FADE_MAX && ( *td_active || hStereoDft->currentNumUpdates < COH_FADE_UPDATES ) ) { for ( b = 0; b < hStereoDft->nbands; b++ ) { - cohBand[b] = ( cohBand[b] * hStereoDft->coh_fade_counter + coh_crossfade[b] * ( COH_FADE_MAX - hStereoDft->coh_fade_counter ) ) / COH_FADE_MAX; + cohBand[b] = ( cohBand[b] * hStereoDft->coh_fade_counter + prev_cohBand[b] * ( COH_FADE_MAX - hStereoDft->coh_fade_counter ) ) / COH_FADE_MAX; } hStereoDft->coh_fade_counter++; - mvr2r( cohBand, coh_crossfade, hStereoDft->nbands ); + if ( hStereoDft->coh_fade_counter > 0 ) + { + mvr2r( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands ); + } + mvr2r( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands ); } else { - mvr2r( cohBand, coh_crossfade, hStereoDft->nbands ); + if ( hStereoDft->coh_fade_counter > 0 ) + { + mvr2r( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands ); + } + mvr2r( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands ); hStereoDft->coh_fade_counter = COH_FADE_MAX; *td_active = 0; } @@ -148,7 +173,8 @@ void stereo_dft_enc_sid_coh( int16_t alpha_level; int16_t n; - nr_of_sid_stereo_bits = ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + /* TODO: still use old number of bits to keep bitexactness in output */ + nr_of_sid_stereo_bits = ( 4400 /*IVAS_SID_5k2*/ - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; zeropad = 0; /* Encode coherence vector. Find best fixed predictor by minimizing prediction error on input vector. @@ -303,6 +329,8 @@ void stereo_dft_enc_sid_coh( ( *nb_bits )++; } + push_next_indice( hBstr, zeropad, ( IVAS_SID_5k2 - 4400 ) / FRAMES_PER_SEC ); + return; } @@ -343,6 +371,9 @@ void stereo_dft_cng_side_gain( } hStereoCng->sg_average_counter++; + hStereoCng->cng_counter++; + hStereoCng->cng_counter = min( hStereoCng->cng_counter, STEREO_DFT_SG_ACT_CNT_MAX ); + if ( core_brate == SID_2k40 ) { /* SID frame */ @@ -440,9 +471,10 @@ void stereo_enc_cng_init( hStereoCng->sg_active_cnt = 0; hStereoCng->first_SID = 1; set_f( hStereoCng->mem_cohBand, 0.5f, STEREO_DFT_BAND_MAX / 2 ); - set_zero( hStereoCng->coh_crossfade, STEREO_DFT_BAND_MAX / 2 ); + set_zero( hStereoCng->prev_cohBand, 2 * ( STEREO_DFT_BAND_MAX / 2 ) ); hStereoCng->td_active = 0; hStereoCng->first_SID_after_TD = 1; + hStereoCng->cng_counter = 0; return; } @@ -459,7 +491,8 @@ void stereo_cng_upd_counters( const int32_t element_mode, /* i : element mode */ const int16_t nbands, /* i : Number of bands in active */ const float sidSideGain[], /* i : SID side gains */ - const int16_t burst_ho_count /* i : Hang-over count */ + const int16_t burst_ho_count, /* i : Hang-over count */ + int16_t *coh_fade_counter /* i : Coherence fade counter */ ) { int16_t b; @@ -483,5 +516,14 @@ void stereo_cng_upd_counters( hStereoCng->sg_active_cnt++; hStereoCng->sg_active_cnt = min( hStereoCng->sg_active_cnt, STEREO_DFT_SG_ACT_CNT_MAX ); + if ( hStereoCng->sg_active_cnt > STEREO_DFT_CNG_ITD_CNT ) + { + hStereoCng->cng_counter = 0; + } + + if ( element_mode == IVAS_CPE_DFT ) + { + *coh_fade_counter = 0; + } return; } diff --git a/lib_enc/ivas_stereo_dft_enc.c b/lib_enc/ivas_stereo_dft_enc.c index 08b89ac9c30aecefc91dedc92a5b7bb710b408fb..ab4844ab944067f4a519135e05b06574f6d460f5 100644 --- a/lib_enc/ivas_stereo_dft_enc.c +++ b/lib_enc/ivas_stereo_dft_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif @@ -62,6 +62,7 @@ static FILE *pF = NULL; #define STEREO_DFT_NRG_PAST_MAX_BAND_LB 4 #define STEREO_DFT_DMX_CROSSOVER ( int16_t )( 132 * ( (float) ( STEREO_DFT_N_NS_ENC ) / STEREO_DFT_N_NS ) + 0.5f ) /* crossover bin between binwise and bandwise DMX */ #define ITD_VAD_E_BAND_N_INIT 200000 +#define ITD_SID_PREV_FRAMES 5 /*------------------------------------------------------------------------- @@ -72,6 +73,12 @@ static void stereo_dft_enc_open( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, const in static void stereo_dft_enc_compute_prm( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, float *DFT_L, float *DFT_R, int16_t k_offset, int16_t flag_quant, const int16_t sp_aud_decision0, const int16_t vad_flag, float *bin_nrgL, float *bin_nrgR, float *dot_prod_nrg_ratio ); +static float stereo_dft_calc_mean_bipd( float *pIpd, float ipd_buf[STEREO_DFT_IPD_BUF_LEN] ); + +static float stereo_dft_calc_mean_ipd_change( float *pIpd, float *ipd_smooth, int16_t gipd_band_max ); + +static void stereo_dft_gipd_stabilization( float *pgIpd, float prev_gipd, float ipd_mean_change ); + #ifdef DEBUG_MODE_DFT static void stereo_dft_enc_get_nipd_flag( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, float *pgIpd, const int16_t sp_aud_decision0, const float gainIPD ); #else @@ -269,17 +276,17 @@ ivas_error stereo_dft_enc_create( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: DFT Stereo memory already allocated\n" ); } - if ( ( hStereoDft_loc = (STEREO_DFT_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_DFT_ENC_DATA ) ) ) == NULL ) + if ( ( hStereoDft_loc = (STEREO_DFT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_DFT_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT Stereo\n" ) ); } - if ( ( hStereoDft_loc->hConfig = (STEREO_DFT_CONFIG_DATA_HANDLE) count_malloc( sizeof( STEREO_DFT_CONFIG_DATA ) ) ) == NULL ) + if ( ( hStereoDft_loc->hConfig = (STEREO_DFT_CONFIG_DATA_HANDLE) malloc( sizeof( STEREO_DFT_CONFIG_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT Stereo Config\n" ) ); } - if ( ( hStereoDft_loc->hItd = (ITD_DATA_HANDLE) count_malloc( sizeof( ITD_DATA ) ) ) == NULL ) + if ( ( hStereoDft_loc->hItd = (ITD_DATA_HANDLE) malloc( sizeof( ITD_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ITD data\n" ) ); } @@ -432,6 +439,13 @@ void stereo_dft_enc_reset( hStereoDft->side_gain_counter = 0; hStereoDft->side_gain_bitdiff_lp = STEREO_DFT_BITDIFF_INIT; set_zero( hStereoDft->gipd, STEREO_DFT_ENC_DFT_NB ); + set_zero( hStereoDft->dot_prod_real_smooth, STEREO_DFT_BAND_MAX ); + set_zero( hStereoDft->dot_prod_img_smooth, STEREO_DFT_BAND_MAX ); + for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) + { + set_zero( hStereoDft->ipd_buf[i], STEREO_DFT_IPD_BUF_LEN ); + } + hStereoDft->prev_gipd = 0.f; hStereoDft->gipd_index = 0; set_zero( hStereoDft->res_pred_gain, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); set_s( hStereoDft->res_pred_index_EC, 0, STEREO_DFT_BAND_MAX ); @@ -491,6 +505,13 @@ void stereo_dft_enc_reset( set_f( hStereoDft->Spd_L_smooth, 1.0f, STEREO_DFT_N_32k_ENC / 2 ); set_f( hStereoDft->Spd_R_smooth, 1.0f, STEREO_DFT_N_32k_ENC / 2 ); + hStereoDft->currentNumUpdates = 0; + hStereoDft->expectedNumUpdates = FIXED_SID_RATE; + hStereoDft->resetFrames = 0; + hStereoDft->sid_gipd = 0; + hStereoDft->prev_sid_gipd = 0; + hStereoDft->prev_sid_no_ipd_flag = 1; + hStereoDft->coh_fade_counter = 0; /* Xtalk classifier */ @@ -567,10 +588,6 @@ void stereo_enc_itd_init( void stereo_dft_enc_update( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ const int16_t max_bwidth /* i : maximum encoded bandwidth */ -#ifdef DEBUG_MODE_DFT - , - const int16_t res_cod_bits -#endif ) { int16_t i, k_offset; @@ -622,7 +639,7 @@ void stereo_dft_enc_update( hStereoDft->nbands_dmx = stereo_dft_band_config( hStereoDft->band_limits_dmx, 1, NFFT_inner, ENC ); /*Compute main parameters*/ - hStereoDft->gipd_band_max = dft_band_ipd[hStereoDft->hConfig->band_res][3]; + hStereoDft->gipd_band_max = dft_band_ipd[1][3]; hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->res_cod_mode[k_offset]]; hStereoDft->res_cod_line_max = (int16_t) ( 0.5f + ( hStereoDft->band_limits[hStereoDft->res_cod_band_max] - 1 ) * 2.f * hStereoDft->N / (float) ( hStereoDft->NFFT ) ); hStereoDft->res_cod_line_max = 8 * ( hStereoDft->res_cod_line_max / 8 ); @@ -670,7 +687,7 @@ void stereo_dft_enc_update( /*residual coding*/ if ( hStereoDft->hConfig->res_cod_mode ) { - tmp = res_cod_bits; + tmp = hStereoDft->res_cod_bits; nbits += tmp; fprintf( stderr, "\t Res cod.: %.2f kbps\n", tmp * input_Fs / ( 1000.f * input_frame ) ); } @@ -695,17 +712,17 @@ void stereo_dft_enc_destroy( { if ( ( *hStereoDft )->hConfig != NULL ) { - count_free( ( *hStereoDft )->hConfig ); + free( ( *hStereoDft )->hConfig ); ( *hStereoDft )->hConfig = NULL; } if ( ( *hStereoDft )->hItd != NULL ) { - count_free( ( *hStereoDft )->hItd ); + free( ( *hStereoDft )->hItd ); ( *hStereoDft )->hItd = NULL; } - count_free( *hStereoDft ); + free( *hStereoDft ); *hStereoDft = NULL; return; @@ -739,7 +756,7 @@ void stereo_dft_enc_analyze( int16_t trigo_step; - wmops_sub_start( "DFT_analysis" ); + push_wmops( "DFT_analysis" ); /*-----------------------------------------------------------------* * Initialization @@ -863,7 +880,7 @@ void stereo_dft_enc_analyze( } } - wmops_sub_end(); + pop_wmops(); return; } @@ -939,7 +956,7 @@ float stereo_dft_enc_synthesize( win = hStereoDft->win; win_ana = hStereoDft->win_ana; - wmops_sub_start( "DFT_synth_fs" ); + push_wmops( "DFT_synth_fs" ); } else if ( output_sampling_rate == INT_FS_12k8 ) { @@ -956,7 +973,7 @@ float stereo_dft_enc_synthesize( win = hStereoDft->win_12k8; win_ana = hStereoDft->win_ana_12k8; - wmops_sub_start( "DFT_synth_12k8" ); + push_wmops( "DFT_synth_12k8" ); } else if ( output_sampling_rate == 16000 ) { @@ -973,13 +990,13 @@ float stereo_dft_enc_synthesize( { mem = hStereoDft->output_mem_dmx_16k_shb; - wmops_sub_start( "DFT_synth_16k_shb" ); + push_wmops( "DFT_synth_16k_shb" ); } else { mem = hStereoDft->output_mem_dmx_16k; - wmops_sub_start( "DFT_synth_16k" ); + push_wmops( "DFT_synth_16k" ); } win = hStereoDft->win_16k; win_ana = hStereoDft->win_ana_16k; @@ -999,7 +1016,7 @@ float stereo_dft_enc_synthesize( win = hStereoDft->win_32k; win_ana = hStereoDft->win_ana_32k; - wmops_sub_start( "DFT_synth_32k" ); + push_wmops( "DFT_synth_32k" ); } else if ( output_sampling_rate == 8000 ) { @@ -1016,7 +1033,7 @@ float stereo_dft_enc_synthesize( win = hStereoDft->win_8k; win_ana = hStereoDft->win_ana_8k; - wmops_sub_start( "DFT_synth_8k" ); + push_wmops( "DFT_synth_8k" ); } else { @@ -1212,7 +1229,7 @@ float stereo_dft_enc_synthesize( } #endif - wmops_sub_end(); + pop_wmops(); return ( nrg ); } @@ -1226,8 +1243,10 @@ float stereo_dft_enc_synthesize( *-------------------------------------------------------------------------*/ void stereo_dft_enc_process( - CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - const int16_t input_frame /* i : input frame length */ + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const int16_t vad_flag_dtx[], /* i: VAD dtx flags */ + const int16_t vad_hover_flag[], /* i: VAD hangover flags */ + const int16_t input_frame /* i : input frame length */ ) { int16_t i, j, b; @@ -1269,7 +1288,7 @@ void stereo_dft_enc_process( /* Initialization */ k_offset = STEREO_DFT_OFFSET; /*Add an offset at encoder*/ - hStereoDft->gipd_band_max = dft_band_ipd[hStereoDft->band_res[k_offset]][3]; + hStereoDft->gipd_band_max = dft_band_ipd[1][3]; hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->res_cod_mode[k_offset]]; hStereoDft->res_cod_line_max = (int16_t) ( 0.5f + ( hStereoDft->band_limits[hStereoDft->res_cod_band_max] - 1 ) * 2.f * input_frame / (float) ( hStereoDft->NFFT ) ); hStereoDft->res_cod_line_max = 8 * ( hStereoDft->res_cod_line_max / 8 ); @@ -1297,8 +1316,7 @@ void stereo_dft_enc_process( if ( hStereoDft->hConfig->itd_mode ) #endif { - stereo_dft_enc_compute_itd( hCPE, pDFT_L, pDFT_R, k_offset, input_frame, bin_nrgL, bin_nrgR ); - + stereo_dft_enc_compute_itd( hCPE, pDFT_L, pDFT_R, k_offset, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL, bin_nrgR ); if ( hCPE->element_mode == IVAS_CPE_MDCT ) { return; @@ -1371,6 +1389,21 @@ void stereo_dft_enc_process( /* DFT stereo parameters */ stereo_dft_enc_compute_prm( hStereoDft, pDFT_L, pDFT_R, k_offset, 1, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->vad_flag, bin_nrgL, bin_nrgR, dot_prod_nrg_ratio ); + if ( vad_flag_dtx[0] == 0 ) + { + if ( hCPE->hStereoCng->cng_counter == 0 && !hCPE->hStereoCng->first_SID_after_TD ) + { + hStereoDft->sid_gipd = hStereoDft->prev_sid_gipd; + hStereoDft->no_ipd_flag = hStereoDft->prev_sid_no_ipd_flag; + } + + if ( hCPE->hStereoCng->cng_counter > ITD_SID_PREV_FRAMES ) + { + hStereoDft->prev_sid_gipd = hStereoDft->sid_gipd; + hStereoDft->prev_sid_no_ipd_flag = hStereoDft->no_ipd_flag; + } + } + /*----------------------------------------------------------------* * UNCLR classifier (detection of uncorrelated L and R channels) *----------------------------------------------------------------*/ @@ -1427,7 +1460,7 @@ void stereo_dft_enc_process( } } - if ( b < hStereoDft->res_cod_band_max ) + if ( b < hStereoDft->res_cod_band_max && vad_flag_dtx[0] ) { #ifdef DEBUGGING assert( hStereoDft->nbands == hStereoDft->nbands_dmx && "Don't use coarser stereo parameter resolution for residual coding bitrates!" ); @@ -1643,9 +1676,11 @@ void stereo_dft_enc_process( sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; } + sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); - wL = 0.5f * max( sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) - sqrtf( sum_nrg_Mid ), 0 ) / sqrtf( sum_nrg_L2 + EPSILON ); + wL = 0.5f * max( sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) - sqrtf( sum_nrg_Mid ), 0 ) * inv_sqrt( sum_nrg_L2 + EPSILON ); wS = 1; + if ( hStereoDft->res_cod_sw_flag ) { wL *= ( 1 - hStereoDft->switch_fade_factor ); @@ -1707,7 +1742,7 @@ static void stereo_dft_enc_get_res_cod_mode_flag( g = fabsf( hStereoDft->side_gain[(k_offset) *STEREO_DFT_BAND_MAX + b] ); *res_dmx_ratio = max( hStereoDft->res_cod_NRG_S[b] / ( hStereoDft->res_cod_NRG_S[b] + ( 1 - g ) * ( 1 - g ) * hStereoDft->res_cod_NRG_M[b] + 1 ), *res_dmx_ratio ); } - check_bounds( res_dmx_ratio, 0, 1 ); /*should always be satisfied*/ + *res_dmx_ratio = check_bounds( *res_dmx_ratio, 0, 1 ); /*should always be satisfied*/ /*Calculate the total energy of RES and DMX*/ dmx_res_all = res_nrg_all_curr + dmx_nrg_all_curr; @@ -1898,7 +1933,7 @@ void stereo_dft_enc_res( panning_gain_min = 1.f - fabsf( panning_gain ); in_phase_ratio = ( panning_gain_min * panning_gain_min * hStereoDft->res_cod_NRG_M[b] ) / ( panning_gain_min * panning_gain_min * hStereoDft->res_cod_NRG_M[b] + hStereoDft->res_cod_NRG_S[b] + 1 ); - check_bounds( &in_phase_ratio, 0, 1 ); + in_phase_ratio = check_bounds( in_phase_ratio, 0, 1 ); res_cod_gain[b] = in_phase_ratio * STEREO_DFT_RES_COD_SNR_MIN + ( 1 - in_phase_ratio ) * STEREO_DFT_RES_COD_SNR_MAX; /*get the maximum through bands*/ @@ -1923,7 +1958,7 @@ void stereo_dft_enc_res( dbgwrite( &max_snr, sizeof( float ), 1, 1, "./res/stereo_dft_res_cod_target_snr.dat" ); #endif - wmops_sub_start( "residual_encode" ); + push_wmops( "residual_encode" ); /* residual encoding */ ECSQ_init_instance( &ecsq_inst, 0 /*dummy index*/, &range_uni_enc_state ); @@ -2001,7 +2036,7 @@ void stereo_dft_enc_res( } #endif - wmops_sub_end(); + pop_wmops(); #ifdef DEBUG_MODE_DFT { @@ -2315,9 +2350,9 @@ void stereo_dft_enc_write_BS( if ( core_brate == SID_2k40 ) { - stereo_dft_enc_sid_calc_coh( hStereoDft, hCPE->hStereoCng->coh_crossfade, &hCPE->hStereoCng->td_active, &hCPE->hStereoCng->first_SID, cohBand ); + stereo_dft_enc_sid_calc_coh( hStereoDft, hCPE->hStereoCng->prev_cohBand, &hCPE->hStereoCng->td_active, &hCPE->hStereoCng->first_SID, cohBand ); - if ( *nb_bits <= ( ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 ) ) + if ( *nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 ) ) { if ( hStereoDft->hItd->itd[k_offset] != 0 ) { @@ -2393,7 +2428,7 @@ void stereo_dft_enc_write_BS( nb += STEREO_DFT_GIPD_NBITS; } } - else if ( *nb_bits <= ( ( IVAS_SID_4k4 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_FLAG_BITS - STEREO_DFT_SID_GIPD_NBITS ) ) + else if ( *nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_FLAG_BITS - STEREO_DFT_SID_GIPD_NBITS ) ) { push_indice( hBstr, IND_STEREO_DFT_NO_IPD_FLAG, hStereoDft->no_ipd_flag, STEREO_DFT_FLAG_BITS ); nb += STEREO_DFT_FLAG_BITS; /*IPD mode flag: 1bit*/ @@ -2412,7 +2447,6 @@ void stereo_dft_enc_write_BS( #endif ( *nb_bits ) += nb; - /*----------------------------------------------------------------* * Residual prediction *----------------------------------------------------------------*/ @@ -2565,8 +2599,10 @@ static void stereo_dft_enc_compute_prm( float sum_energy_L, sum_energy_R; float g, c; float abs_L_R; + float abs_L_R2; float gain_IPD; float sub_nrg_DMX[STEREO_DFT_BAND_MAX]; + float sub_nrg_DMX2; float sub_nrg_L[STEREO_DFT_BAND_MAX]; float sub_nrg_R[STEREO_DFT_BAND_MAX]; float diff_ipd; @@ -2580,6 +2616,9 @@ static void stereo_dft_enc_compute_prm( float sum_past_dot_prod_abs, sum_past_dot_prod_abs2; float sum_past_nrg_dmx; int16_t pos; + float pIpd[STEREO_DFT_BAND_MAX]; + float ipd_smooth[STEREO_DFT_BAND_MAX]; + float ipd_mean_change; /*------------------------------------------------------------------* * Initialization @@ -2592,7 +2631,6 @@ static void stereo_dft_enc_compute_prm( set_f( sub_nrg_L, 0, STEREO_DFT_BAND_MAX ); set_f( sub_nrg_R, 0, STEREO_DFT_BAND_MAX ); - pSideGain = hStereoDft->side_gain + k_offset * STEREO_DFT_BAND_MAX; pgIpd = hStereoDft->gipd + k_offset; pPredGain = hStereoDft->res_pred_gain + k_offset * STEREO_DFT_BAND_MAX; @@ -2601,6 +2639,7 @@ static void stereo_dft_enc_compute_prm( sum_energy_R = EPSILON; sum_dot_prod_real = EPSILON; sum_dot_prod_img = EPSILON; + sub_nrg_DMX2 = 0.f; #ifdef DEBUG_MODE_DFT sum_nrg_L = EPSILON; sum_nrg_R = EPSILON; @@ -2630,10 +2669,10 @@ static void stereo_dft_enc_compute_prm( pNrgL = bin_nrgL; pNrgR = bin_nrgR; - sum_nrg_L2 = 0; - sum_nrg_R2 = 0; - dot_prod_real2 = 0; - dot_prod_img2 = 0; + sum_nrg_L2 = EPSILON; + sum_nrg_R2 = EPSILON; + dot_prod_real2 = EPSILON; + dot_prod_img2 = EPSILON; for ( i = hStereoDft->band_limits_dmx[b2]; i < hStereoDft->band_limits_dmx[b2 + 1]; i++ ) { @@ -2644,6 +2683,19 @@ static void stereo_dft_enc_compute_prm( dot_prod_real2 += pDFT_L[2 * i] * pDFT_R[2 * i] + pDFT_L[2 * i + 1] * pDFT_R[2 * i + 1]; dot_prod_img2 += pDFT_L[2 * i + 1] * pDFT_R[2 * i] - pDFT_L[2 * i] * pDFT_R[2 * i + 1]; } + abs_L_R2 = sqrtf( dot_prod_real2 * dot_prod_real2 + dot_prod_img2 * dot_prod_img2 ); + sub_nrg_DMX2 = sum_nrg_L2 + sum_nrg_R2 + 2 * abs_L_R2; + + if ( b2 < hStereoDft->gipd_band_max ) + { + hStereoDft->dot_prod_real_smooth[b2] = 0.5f * hStereoDft->dot_prod_real_smooth[b2] + 0.5f * dot_prod_real2; + hStereoDft->dot_prod_img_smooth[b2] = 0.5f * hStereoDft->dot_prod_img_smooth[b2] + 0.5f * dot_prod_img2; + pIpd[b2] = (float) atan2( hStereoDft->dot_prod_img_smooth[b2], hStereoDft->dot_prod_real_smooth[b2] ); + + ipd_smooth[b2] = stereo_dft_calc_mean_bipd( &pIpd[b2], hStereoDft->ipd_buf[b2] ); + + gain_IPD += ( sum_nrg_L2 + sum_nrg_R2 + 2 * dot_prod_real2 ) / sub_nrg_DMX2 / hStereoDft->gipd_band_max; + } sum_past_nrgL2 = EPSILON; sum_past_nrgR2 = EPSILON; @@ -2798,17 +2850,16 @@ static void stereo_dft_enc_compute_prm( } - if ( b < hStereoDft->gipd_band_max ) - { - gain_IPD += ( sum_nrg_L + sum_nrg_R + 2 * dot_prod_real ) / sub_nrg_DMX[b] / hStereoDft->gipd_band_max; - } - - if ( b == hStereoDft->gipd_band_max - 1 ) + if ( b2 == hStereoDft->gipd_band_max ) { + ipd_mean_change = stereo_dft_calc_mean_ipd_change( pIpd, ipd_smooth, hStereoDft->gipd_band_max ); hStereoDft->sum_dot_prod_real = ( 1.f - hStereoDft->sfm ) * hStereoDft->sum_dot_prod_real + hStereoDft->sfm * sum_dot_prod_real; hStereoDft->sum_dot_prod_img = ( 1.f - hStereoDft->sfm ) * hStereoDft->sum_dot_prod_img + hStereoDft->sfm * sum_dot_prod_img; pgIpd[0] = (float) atan2( hStereoDft->sum_dot_prod_img, hStereoDft->sum_dot_prod_real ); + + stereo_dft_gipd_stabilization( &pgIpd[0], hStereoDft->prev_gipd, ipd_mean_change ); + hStereoDft->prev_gipd = pgIpd[0]; } } @@ -2943,7 +2994,11 @@ static void stereo_dft_enc_compute_prm( /* parameters for bred0 <= b < bpred1 are estimated from parameters of the remaining bands with ptrans0 <= b < btrans1. */ - bpred1 = ( hStereoDft->nbands > 10 ) ? hStereoDft->nbands - 2 : hStereoDft->nbands; + bpred1 = ( hStereoDft->nbands > 10 ) ? STEREO_DFT_RES_PRED_BAND_MAX - 2 : hStereoDft->nbands; + if ( hStereoDft->band_res[k_offset] == STEREO_DFT_BAND_RES_LOW ) + { + bpred1 = min( bpred1, 6 ); + } bpred0 = bpred1 - STEREO_DFT_RES_PRED_BAND_MIN_CONST; /* get estimate (currently the maximal index) */ @@ -2963,7 +3018,7 @@ static void stereo_dft_enc_compute_prm( if ( hStereoDft->reverb_flag && hStereoDft->nbands > 10 ) /*SWB and FB*/ { - for ( b = hStereoDft->nbands - 1; b >= hStereoDft->nbands - 2; b-- ) + for ( b = STEREO_DFT_RES_PRED_BAND_MAX - 1; b >= STEREO_DFT_RES_PRED_BAND_MAX - 2; b-- ) { hStereoDft->res_pred_index_EC[b - STEREO_DFT_RES_PRED_BAND_MIN_CONST] = hStereoDft->res_pred_index_EC[b]; } @@ -3143,6 +3198,171 @@ static void res_pred_gain_mode_decision( } +/*------------------------------------------------------------------------- + * stereo_dft_calc_mean_bipd() + * + * Calculate mean of previous bandwise IPD values + *------------------------------------------------------------------------*/ + +static float stereo_dft_calc_mean_bipd( + float *pIpd, /* i: current bandwise IPD */ + float ipd_buf[STEREO_DFT_IPD_BUF_LEN] /* i/o: previous bandwise IPDs */ +) +{ + int16_t i; + float ipd_smooth; + float diff_to_last; + + assert( *pIpd <= EVS_PI && *pIpd >= -EVS_PI ); + + ipd_smooth = 0.f; + for ( i = 0; i < STEREO_DFT_IPD_BUF_LEN; i++ ) + { + if ( i == 0 ) + { + diff_to_last = ipd_buf[0]; + } + else + { + diff_to_last = fabsf( ipd_buf[i] - ipd_smooth ); + } + if ( diff_to_last > EVS_PI ) + { + if ( ipd_buf[i] > 0 ) + { + ipd_buf[i] -= 2 * EVS_PI; + } + else + { + ipd_buf[i] += 2 * EVS_PI; + } + } + ipd_smooth = ( i / (float) ( i + 1 ) ) * ipd_smooth + ( 1 / (float) ( i + 1 ) ) * ipd_buf[i]; + if ( ipd_smooth < -EVS_PI ) + { + ipd_smooth += 2 * EVS_PI; + } + else if ( ipd_smooth > EVS_PI ) + { + ipd_smooth -= 2 * EVS_PI; + } + } + + for ( i = 0; i < STEREO_DFT_IPD_BUF_LEN - 1; i++ ) + { + ipd_buf[i] = ipd_buf[i + 1]; + } + ipd_buf[STEREO_DFT_IPD_BUF_LEN - 1] = *pIpd; + +#ifdef DEBUG_MODE_DFT + dbgwrite( pIpd, sizeof( float ), 1, 1, "res/stereo_dft_bipd.pcm" ); + dbgwrite( &ipd_smooth, sizeof( float ), 1, 1, "res/stereo_dft_bipd_smooth.pcm" ); +#endif + + return ipd_smooth; +} + + +/*------------------------------------------------------------------------- + * stereo_dft_calc_mean_ipd_change() + * + * Calculate mean IPD change over all bands + *------------------------------------------------------------------------*/ + +static float stereo_dft_calc_mean_ipd_change( + float *pIpd, /* i: bandwise IPDs */ + float *ipd_smooth, /* i: mean of previous bandwise IPDs */ + int16_t gipd_band_max /* i: number of IPD bands */ +) +{ + int16_t b; + float ipd_mean_change; + float ipd_change[STEREO_DFT_BAND_MAX]; + + ipd_mean_change = 0.f; + for ( b = 0; b < gipd_band_max; b++ ) + { + ipd_change[b] = fabsf( pIpd[b] - ipd_smooth[b] ); + if ( ipd_change[b] > EVS_PI ) + { + ipd_change[b] = 2 * EVS_PI - ipd_change[b]; + } + ipd_mean_change += ipd_change[b]; + } + ipd_mean_change /= gipd_band_max; + +#ifdef DEBUG_MODE_DFT + dbgwrite( ipd_change, sizeof( float ), hStereoDft->gipd_band_max, 1, "res/stereo_dft_ipd_change.pcm" ); + dbgwrite( &ipd_mean_change, sizeof( float ), 1, 1, "res/stereo_dft_ipd_mean_change.pcm" ); +#endif + + return ipd_mean_change; +} + + +/*------------------------------------------------------------------------- + * stereo_dft_gipd_stabilization() + * + * stabilize global IPD based on stability of bandwise IPDs + *------------------------------------------------------------------------*/ + +static void stereo_dft_gipd_stabilization( + float *pgIpd, /* i/o: global IPD to be stabilized */ + float prev_gipd, /* i: previous global IPD */ + float ipd_mean_change /* i: mean of previous bandwise IPDs */ +) +{ + float diff_gipd; + + if ( ipd_mean_change < 0.3f ) + { + *pgIpd = prev_gipd; + } + else + { + diff_gipd = fabsf( *pgIpd - prev_gipd ); + if ( diff_gipd > EVS_PI ) + { + diff_gipd = 2 * EVS_PI - diff_gipd; + } + if ( diff_gipd > ipd_mean_change ) + { + if ( *pgIpd > prev_gipd ) + { + if ( *pgIpd - prev_gipd < EVS_PI ) + { + *pgIpd = prev_gipd + ipd_mean_change; + } + else + { + *pgIpd = prev_gipd - ipd_mean_change; + if ( *pgIpd < -EVS_PI ) + { + *pgIpd += 2 * EVS_PI; + } + } + } + else + { + if ( prev_gipd - *pgIpd < EVS_PI ) + { + *pgIpd = prev_gipd - ipd_mean_change; + } + else + { + *pgIpd = prev_gipd + ipd_mean_change; + if ( *pgIpd > EVS_PI ) + { + *pgIpd -= 2 * EVS_PI; + } + } + } + } + } + return; +} + + /*------------------------------------------------------------------------- * stereo_dft_enc_get_nipd_flag() * diff --git a/lib_enc/ivas_stereo_dft_enc_itd.c b/lib_enc/ivas_stereo_dft_enc_itd.c index 4c1967c2ad630f573cae5d2d50d9bfeaf97b8423..f52d67a47a328fe47fcdc6ccf4d2c167dc7564f4 100644 --- a/lib_enc/ivas_stereo_dft_enc_itd.c +++ b/lib_enc/ivas_stereo_dft_enc_itd.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -45,7 +45,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -66,7 +66,9 @@ #define SUBDIV ( 2 * STEREO_DFT_ITD_MAX_ANA / L_SAMPLES ) #define DENOM 0.05f -#define XSPEC_ALPHA ( 1.f / 32 ) +#define XSPEC_ALPHA ( 1.f / 32 ) +#define CORR_FILT 0.8f +#define CORR_RESET_FRAMES_MAX 20 #define ITD_VAD_NOISE_INIT_FRAMES 30 #define ITD_VAD_THRSHOLD 0.001f @@ -446,7 +448,6 @@ static float calc_mean_E_ratio( ITD_DATA_HANDLE hItd, int16_t nbands, int16_t band_limits[], - const int16_t NFFT, const float sfm, const float nrg_L[STEREO_DFT_N_32k_ENC / 2], const float nrg_R[STEREO_DFT_N_32k_ENC / 2], @@ -467,7 +468,7 @@ static float calc_mean_E_ratio( grand_sum_xcorr_img = 0.0f; /*take bands up to 32kHz bandwidth as ITD is always calculated at 32kHz sampling rate*/ - nbands -= ( NFFT > STEREO_DFT_N_32k_ENC ); + nbands -= ( band_limits[nbands] > STEREO_DFT_N_32k_ENC / 2 ); sum_Er = 0; for ( b = 0; b < nbands; b++ ) @@ -723,6 +724,8 @@ void stereo_dft_enc_compute_itd( float *DFT_R, const int16_t k_offset, const int16_t input_frame, + const int16_t vad_flag_dtx[], + const int16_t vad_hover_flag[], float *bin_nrgL, float *bin_nrgR ) { @@ -769,6 +772,8 @@ void stereo_dft_enc_compute_itd( const float *dft_trigo32k; float trigo_enc[STEREO_DFT_N_32k_ENC / 2 + 1]; + float cng_xcorr_filt; + if ( hCPE->element_mode == IVAS_CPE_DFT ) { hStereoDft = hCPE->hStereoDft; @@ -927,6 +932,8 @@ void stereo_dft_enc_compute_itd( vad_flag_itd = stereo_dft_enc_itd_vad( hItd->E_band_n, &( hItd->vad_frm_cnt ), Spd_L, Spd_R, &mssnr ); + vad_flag_itd = vad_flag_itd && vad_flag_dtx[0]; + if ( sum_nrg_L < EPSILON ) { sfm_L = 0; @@ -1054,17 +1061,81 @@ void stereo_dft_enc_compute_itd( if ( hCPE->hCoreCoder[0]->Opt_DTX_ON && hCPE->element_mode == IVAS_CPE_DFT ) { - if ( hCPE->hCoreCoder[0]->last_core_brate == SID_2k40 || hCPE->hCoreCoder[0]->last_core_brate == FRAME_NO_DATA || hCPE->hStereoCng->first_SID_after_TD ) + if ( hCPE->hFrontVad[0] != NULL ) + { + /* Determine if we are in hangover */ + if ( vad_hover_flag[0] && vad_hover_flag[1] ) + { + /* Determine if we are in the first DTX hangover frame (also triggers for VAD hangover frame) */ + if ( hStereoDft->resetFrames > CORR_RESET_FRAMES_MAX ) + { + /* Reset cross spectrum when there is hangover */ + set_f( hStereoDft->xspec_smooth, 0.0f, STEREO_DFT_N_32k_ENC ); + hStereoDft->resetFrames = 0; + hStereoDft->currentNumUpdates = 0; + /* Expected minimum number of updates including first SID */ + hStereoDft->expectedNumUpdates = 1 + min( hCPE->hFrontVad[0]->rem_dtx_ho, hCPE->hFrontVad[1]->rem_dtx_ho ); + } + else if ( hStereoDft->currentNumUpdates >= hStereoDft->expectedNumUpdates ) + { + hStereoDft->expectedNumUpdates += 1 + min( hCPE->hFrontVad[0]->rem_dtx_ho, hCPE->hFrontVad[1]->rem_dtx_ho ); + } + cng_xcorr_filt = max( min( CORR_FILT, 10.0f * CORR_FILT / ( hStereoDft->expectedNumUpdates + hStereoDft->currentNumUpdates ) ), sfm_L ); + hStereoDft->currentNumUpdates++; + for ( i = 1; i < NFFT / 2; i++ ) + { + /* Low pass filter cross L/R power spectrum */ + hStereoDft->xspec_smooth[2 * i] = ( 1.f - cng_xcorr_filt ) * hStereoDft->xspec_smooth[2 * i] + cng_xcorr_filt * xcorr[2 * i]; + hStereoDft->xspec_smooth[2 * i + 1] = ( 1.f - cng_xcorr_filt ) * hStereoDft->xspec_smooth[2 * i + 1] + cng_xcorr_filt * xcorr[2 * i + 1]; + + /* Low pass filter L/R power spectrum */ + /* Calculate coherence as cross spectral density divided by L*R power spectrum */ + hStereoDft->Spd_L_smooth[i] = ( 1.f - cng_xcorr_filt ) * hStereoDft->Spd_L_smooth[i] + cng_xcorr_filt * Spd_L[i]; + hStereoDft->Spd_R_smooth[i] = ( 1.f - cng_xcorr_filt ) * hStereoDft->Spd_R_smooth[i] + cng_xcorr_filt * Spd_R[i]; + } + } + else if ( vad_flag_dtx[0] == 0 ) + { + hStereoDft->resetFrames = 0; + } + else + { + if ( hStereoDft->resetFrames < CORR_RESET_FRAMES_MAX + 1 ) + { + hStereoDft->resetFrames++; + } + if ( !vad_hover_flag[0] && !vad_hover_flag[1] ) + { + hStereoDft->expectedNumUpdates = hStereoDft->currentNumUpdates; + } + } + } + if ( ( vad_flag_dtx[0] == 0 ) || ( hCPE->hFrontVad[0] == NULL && ( hCPE->hCoreCoder[0]->last_core_brate == SID_2k40 || hCPE->hCoreCoder[0]->last_core_brate == FRAME_NO_DATA ) ) || hCPE->hStereoCng->first_SID_after_TD ) { + if ( vad_flag_dtx[0] == 0 ) + { + /* expectedNumUpdates updated after call to dtx() in SID frames */ + cng_xcorr_filt = max( min( CORR_FILT, 10.0f * CORR_FILT / ( hStereoDft->expectedNumUpdates + hStereoDft->currentNumUpdates ) ), sfm_L ); + hStereoDft->currentNumUpdates++; + hStereoDft->sfm = cng_xcorr_filt; + } + else /* use sfm for active frames */ + { + cng_xcorr_filt = sfm_L; + } + + /* Copy state of xspec_smooth to xcorr_smooth in first CNG frame */ + if ( hCPE->hStereoCng->cng_counter == 0 && vad_flag_dtx[0] == 0 ) + { + mvr2r( hStereoDft->xspec_smooth, hItd->xcorr_smooth, NFFT ); + } for ( i = 1; i < NFFT / 2; i++ ) { /* Low pass filter cross L/R power spectrum */ hStereoDft->xspec_smooth[2 * i] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->xspec_smooth[2 * i] + XSPEC_ALPHA * xcorr[2 * i]; hStereoDft->xspec_smooth[2 * i + 1] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->xspec_smooth[2 * i + 1] + XSPEC_ALPHA * xcorr[2 * i + 1]; - - hItd->xcorr_smooth[2 * i] = ( 1.f - sfm_L ) * hItd->xcorr_smooth[2 * i] + sfm_L * xcorr[2 * i]; - hItd->xcorr_smooth[2 * i + 1] = ( 1.f - sfm_L ) * hItd->xcorr_smooth[2 * i + 1] + sfm_L * xcorr[2 * i + 1]; - + hItd->xcorr_smooth[2 * i] = ( 1.f - cng_xcorr_filt ) * hItd->xcorr_smooth[2 * i] + cng_xcorr_filt * xcorr[2 * i]; + hItd->xcorr_smooth[2 * i + 1] = ( 1.f - cng_xcorr_filt ) * hItd->xcorr_smooth[2 * i + 1] + cng_xcorr_filt * xcorr[2 * i + 1]; tmpf1 = sqrtf( hItd->xcorr_smooth[i * 2] * hItd->xcorr_smooth[i * 2] + hItd->xcorr_smooth[i * 2 + 1] * hItd->xcorr_smooth[i * 2 + 1] ); tmpf1 += EPSILON; tmpf2 = tmpf1; @@ -1238,7 +1309,7 @@ void stereo_dft_enc_compute_itd( /*calculate mean E ratio of main to background signal for cohSNR*/ if ( hCPE->element_mode == IVAS_CPE_DFT ) { - mEr = calc_mean_E_ratio( hItd, hStereoDft->nbands, hStereoDft->band_limits, hStereoDft->NFFT, sfm_L, pNrgL, pNrgR, &total_mEr ); + mEr = calc_mean_E_ratio( hItd, hStereoDft->nbands, hStereoDft->band_limits, sfm_L, pNrgL, pNrgR, &total_mEr ); } else { @@ -1247,7 +1318,7 @@ void stereo_dft_enc_compute_itd( set_s( band_limits, 0, STEREO_DFT_BAND_MAX + 1 ); set_band_limits( &nbands, band_limits, hCPE->hStereoMdct->hDft_ana->NFFT ); - mEr = calc_mean_E_ratio( hItd, nbands, band_limits, hCPE->hStereoMdct->hDft_ana->NFFT, sfm_L, pNrgL, pNrgR, &total_mEr ); + mEr = calc_mean_E_ratio( hItd, nbands, band_limits, sfm_L, pNrgL, pNrgR, &total_mEr ); } /*calculate total cohSNR for frame in dB*/ @@ -1557,7 +1628,7 @@ void stereo_dft_enc_compute_itd( /* Update memory */ hItd->prev_itd = itd; - check_bounds_s( &itd, -STEREO_DFT_ITD_MAX, STEREO_DFT_ITD_MAX ); + itd = check_bounds_s( itd, -STEREO_DFT_ITD_MAX, STEREO_DFT_ITD_MAX ); /*Inverse the time diff*/ hItd->itd[k_offset] = -1.f * itd; diff --git a/lib_enc/ivas_stereo_dft_td_itd.c b/lib_enc/ivas_stereo_dft_td_itd.c index 8f1f653b18ba3f4033ca8834df18f7c2a43173bd..b7fb95422f3136080892b0df097b65719ef747c6 100644 --- a/lib_enc/ivas_stereo_dft_td_itd.c +++ b/lib_enc/ivas_stereo_dft_td_itd.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -47,7 +47,7 @@ #ifdef DEBUG_PLOT #include "deb_out.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -161,8 +161,8 @@ static void stereo_td_channel_extrapolate( g = dot_lead_lag / dot_lead_lead; nsr = 1 - ( ( dot_lead_lag * dot_lead_lag ) / ( dot_lead_lead * dot_lag_lag ) ); - check_bounds( &g, -1, 1.5f ); - check_bounds( &nsr, 0.0f, 1 ); + g = check_bounds( g, -1, 1.5f ); + nsr = check_bounds( nsr, 0.0f, 1 ); g_lpc = sqrtf( nsr ); /* rectangular window */ @@ -383,8 +383,10 @@ void stereo_td_itd( * ---------------------------------------------------------------*/ void stereo_td_itd_mdct_stereo( - CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ - const int16_t input_frame /* i : frame length */ + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ + const int16_t vad_flag_dtx[], /* i: VAD dtx flags */ + const int16_t vad_hover_flag[], /* i: VAD hangover flags */ + const int16_t input_frame /* i : frame length */ ) { int16_t i; @@ -411,7 +413,7 @@ void stereo_td_itd_mdct_stereo( stereo_dft_enc_analyze( hCPE->hCoreCoder, CPE_CHANNELS, input_frame, NULL, hStereoMdct, DFT, hCPE->input_mem ); /*call ITD function*/ - stereo_dft_enc_compute_itd( hCPE, DFT[0], DFT[1], STEREO_DFT_OFFSET, input_frame, bin_nrgL, bin_nrgR ); + stereo_dft_enc_compute_itd( hCPE, DFT[0], DFT[1], STEREO_DFT_OFFSET, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL, bin_nrgR ); /* Time Domain ITD compensation using extrapolation */ #ifdef DEBUG_MODE_DFT diff --git a/lib_enc/ivas_stereo_dmx_evs.c b/lib_enc/ivas_stereo_dmx_evs.c index af3430766a0085ccd4fb4117811db5a8658b14a0..a5c0fe147f0055724024771e5133507e08ccab36 100644 --- a/lib_enc/ivas_stereo_dmx_evs.c +++ b/lib_enc/ivas_stereo_dmx_evs.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -63,6 +63,8 @@ #define STEREO_DMX_EVS_DMX_EGY_FORGETTING 0.25f #define STEREO_DMX_EVS_CORR_FORGETTING 0.78f +#define Q_BAND 0.25f + /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ @@ -150,61 +152,191 @@ static void calc_poc( { int16_t i, n1, n2; int16_t n0, *itdLR; - const float *c, *s; + const float *s; float *P; float tmp1, tmp2, Lr, Li, Rr, Ri, gamma, igamma, iN; - float specPOr[L_FRAME48k], specPOi[L_FRAME48k]; + + float specPOr[L_FRAME48k / 2 + 1], specPOi[L_FRAME48k / 2]; /*real and imaginary values for searching phase angle*/ float tmpPOC1[L_FRAME48k], tmpPOC2[L_FRAME48k]; float rfft_buf[L_FRAME48k]; int16_t step, bias; + int16_t mult_angle; + int16_t j; + int16_t end; + + int16_t cos_step, cos_max; + float eps_cos, eps_sin, EPS; /* Initialization */ iN = 1.0f / (float) input_frame; - c = hPOC->sin + ( input_frame >> 2 ); s = hPOC->sin; P = hPOC->P; n0 = input_frame / 2; itdLR = hPOC->itdLR; + igamma = STEREO_DMX_EVS_POC_GAMMA * iN; gamma = 1.0f - igamma; - set_zero( tmpPOC1, L_FRAME48k ); - set_zero( tmpPOC2, L_FRAME48k ); + + + step = 1; + bias = 0; + cos_step = 2; + cos_max = n0; + mult_angle = 3; if ( input_frame == L_FRAME16k ) { step = 3; bias = 1; + cos_step = 4; + cos_max = input_frame; + mult_angle = 2; /*****/ } - else + if ( input_frame == L_FRAME32k ) { - step = 1; - bias = 0; + mult_angle = 2; } - specPOr[0] = sign( specLr[0] ) * sign( specRr[0] ) * wnd[bias]; + end = min( n0, 320 ); + specPOr[0] = sign( specLr[0] * specRr[0] ) * wnd[bias]; specPOi[0] = 0.0f; + EPS = hPOC->eps; + if ( input_frame == L_FRAME48k ) + { + for ( i = 1; i < n0 / 2; i++ ) + { + eps_cos = s[cos_max - i * cos_step /*cos_max - i_for*/] * EPS; + eps_sin = s[i * cos_step /*i_for*/] * EPS; + Lr = specLr[i] + specRr[i] * eps_cos + specRi[i] * eps_sin; + Li = specLi[i] - specRr[i] * eps_sin + specRi[i] * eps_cos; + Rr = specRr[i] + specLr[i] * eps_cos + specLi[i] * eps_sin; + Ri = specRi[i] - specLr[i] * eps_sin + specLi[i] * eps_cos; + + specPOr[i] = ( Lr * Rr + Li * Ri ); + specPOi[i] = ( Lr * Ri - Li * Rr ); + j = n0 - i; + if ( j < 320 ) + { + Lr = specLr[j] - specRr[j] * eps_cos + specRi[j] * eps_sin; + Li = specLi[j] - specRr[j] * eps_sin - specRi[j] * eps_cos; + Rr = specRr[j] - specLr[j] * eps_cos + specLi[j] * eps_sin; + Ri = specRi[j] - specLr[j] * eps_sin - specLi[j] * eps_cos; - for ( i = 1; i < n0; i++ ) + specPOr[j] = ( Lr * Rr + Li * Ri ); + specPOi[j] = ( Lr * Ri - Li * Rr ); + } + } + } + else /* 16kHz and 32 kHz*/ { - Lr = specLr[i]; - Li = specLi[i]; - Rr = specRr[i]; - Ri = specRi[i]; + for ( i = 1; i < n0 / 2; i++ ) + { + eps_cos = s[cos_max - i * cos_step /*cos_max - i_for*/] * EPS; + eps_sin = s[i * cos_step /*i_for*/] * EPS; + + Lr = specLr[i] + specRr[i] * eps_cos + specRi[i] * eps_sin; + Li = specLi[i] - specRr[i] * eps_sin + specRi[i] * eps_cos; + Rr = specRr[i] + specLr[i] * eps_cos + specLi[i] * eps_sin; + Ri = specRi[i] - specLr[i] * eps_sin + specLi[i] * eps_cos; + specPOr[i] = ( Lr * Rr + Li * Ri ); + specPOi[i] = ( Lr * Ri - Li * Rr ); + + j = n0 - i; + Lr = specLr[j] - specRr[j] * eps_cos + specRi[j] * eps_sin; + Li = specLi[j] - specRr[j] * eps_sin - specRi[j] * eps_cos; + Rr = specRr[j] - specLr[j] * eps_cos + specLi[j] * eps_sin; + Ri = specRi[j] - specLr[j] * eps_sin - specLi[j] * eps_cos; + specPOr[j] = ( Lr * Rr + Li * Ri ); + specPOi[j] = ( Lr * Ri - Li * Rr ); + } + } + { + /* i=n0/2*/ + Lr = specLr[i] + specRi[i] * EPS; + Li = specLi[i] - specRr[i] * EPS; + Rr = specRr[i] + specLi[i] * EPS; + Ri = specRi[i] - specLr[i] * EPS; + specPOr[i] = ( Lr * Rr + Li * Ri ); + specPOi[i] = ( Lr * Ri - Li * Rr ); + } + /* complex spectrum (specPOr[i], specPOi[i]) are placed on an unit circle without using srqt()*/ + for ( i = 1; i < 10; i++ ) /*search from 4 angles */ + { + tmp1 = wnd[i * step + bias] * gamma; - Lr += ( specRr[i] * c[i] + specRi[i] * s[i] ); - Li += ( -specRr[i] * s[i] + specRi[i] * c[i] ); - Rr += ( specLr[i] * c[i] + specLi[i] * s[i] ); - Ri += ( -specLr[i] * s[i] + specLi[i] * c[i] ); + specPOr[i] = sign( specPOr[i] ) * 0.866f * tmp1; /* low angles are more frequent for low frequency */ + specPOi[i] = sign( specPOi[i] ) * 0.5f * tmp1; + gamma -= igamma; + } + for ( ; i < n0 >> 4; i++ ) /*search from 4 angles */ + { + tmp1 = wnd[i * step + bias] * gamma * 0.7071f; - tmp1 = wnd[i * step + bias] * gamma / ( sqrtf( ( ( Lr * Lr + Li * Li ) ) * ( ( Rr * Rr + Ri * Ri ) ) ) + hPOC->eps ); + specPOr[i] = sign( specPOr[i] ) * tmp1; + specPOi[i] = sign( specPOi[i] ) * tmp1; /* low accuracy is adequate for low frequency */ + gamma -= igamma; + } - specPOr[i] = ( Lr * Rr + Li * Ri ) * tmp1; - specPOi[i] = ( Lr * Ri - Li * Rr ) * tmp1; + for ( ; i < n0 >> 3; i++ ) /* binary search from 8 angles */ + { + tmp1 = wnd[i * step + bias] * gamma; + if ( ( specPOr[i] - specPOi[i] ) * ( specPOr[i] + specPOi[i] ) > 0 ) + { + specPOr[i] = sign( specPOr[i] ) * tmp1 * /*0.923880f*/ s[120 * mult_angle]; /* cos(PI/8)*/ + specPOi[i] = sign( specPOi[i] ) * tmp1 * /*0.382683f*/ s[40 * mult_angle]; + } + else + { + specPOr[i] = sign( specPOr[i] ) * tmp1 * /*0.382683f*/ s[40 * mult_angle]; /* cos(PI*3/8)*/ + specPOi[i] = sign( specPOi[i] ) * tmp1 * /*0.923880f*/ s[120 * mult_angle]; + } + gamma -= igamma; + } + for ( ; i < end; i++ ) /* binary search from 16 angles */ + { + tmp1 = wnd[i * step + bias] * gamma; + if ( ( specPOr[i] - specPOi[i] ) * ( specPOr[i] + specPOi[i] ) > 0 ) + { + if ( ( specPOr[i] * 0.414213f - specPOi[i] ) * ( specPOr[i] * 0.414213f + specPOi[i] ) > 0 ) /*tan(PI/8)*/ + { + specPOr[i] = sign( specPOr[i] ) * tmp1 /*0.980785f */ * s[140 * mult_angle]; /* cos(PI/16)*/ + specPOi[i] = sign( specPOi[i] ) * tmp1 /*0.195090f */ * s[20 * mult_angle]; + } + else + { + specPOr[i] = sign( specPOr[i] ) * tmp1 /* 0.831470f */ * s[100 * mult_angle]; /*cos(PI*3/16)*/ + specPOi[i] = sign( specPOi[i] ) * tmp1 /* 0.555570f*/ * s[60 * mult_angle]; + } + } + else + { + if ( ( specPOr[i] - specPOi[i] * 0.414213f ) * ( specPOr[i] + specPOi[i] * 0.414213f ) > 0 ) /*tan(PI/8)*/ + { + specPOr[i] = sign( specPOr[i] ) * tmp1 /** 0.555570f*/ * s[60 * mult_angle]; /*cos(PI*5/16)*/ + specPOi[i] = sign( specPOi[i] ) * tmp1 /** 0.831470f*/ * s[100 * mult_angle]; + } + else + { + specPOr[i] = sign( specPOr[i] ) * tmp1 /** 0.195090f*/ * s[20 * mult_angle]; /*cos(PI*7/16)*/ + specPOi[i] = sign( specPOi[i] ) * tmp1 /** 0.980785f*/ * s[140 * mult_angle]; + } + } gamma -= igamma; } - specPOr[n0] = sign( specLr[i] ) * sign( specRr[i] ) * wnd[i * step + bias] * gamma; + + if ( i < n0 ) + { + gamma -= igamma * ( n0 - 320 ); + } + for ( ; i < n0; i++ ) /*neglect higher frequency bins when 48 kHz samplng*/ + { + specPOr[i] = 0.f; + specPOi[i] = 0.f; + } + specPOr[n0] = sign( specLr[n0] * specRr[n0] ) * wnd[i * step + bias] * gamma; + rfft_buf[0] = specPOr[0]; rfft_buf[1] = specPOr[n0]; @@ -305,7 +437,7 @@ static float find_poc_peak( itd_cand[0] = itd_cand[1] = 0; P = hPOC->P; - for ( i = 1; i < hPOC->shift_limit; i++ ) + for ( i = 1; i < hPOC->shift_limit; i++ ) /*find peaks of POC P[] with positive and negative ITD */ { if ( P[Lh - i] > Q[0] ) { @@ -340,7 +472,7 @@ static float find_poc_peak( Q[n] = ( 1.0f - ( cQ[n] / ( peak_range * 2 + 1 ) + eps2 ) / ( Q[n] + eps2 ) ); Q[n] = max( Q[n], 0.0f ); - if ( on[n] ) + if ( on[n] ) /*if channel n was active (likely to be preceding) in the previous frame*/ { tmpf = ( 0.3f - 0.2f * (float) abs( itd_cand[n] ) / (float) hPOC->shift_limit ) * peakQ[n]; if ( Q[n] < tmpf ) @@ -357,7 +489,7 @@ static float find_poc_peak( peakQ[n] = max( peakQ[n], Q[n] ); } - else + else /*if channel n was not active (not likely to be preceding) in the previous frame*/ { tmpf = ( 0.75f - 0.2f * (float) abs( itd_cand[n] ) / (float) hPOC->shift_limit ); @@ -374,20 +506,36 @@ static float find_poc_peak( } } - if ( on[0] && prev_off[0] ) + if ( ( on[0] && prev_off[0] ) && ( on[1] && prev_off[1] ) ) /*if both channels have newly detected as active (possibility of preceding), select channel by peakness Q[] of POC */ + { + *itd = ( Q[0] > Q[1] ) ? (float) itdLR[0] : (float) itdLR[1]; + } + else if ( ( on[0] && prev_off[0] ) && ( Q[0] > ( Q[1] - 0.1 ) ) ) /* if channel 0 becomes active, select channel 0*/ { *itd = (float) itdLR[0]; } - else if ( on[1] && prev_off[1] ) + else if ( ( on[1] && prev_off[1] ) && ( Q[1] > ( Q[0] - 0.1 ) ) ) /*if channel 1 becomes active, selsect channel 1*/ { *itd = (float) itdLR[1]; } - else + else if ( Q[0] > ( Q[1] + Q_BAND ) ) /* if no status change, use Q[]*/ + { + *itd = (float) itdLR[0]; + } + else if ( Q[1] > ( Q[0] + Q_BAND ) ) /* if no status change, use Q[]*/ + { + *itd = (float) itdLR[1]; + } + else if ( *itd == 0.0 ) /*if no channels are likely to be preceding, follow the status of the previous frame*/ + { + *itd = 0; + } + else /*follow the status of the previous frame*/ { *itd = ( *itd > 0 ) ? (float) itdLR[0] : (float) itdLR[1]; } - cconfidence = sqrtf( fabsf( Q[0] - Q[1] ) ); + cconfidence = sqrtf( fabsf( Q[0] - Q[1] ) ); /*higher value indicates higher confidence for one preceding channel*/ return hPOC->confidence = hPOC->confidence * STEREO_DMX_EVS_CORR_FORGETTING + cconfidence * ( 1.0f - STEREO_DMX_EVS_CORR_FORGETTING ); } @@ -699,7 +847,7 @@ ivas_error stereo_dmx_evs_init_encoder( input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); hStereoDmxEVS = NULL; - if ( ( hStereoDmxEVS = (STEREO_DMX_EVS_ENC_HANDLE) count_malloc( sizeof( STEREO_DMX_EVS_ENC_DATA ) ) ) == NULL ) + if ( ( hStereoDmxEVS = (STEREO_DMX_EVS_ENC_HANDLE) malloc( sizeof( STEREO_DMX_EVS_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for STEREO_DMX_EVS_ENC_DATA\n" ) ); } @@ -733,7 +881,7 @@ ivas_error stereo_dmx_evs_init_encoder( } hStereoDmxEVS->hPOC = NULL; - if ( ( hStereoDmxEVS->hPOC = (STEREO_DMX_EVS_POC_HANDLE) count_malloc( sizeof( STEREO_DMX_EVS_POC_DATA ) ) ) == NULL ) + if ( ( hStereoDmxEVS->hPOC = (STEREO_DMX_EVS_POC_HANDLE) malloc( sizeof( STEREO_DMX_EVS_POC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for STEREO_DMX_EVS_POC_DATA\n" ) ); } @@ -768,20 +916,21 @@ ivas_error stereo_dmx_evs_init_encoder( if ( input_frame == L_FRAME16k ) { - hStereoDmxEVS->hPOC->sin = Stereo_dmx_s_wnd_coef_eps_16k; + hStereoDmxEVS->hPOC->sin = dft_trigo_32k; } else if ( input_frame == L_FRAME32k ) { - hStereoDmxEVS->hPOC->sin = Stereo_dmx_s_wnd_coef_eps_32k; + hStereoDmxEVS->hPOC->sin = dft_trigo_32k; } else if ( input_frame == L_FRAME48k ) { - hStereoDmxEVS->hPOC->sin = Stereo_dmx_s_wnd_coef_eps_48k; + hStereoDmxEVS->hPOC->sin = dft_trigo_48k; } else { return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid frame length\n" ); } + hStereoDmxEVS->hPOC->confidence = 0.0f; *hStereoDmxEVS_out = hStereoDmxEVS; @@ -797,16 +946,22 @@ ivas_error stereo_dmx_evs_init_encoder( *-------------------------------------------------------------------*/ void stereo_dmx_evs_close_encoder( - STEREO_DMX_EVS_ENC_HANDLE hStereoDmxEVS /* i/o: Stereo downmix for EVS encoder handle */ + STEREO_DMX_EVS_ENC_HANDLE *hStereoDmxEVS /* i/o: Stereo downmix for EVS encoder handle */ ) { - if ( hStereoDmxEVS->hPOC != NULL ) + if ( hStereoDmxEVS == NULL || *hStereoDmxEVS == NULL ) + { + return; + } + + if ( ( *hStereoDmxEVS )->hPOC != NULL ) { - count_free( hStereoDmxEVS->hPOC ); - hStereoDmxEVS->hPOC = NULL; + free( ( *hStereoDmxEVS )->hPOC ); + ( *hStereoDmxEVS )->hPOC = NULL; } - count_free( hStereoDmxEVS ); + free( ( *hStereoDmxEVS ) ); + ( *hStereoDmxEVS ) = NULL; return; } diff --git a/lib_enc/ivas_stereo_eclvq_enc.c b/lib_enc/ivas_stereo_eclvq_enc.c index dffdafd17a64d09b598c4d9d4ca9b5683eb4e8be..fc622b53211efc8ee744f8a5ac3dba69815ba764 100644 --- a/lib_enc/ivas_stereo_eclvq_enc.c +++ b/lib_enc/ivas_stereo_eclvq_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "ivas_rom_enc.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /* used only for norm_s in the code_length_from_count function */ #include "basop32.h" @@ -240,9 +240,9 @@ static int16_t code_length_from_count( assert( c <= ( 1 << 14 ) ); #endif -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP c_norm = norm_s( (int16_t) c ); /* equivalent with 14 - floor(log_base2(c)) */ -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /* compute linear approximation of log2(1 + x), for x in [0, 1], using a look-up table with 64 entries */ /* normalize to {16384, ..., 32767}, subtract MSB bit, and convert to Q6 for indexing log2_1px_table */ diff --git a/lib_enc/ivas_stereo_ica_enc.c b/lib_enc/ivas_stereo_ica_enc.c index d63c8b217c56753e3a6b2c54e3da012eedcf6715..4cdd1c2fc367bbce50e9ca5ccdedf31b810c94fc 100644 --- a/lib_enc/ivas_stereo_ica_enc.c +++ b/lib_enc/ivas_stereo_ica_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #include "rom_com.h" #include "ivas_rom_com.h" @@ -345,7 +345,7 @@ static void utilCrossCorr( temp = sum2_f( tempBuf1, len ); temp *= sum2_f( tempBuf2, len ); - scale = ( temp == 0 ) ? 1.0f : 1.0f / sqrtf( temp ); + scale = ( temp == 0 ) ? 1.0f : inv_sqrt( temp ); /* starting point of lag search range should be less than the ending point */ assert( lagSearchRange[0] <= lagSearchRange[1] ); diff --git a/lib_enc/ivas_stereo_icbwe_enc.c b/lib_enc/ivas_stereo_icbwe_enc.c index 1d1f89f65642238e706b001d6c2e91e574a812f8..43ae497df8c602bdc9415f47ddb7cfaca78237ee 100644 --- a/lib_enc/ivas_stereo_icbwe_enc.c +++ b/lib_enc/ivas_stereo_icbwe_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include "ivas_cnst.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include "rom_com.h" #include "ivas_rom_com.h" #ifdef DEBUGGING diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 710e6719720265d8ede3de3e9e03e508bd328352..fa9b108f0075e489fd36560a78baaf2b5a978777 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * sync_tcx_mode() @@ -129,6 +129,7 @@ void stereo_mdct_core_enc( float *p_orig_spectrum_long[CPE_CHANNELS], orig_spectrum_long[CPE_CHANNELS][N_MAX]; /* MDCT output (L/R). */ float *orig_spectrum[CPE_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ float powerSpec[CPE_CHANNELS][N_MAX]; + float *p_powerSpec[CPE_CHANNELS]; float powerSpecMsInv_long[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ float *powerSpecMsInv[CPE_CHANNELS][2]; float quantized_spectrum_long[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ @@ -145,7 +146,7 @@ void stereo_mdct_core_enc( int16_t stereo_bits; int16_t meta_bits, signal_bits; - wmops_sub_start( "stereo_mdct_core_enc" ); + push_wmops( "stereo_mdct_core_enc" ); L_subframeTCX = 0; /* to avoid compilation warning */ @@ -234,7 +235,11 @@ void stereo_mdct_core_enc( *---------------------------------------------------------------*/ ivas_mdct_core_whitening_enc( hCPE, new_samples, old_wsp, pitch_buf, p_mdst_spectrum_long, - tnsBits, p_orig_spectrum_long, tnsSize, p_param, hBstr, NULL, 0, CPE_CHANNELS ); + tnsBits, p_orig_spectrum_long, tnsSize, p_param, hBstr, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + NULL, +#endif + 0, CPE_CHANNELS ); for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -253,9 +258,10 @@ void stereo_mdct_core_enc( /*--------------------------------------------------------------* * Stereo Processing *---------------------------------------------------------------*/ - - stereo_coder_tcx( hStereoMdct, sts, ms_mask, mdst_spectrum, inv_spectrum, inv_mdst_spectrum, 0 ); - + if ( !hStereoMdct->isSBAStereoMode ) + { + stereo_coder_tcx( hStereoMdct, sts, ms_mask, mdst_spectrum, inv_spectrum, inv_mdst_spectrum, 0 ); + } /*--------------------------------------------------------------* * Power spectrum calculation @@ -346,10 +352,13 @@ void stereo_mdct_core_enc( nSubframes = ( sts[0]->hTcxEnc->tcxMode == TCX_20 || sts[1]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; for ( n = 0; n < nSubframes; n++ ) { - if ( hStereoMdct->mdct_stereo_mode[n] != hStereoMdct->IGFStereoMode[n] || - hStereoMdct->mdct_stereo_mode[n] == SMDCT_BW_MS ) + if ( ( hStereoMdct->mdct_stereo_mode[n] != hStereoMdct->IGFStereoMode[n] || + hStereoMdct->mdct_stereo_mode[n] == SMDCT_BW_MS ) && + !hStereoMdct->isSBAStereoMode ) { - ProcessStereoIGF( hStereoMdct, sts, ms_mask, orig_spectrum, powerSpec, powerSpecMsInv, inv_spectrum, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); + p_powerSpec[0] = powerSpec[0]; + p_powerSpec[1] = powerSpec[1]; + ProcessStereoIGF( hStereoMdct, sts, ms_mask, orig_spectrum, p_powerSpec, powerSpecMsInv, inv_spectrum, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); } else { @@ -395,9 +404,14 @@ void stereo_mdct_core_enc( /* correct side bits per channel*/ sts[0]->side_bits_frame_channel -= SMDCT_NBBITS_SPLIT_RATIO; - - stereo_bits = write_stereo_to_bitstream( hStereoMdct, sts, ms_mask, 0, hBstr ); - + if ( !hStereoMdct->isSBAStereoMode ) + { + stereo_bits = write_stereo_to_bitstream( hStereoMdct, sts, ms_mask, 0, hBstr ); + } + else + { + stereo_bits = 0; + } /*--------------------------------------------------------------* * Split available bits between channels *---------------------------------------------------------------*/ @@ -413,7 +427,7 @@ void stereo_mdct_core_enc( nAvailBits -= meta_bits; nAvailBits -= SMDCT_NBBITS_SPLIT_RATIO; - splitAvailableBits( nAvailBits, hStereoMdct->split_ratio, &sts[0]->bits_frame_channel, &sts[1]->bits_frame_channel ); + splitAvailableBits( nAvailBits, hStereoMdct->split_ratio, hStereoMdct->isSBAStereoMode, &sts[0]->bits_frame_channel, &sts[1]->bits_frame_channel ); #ifdef DEBUG_MODE_MDCT dbgwrite( &nAvailBits, sizeof( int16_t ), 1, 1, "./res/nAvailBits" ); #endif @@ -439,9 +453,13 @@ void stereo_mdct_core_enc( } #endif - ivas_mdct_quant_coder( hCPE, 0, tnsBits, tnsSize, p_param, 0 ); + ivas_mdct_quant_coder( hCPE, +#ifndef ISSUE_24_CLEANUP_MCT_LFE + 0, +#endif + tnsBits, tnsSize, p_param, 0 ); - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_enc/ivas_stereo_mdct_igf_enc.c b/lib_enc/ivas_stereo_mdct_igf_enc.c index b04fe84de23a8f7c17434e40bf60d33b056333d0..1924028bcf9ff6ae1ea8f3470f59e5b5090ada01 100644 --- a/lib_enc/ivas_stereo_mdct_igf_enc.c +++ b/lib_enc/ivas_stereo_mdct_igf_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "stat_enc.h" #include "ivas_stat_enc.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/ivas_stereo_mdct_stereo_enc.c b/lib_enc/ivas_stereo_mdct_stereo_enc.c index fcad004b3a2148aa840e381293540f05b7c50f21..4ef24de8a191368165a8406f556121d047f5be93 100644 --- a/lib_enc/ivas_stereo_mdct_stereo_enc.c +++ b/lib_enc/ivas_stereo_mdct_stereo_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "prot.h" #include "ivas_rom_com.h" #include "ivas_rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "stat_enc.h" #ifdef DEBUG_PLOT #include "deb_out.h" @@ -189,7 +189,7 @@ void stereo_coder_tcx( int16_t k; int16_t nSubframes, L_frameTCX; int16_t nAvailBitsMS[NB_DIV]; - wmops_sub_start( "stereo_coder_tcx" ); + push_wmops( "stereo_coder_tcx" ); set_s( nAvailBitsMS, 0, NB_DIV ); @@ -321,7 +321,7 @@ void stereo_coder_tcx( #endif hStereoMdct->sw_uncorr = 1; - wmops_sub_end(); + pop_wmops(); return; } #ifdef DEBUGGING @@ -342,7 +342,7 @@ void stereo_coder_tcx( set_s( &ms_mask[k][0], 1, MAX_SFB ); } - wmops_sub_end(); + pop_wmops(); return; } #endif @@ -464,7 +464,7 @@ void stereo_coder_tcx( hStereoMdct->sw_uncorr = ( sw_uncorr_mean > 0.6f ); } - wmops_sub_end(); + pop_wmops(); #ifdef DEBUG_MODE_MDCT /* MDCT stereo data */ @@ -1161,13 +1161,13 @@ void initMdctStereoEncData( { if ( hStereoMdct->hDft_ana != NULL ) { - count_free( hStereoMdct->hDft_ana ); + free( hStereoMdct->hDft_ana ); hStereoMdct->hDft_ana = NULL; } if ( hStereoMdct->hItd != NULL ) { - count_free( hStereoMdct->hItd ); + free( hStereoMdct->hItd ); hStereoMdct->hItd = NULL; } } @@ -1188,7 +1188,7 @@ ivas_error initMdctItdHandling( { if ( hStereoMdct->hItd == NULL ) { - if ( ( hStereoMdct->hItd = (ITD_DATA_HANDLE) count_malloc( sizeof( ITD_DATA ) ) ) == NULL ) + if ( ( hStereoMdct->hItd = (ITD_DATA_HANDLE) malloc( sizeof( ITD_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ITD data\n" ) ); } @@ -1196,7 +1196,7 @@ ivas_error initMdctItdHandling( if ( hStereoMdct->hDft_ana == NULL ) { - if ( ( hStereoMdct->hDft_ana = (DFT_ANA_HANDLE) count_malloc( sizeof( DFT_ANA ) ) ) == NULL ) + if ( ( hStereoMdct->hDft_ana = (DFT_ANA_HANDLE) malloc( sizeof( DFT_ANA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ITD data\n" ) ); } @@ -1223,17 +1223,17 @@ void stereo_mdct_enc_destroy( { if ( ( *hStereoMdct )->hDft_ana != NULL ) { - count_free( ( *hStereoMdct )->hDft_ana ); + free( ( *hStereoMdct )->hDft_ana ); ( *hStereoMdct )->hDft_ana = NULL; } if ( ( *hStereoMdct )->hItd != NULL ) { - count_free( ( *hStereoMdct )->hItd ); + free( ( *hStereoMdct )->hItd ); ( *hStereoMdct )->hItd = NULL; } - count_free( *hStereoMdct ); + free( *hStereoMdct ); *hStereoMdct = NULL; return; diff --git a/lib_enc/ivas_stereo_switching_enc.c b/lib_enc/ivas_stereo_switching_enc.c index 3074509870a0fdc5f4ea025b4d326aadf80c68eb..0e6fe1496bd03ad3d770befe24a51544b18b4b77 100644 --- a/lib_enc/ivas_stereo_switching_enc.c +++ b/lib_enc/ivas_stereo_switching_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,16 +32,16 @@ #include #include "options.h" -#ifdef DEBUGGING -#include "debug.h" -#endif #include "cnst.h" #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" #include "ivas_rom_com.h" -#include "wmops.h" - +#include "assert.h" +#include "wmc_auto.h" +#ifdef DEBUGGING +#include "debug.h" +#endif /*-------------------------------------------------------------------* * Function allocate_CoreCoder_enc() @@ -55,7 +55,7 @@ static ivas_error allocate_CoreCoder_enc( { if ( st->hLPDmem == NULL && st->element_mode != IVAS_CPE_MDCT ) { - if ( ( st->hLPDmem = (LPD_state_HANDLE) count_malloc( sizeof( LPD_state ) ) ) == NULL ) + if ( ( st->hLPDmem = (LPD_state_HANDLE) malloc( sizeof( LPD_state ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LPDmem\n" ) ); } @@ -64,7 +64,7 @@ static ivas_error allocate_CoreCoder_enc( if ( st->hGSCEnc == NULL && st->element_mode != IVAS_CPE_MDCT ) { - if ( ( st->hGSCEnc = (GSC_ENC_HANDLE) count_malloc( sizeof( GSC_ENC_DATA ) ) ) == NULL ) + if ( ( st->hGSCEnc = (GSC_ENC_HANDLE) malloc( sizeof( GSC_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for GSC\n" ) ); } @@ -73,7 +73,7 @@ static ivas_error allocate_CoreCoder_enc( if ( st->hNoiseEst == NULL ) { - if ( ( st->hNoiseEst = (NOISE_EST_HANDLE) count_malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) + if ( ( st->hNoiseEst = (NOISE_EST_HANDLE) malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ) ); } @@ -82,7 +82,7 @@ static ivas_error allocate_CoreCoder_enc( if ( st->hVAD == NULL ) { - if ( ( st->hVAD = (VAD_HANDLE) count_malloc( sizeof( VAD_DATA ) ) ) == NULL ) + if ( ( st->hVAD = (VAD_HANDLE) malloc( sizeof( VAD_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n" ) ); } @@ -91,7 +91,7 @@ static ivas_error allocate_CoreCoder_enc( if ( st->hSpMusClas == NULL ) { - if ( ( st->hSpMusClas = (SP_MUS_CLAS_HANDLE) count_malloc( sizeof( SP_MUS_CLAS_DATA ) ) ) == NULL ) + if ( ( st->hSpMusClas = (SP_MUS_CLAS_HANDLE) malloc( sizeof( SP_MUS_CLAS_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Speech/music classifier\n" ) ); } @@ -114,25 +114,25 @@ static void deallocate_CoreCoder_TCX_enc( { if ( st->hTcxEnc != NULL ) { - count_free( st->hTcxEnc ); + free( st->hTcxEnc ); st->hTcxEnc = NULL; } if ( st->hTcxCfg != NULL ) { - count_free( st->hTcxCfg ); + free( st->hTcxCfg ); st->hTcxCfg = NULL; } if ( st->hIGFEnc != NULL ) { - count_free( st->hIGFEnc ); + free( st->hIGFEnc ); st->hIGFEnc = NULL; } if ( st->hHQ_core != NULL ) { - count_free( st->hHQ_core ); + free( st->hHQ_core ); st->hHQ_core = NULL; } @@ -152,31 +152,31 @@ static void deallocate_CoreCoder_enc( { if ( st->hLPDmem != NULL ) { - count_free( st->hLPDmem ); + free( st->hLPDmem ); st->hLPDmem = NULL; } if ( st->hGSCEnc != NULL ) { - count_free( st->hGSCEnc ); + free( st->hGSCEnc ); st->hGSCEnc = NULL; } if ( st->hNoiseEst != NULL && st->element_mode != IVAS_CPE_MDCT ) { - count_free( st->hNoiseEst ); + free( st->hNoiseEst ); st->hNoiseEst = NULL; } if ( st->hVAD != NULL && st->element_mode != IVAS_CPE_MDCT ) { - count_free( st->hVAD ); + free( st->hVAD ); st->hVAD = NULL; } if ( st->hSpMusClas != NULL && st->element_mode != IVAS_CPE_MDCT ) { - count_free( st->hSpMusClas ); + free( st->hSpMusClas ); st->hSpMusClas = NULL; } @@ -187,7 +187,7 @@ static void deallocate_CoreCoder_enc( if ( st->hBWE_TD != NULL ) { - count_free( st->hBWE_TD ); + free( st->hBWE_TD ); st->hBWE_TD = NULL; } @@ -198,7 +198,7 @@ static void deallocate_CoreCoder_enc( if ( st->hBWE_FD != NULL ) { - count_free( st->hBWE_FD ); + free( st->hBWE_FD ); st->hBWE_FD = NULL; } @@ -218,11 +218,12 @@ static void deallocate_CoreCoder_enc( *-------------------------------------------------------------------*/ ivas_error stereo_memory_enc( - CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ - const int32_t input_Fs, /* i : input sampling rate */ - const int16_t max_bwidth, /* i : maximum audio bandwidth */ - float *tdm_last_ratio, /* o : TD stereo last ratio */ - const IVAS_FORMAT ivas_format /* i : ivas format */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const int32_t input_Fs, /* i : input sampling rate */ + const int16_t max_bwidth, /* i : maximum audio bandwidth */ + float *tdm_last_ratio, /* o : TD stereo last ratio */ + const IVAS_FORMAT ivas_format, /* i : ivas format */ + const int16_t nchan_transport /* i : number transport chans */ ) { Encoder_State *st; @@ -230,6 +231,8 @@ ivas_error stereo_memory_enc( error = IVAS_ERR_OK; + assert( hCPE->last_element_mode >= IVAS_CPE_DFT && "Switching from SCE to CPE is not a valid configuration!" ); + /*--------------------------------------------------------------* * save parameters from structures that will be freed *---------------------------------------------------------------*/ @@ -260,7 +263,7 @@ ivas_error stereo_memory_enc( /* deallocate data structure of the previous CPE mode */ if ( hCPE->hStereoTD != NULL ) { - count_free( hCPE->hStereoTD ); + free( hCPE->hStereoTD ); hCPE->hStereoTD = NULL; } @@ -282,7 +285,7 @@ ivas_error stereo_memory_enc( /* allocate ICBWE structure */ if ( hCPE->hStereoICBWE == NULL ) { - if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) count_malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); } @@ -294,7 +297,7 @@ ivas_error stereo_memory_enc( st = hCPE->hCoreCoder[0]; if ( st->hHQ_core == NULL ) { - if ( ( st->hHQ_core = (HQ_ENC_HANDLE) count_malloc( sizeof( HQ_ENC_DATA ) ) ) == NULL ) + if ( ( st->hHQ_core = (HQ_ENC_HANDLE) malloc( sizeof( HQ_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ core\n" ) ); } @@ -331,7 +334,7 @@ ivas_error stereo_memory_enc( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: TD Stereo memory already allocated\n" ); } - if ( ( hCPE->hStereoTD = (STEREO_TD_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_TD_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTD = (STEREO_TD_ENC_DATA_HANDLE) malloc( sizeof( STEREO_TD_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) ); } @@ -359,7 +362,7 @@ ivas_error stereo_memory_enc( { if ( hCPE->hCoreCoder[1]->hDtxEnc != NULL ) { - count_free( hCPE->hCoreCoder[1]->hDtxEnc ); + free( hCPE->hCoreCoder[1]->hDtxEnc ); hCPE->hCoreCoder[1]->hDtxEnc = NULL; } @@ -371,7 +374,7 @@ ivas_error stereo_memory_enc( if ( hCPE->hCoreCoder[0]->Opt_DTX_ON && hCPE->hCoreCoder[0]->hTdCngEnc == NULL ) { - if ( ( hCPE->hCoreCoder[0]->hTdCngEnc = (TD_CNG_ENC_HANDLE) count_malloc( sizeof( TD_CNG_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hCoreCoder[0]->hTdCngEnc = (TD_CNG_ENC_HANDLE) malloc( sizeof( TD_CNG_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n" ) ); } @@ -385,7 +388,7 @@ ivas_error stereo_memory_enc( return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: TCA Stereo memory already allocated\n" ); } - if ( ( hCPE->hStereoTCA = (STEREO_TCA_ENC_HANDLE) count_malloc( sizeof( STEREO_TCA_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoTCA = (STEREO_TCA_ENC_HANDLE) malloc( sizeof( STEREO_TCA_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); } @@ -412,7 +415,7 @@ ivas_error stereo_memory_enc( /* allocate BWEs for primary channel */ if ( st->hBWE_TD == NULL ) { - if ( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) count_malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); } @@ -428,7 +431,7 @@ ivas_error stereo_memory_enc( InitSWBencBuffer( st->hBWE_TD ); ResetSHBbuffer_Enc( st->hBWE_TD ); - if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) count_malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); } @@ -439,7 +442,7 @@ ivas_error stereo_memory_enc( /* allocate stereo CNG structure */ if ( hCPE->hStereoCng == NULL ) { - if ( ( hCPE->hStereoCng = (STEREO_CNG_ENC_HANDLE) count_malloc( sizeof( STEREO_CNG_ENC ) ) ) == NULL ) + if ( ( hCPE->hStereoCng = (STEREO_CNG_ENC_HANDLE) malloc( sizeof( STEREO_CNG_ENC ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo Cng for Unified/TD\n" ) ); } @@ -465,19 +468,19 @@ ivas_error stereo_memory_enc( if ( hCPE->hStereoTD != NULL ) { - count_free( hCPE->hStereoTD ); + free( hCPE->hStereoTD ); hCPE->hStereoTD = NULL; } if ( hCPE->hStereoTCA != NULL ) { - count_free( hCPE->hStereoTCA ); + free( hCPE->hStereoTCA ); hCPE->hStereoTCA = NULL; } if ( hCPE->hStereoICBWE != NULL ) { - count_free( hCPE->hStereoICBWE ); + free( hCPE->hStereoICBWE ); hCPE->hStereoICBWE = NULL; } @@ -499,7 +502,7 @@ ivas_error stereo_memory_enc( /* allocate TCX/IGF structures for second channel */ st = hCPE->hCoreCoder[1]; - if ( ( st->hTcxEnc = (TCX_ENC_HANDLE) count_malloc( sizeof( TCX_ENC_DATA ) ) ) == NULL ) + if ( ( st->hTcxEnc = (TCX_ENC_HANDLE) malloc( sizeof( TCX_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxEnc\n" ) ); } @@ -514,19 +517,24 @@ ivas_error stereo_memory_enc( st->last_core = ACELP_CORE; /* needed to set-up TCX core in SetTCXModeInfo() */ } - if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) count_malloc( sizeof( TCX_config ) ) ) == NULL ) + if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxCfg\n" ) ); } - if ( ( st->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) count_malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) + if ( ( st->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n" ) ); } - st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); /* allocate and initialize MDCT stereo structure */ - if ( ( hCPE->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) count_malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); } @@ -536,6 +544,8 @@ ivas_error stereo_memory_enc( #endif initMdctStereoEncData( hCPE->hStereoMdct, ivas_format, hCPE->element_mode, hCPE->element_brate, hCPE->hCoreCoder[0]->max_bwidth, 0, NULL, 1 ); + hCPE->hStereoMdct->isSBAStereoMode = ( ivas_format == SBA_FORMAT && nchan_transport == 2 ); + if ( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->element_brate <= MAX_MDCT_ITD_BRATE && ivas_format == STEREO_FORMAT ) { if ( ( error = initMdctItdHandling( hCPE->hStereoMdct, input_Fs ) ) != IVAS_ERR_OK ) @@ -559,7 +569,7 @@ ivas_error stereo_memory_enc( if ( st->hDtxEnc == NULL ) { - if ( ( st->hDtxEnc = (DTX_ENC_HANDLE) count_malloc( sizeof( DTX_ENC_DATA ) ) ) == NULL ) + if ( ( st->hDtxEnc = (DTX_ENC_HANDLE) malloc( sizeof( DTX_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX variables\n" ) ); } @@ -568,7 +578,7 @@ ivas_error stereo_memory_enc( if ( st->hTdCngEnc != NULL ) { - count_free( st->hTdCngEnc ); + free( st->hTdCngEnc ); st->hTdCngEnc = NULL; } @@ -755,11 +765,8 @@ void stereo_switching_enc( /* no secondary channel in the previous frame -> memory resets */ set_zero( sts[1]->old_inp_12k8, L_INP_MEM ); - /*set_zero( sts[1]->old_inp_16k, L_INP_MEM );*/ set_zero( sts[1]->mem_decim, 2 * L_FILT_MAX ); - /*set_zero( sts[1]->mem_decim16k, 2*L_FILT_MAX );*/ sts[1]->mem_preemph = 0; - /*sts[1]->mem_preemph16k = 0;*/ set_zero( sts[1]->buf_speech_enc, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); set_zero( sts[1]->buf_speech_enc_pe, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); @@ -800,7 +807,6 @@ void stereo_switching_enc( mvr2r( sts[0]->lsp_old1, sts[1]->lsp_old1, M ); sts[1]->GSC_noisy_speech = 0; - if ( hCPE->element_mode == IVAS_CPE_MDCT ) { /* cross-fade overlap region of DFT Stereo downmix and original stereo channels */ @@ -810,14 +816,12 @@ void stereo_switching_enc( sts[1]->input[-sts[0]->encoderLookahead_FB + i] = ( ( sts[0]->encoderLookahead_FB - i ) * sts[0]->input[-sts[0]->encoderLookahead_FB + i] + i * sts[1]->input[-sts[0]->encoderLookahead_FB + i] ) * tmpF; sts[0]->input[-sts[0]->encoderLookahead_FB + i] = ( ( sts[0]->encoderLookahead_FB - i ) * sts[0]->input[-sts[0]->encoderLookahead_FB + i] + i * sts[1]->input[-2 * sts[0]->encoderLookahead_FB + i] ) * tmpF; } - /* restore continous signal in right channel (part of old_output was used to store original left channel) */ + /* restore continuous signal in right channel (part of old_output was used to store original left channel) */ mvr2r( sts[0]->input - sts[0]->hTcxEnc->L_frameTCX, sts[1]->input - sts[0]->hTcxEnc->L_frameTCX, sts[0]->hTcxEnc->L_frameTCX - sts[0]->encoderLookahead_FB ); sts[1]->last_core = sts[0]->last_core; sts[1]->last_coder_type = sts[0]->last_coder_type; sts[1]->last_bwidth = sts[0]->last_bwidth; - sts[1]->hTcxCfg->last_aldo = sts[0]->hTcxCfg->last_aldo; - sts[1]->hTcxCfg->tcx_curr_overlap_mode = sts[0]->hTcxCfg->tcx_curr_overlap_mode; } } else if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode == IVAS_CPE_MDCT ) @@ -826,5 +830,12 @@ void stereo_switching_enc( set_f( sts[1]->hLPDmem->old_exc, 0.0f, L_EXC_MEM ); } + /* TD/DFT -> MDCT stereo switching (there is no TCX in the TD stereo secondary channel, or DFT stereo) */ + if ( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->last_element_mode != IVAS_CPE_MDCT ) + { + sts[1]->hTcxCfg->last_aldo = sts[0]->hTcxCfg->last_aldo; + sts[1]->hTcxCfg->tcx_curr_overlap_mode = sts[0]->hTcxCfg->tcx_curr_overlap_mode; + } + return; } diff --git a/lib_enc/ivas_stereo_td_analysis.c b/lib_enc/ivas_stereo_td_analysis.c index cda6387f05f76616b83229d80aaf304d9583f038..d2d72c153426b47d40febe4c2079a100de5f2247 100644 --- a/lib_enc/ivas_stereo_td_analysis.c +++ b/lib_enc/ivas_stereo_td_analysis.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -338,7 +338,7 @@ int16_t stereo_tdm_ener_analysis( { if ( hCPE->element_brate >= IVAS_48k && sts[0]->hVAD->hangover_cnt != 0 && max( hStereoTD->tdm_lt_rms_L, hStereoTD->tdm_lt_rms_R ) < 512.0f ) { - check_bounds( &ratio_L, 0.3f, 0.7f ); + ratio_L = check_bounds( ratio_L, 0.3f, 0.7f ); } if ( ( hCPE->hStereoTCA->instTargetGain > 1.2f || hCPE->hStereoTCA->targetGain > 1.0f ) && ratio_L < 0.4f ) @@ -423,14 +423,13 @@ int16_t stereo_tdm_ener_analysis( idx_offet *= -1; } desired_idx += idx_offet; - check_bounds_s( &desired_idx, 0, 30 ); + desired_idx = check_bounds_s( desired_idx, 0, 30 ); } } if ( sts[1]->clas != UNVOICED_CLAS || sts[0]->clas != UNVOICED_CLAS ) { - desired_idx = min( desired_idx, 25 ); - desired_idx = max( desired_idx, 5 ); + desired_idx = check_bounds_s( desired_idx, 5, 25 ); } hStereoTD->tdm_inst_ratio_idx = desired_idx; @@ -848,7 +847,7 @@ static float Comp_diff_lt_corr( adaprate = M_ADAP * min( tdm_lt_rms_R, tdm_lt_rms_L ) + B_ADAP; } - check_bounds( &adaprate, MIN_ADAP_FAC, 1.0f ); + adaprate = check_bounds( adaprate, MIN_ADAP_FAC, 1.0f ); /*----------------------------------------------------------------* * In case of unvoiced content (expect when it is part of an onset), @@ -942,7 +941,7 @@ static int16_t limit_idx_Dwnmix( int16_t idx; idx = idx_in; - check_bounds_s( &idx, 1, 29 ); + idx = check_bounds_s( idx, 1, 29 ); if ( unclr_decision == 1 && tdm_last_LRTD_frame_cnt > 1 ) { diff --git a/lib_enc/ivas_stereo_td_enc.c b/lib_enc/ivas_stereo_td_enc.c index cba218a3d059bc9535a0e65c1354a9d6a3444daf..3857795dceadc5a1f43a07939971f77ac20dcd90 100644 --- a/lib_enc/ivas_stereo_td_enc.c +++ b/lib_enc/ivas_stereo_td_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "prot.h" #include "ivas_prot.h" #include "ivas_rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include "math.h" @@ -190,7 +190,7 @@ ivas_error stereo_set_tdm( { if ( st->hBWE_TD != NULL ) { - count_free( st->hBWE_TD ); + free( st->hBWE_TD ); st->hBWE_TD = NULL; } @@ -198,7 +198,7 @@ ivas_error stereo_set_tdm( if ( st->hBWE_FD != NULL ) { - count_free( st->hBWE_FD ); + free( st->hBWE_FD ); st->hBWE_FD = NULL; } } @@ -206,7 +206,7 @@ ivas_error stereo_set_tdm( /* allocate ICBWE structure */ if ( hCPE->hStereoICBWE == NULL ) { - if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) count_malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) + if ( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); } @@ -222,7 +222,7 @@ ivas_error stereo_set_tdm( /* deallocate ICBWE structure */ if ( hCPE->hStereoICBWE != NULL ) { - count_free( hCPE->hStereoICBWE ); + free( hCPE->hStereoICBWE ); hCPE->hStereoICBWE = NULL; } @@ -238,7 +238,7 @@ ivas_error stereo_set_tdm( /* allocate BWEs for secondary channel */ if ( st->hBWE_TD == NULL ) { - if ( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) count_malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); } @@ -251,7 +251,7 @@ ivas_error stereo_set_tdm( InitSWBencBuffer( st->hBWE_TD ); ResetSHBbuffer_Enc( st->hBWE_TD ); - if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) count_malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) + if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); } @@ -302,12 +302,13 @@ ivas_error stereo_set_tdm( *-------------------------------------------------------------------*/ void tdm_configure_enc( - CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ - const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ - const int16_t tdm_ratio_idx, /* i : ratio index */ - const int16_t tdm_ratio_idx_SM, /* i : ratio index in SM mode */ - const int16_t attack_flag, /* i : Primary channel attack flag */ - const int16_t nb_bits_metadata /* i : number of metadata bits */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const float Etot_last[CPE_CHANNELS], /* i/o: Energy of last frame */ + const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ + const int16_t tdm_ratio_idx, /* i : ratio index */ + const int16_t tdm_ratio_idx_SM, /* i : ratio index in SM mode */ + const int16_t attack_flag, /* i : Primary channel attack flag */ + const int16_t nb_bits_metadata /* i : number of metadata bits */ ) { int16_t tdm_ratio_bit_alloc_idx, mod_ct; @@ -326,11 +327,11 @@ void tdm_configure_enc( *----------------------------------------------------------------*/ hStereoTD->tdm_use_IAWB_Ave_lpc = 0; /* Flag initialisation */ - sts[0]->hSpMusClas->tdm_lt_Etot = 0.1f * sts[0]->hNoiseEst->Etot_last + 0.9f * sts[0]->hSpMusClas->tdm_lt_Etot; - sts[1]->hSpMusClas->tdm_lt_Etot = 0.1f * sts[1]->hNoiseEst->Etot_last + 0.9f * sts[1]->hSpMusClas->tdm_lt_Etot; + sts[0]->hSpMusClas->tdm_lt_Etot = 0.1f * Etot_last[0] + 0.9f * sts[0]->hSpMusClas->tdm_lt_Etot; + sts[1]->hSpMusClas->tdm_lt_Etot = 0.1f * Etot_last[1] + 0.9f * sts[1]->hSpMusClas->tdm_lt_Etot; if ( hCPE->hStereoClassif->lrtd_mode == 0 && ( ( sts[1]->hSpMusClas->tdm_lt_Etot < 0 && hCPE->hCoreCoder[1]->vad_flag == 0 ) /* very clean signal */ - || ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( sts[1]->hNoiseEst->Etot_last < 30.0f && ( sts[0]->hSpMusClas->tdm_lt_Etot - sts[1]->hSpMusClas->tdm_lt_Etot ) > 26.0f ) ) ) ) + || ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( Etot_last[1] < 30.0f && ( sts[0]->hSpMusClas->tdm_lt_Etot - sts[1]->hSpMusClas->tdm_lt_Etot ) > 26.0f ) ) ) ) { sts[1]->coder_type = INACTIVE; @@ -340,7 +341,7 @@ void tdm_configure_enc( } hStereoTD->tdm_lp_reuse_flag = 1; } - else if ( ( ( hCPE->hCoreCoder[1]->vad_flag == 0 ) || ( hCPE->hCoreCoder[0]->vad_flag == 0 && sts[1]->hNoiseEst->Etot_last < 30.0f && ( sts[0]->hSpMusClas->tdm_lt_Etot - sts[1]->hSpMusClas->tdm_lt_Etot ) > 26.0f ) ) && ( hCPE->hStereoClassif->lrtd_mode == 1 ) /* && NO_DTX */ ) /* boths channels are inactive but not DTX used*/ + else if ( ( ( hCPE->hCoreCoder[1]->vad_flag == 0 ) || ( hCPE->hCoreCoder[0]->vad_flag == 0 && Etot_last[1] < 30.0f && ( sts[0]->hSpMusClas->tdm_lt_Etot - sts[1]->hSpMusClas->tdm_lt_Etot ) > 26.0f ) ) && ( hCPE->hStereoClassif->lrtd_mode == 1 ) /* && NO_DTX */ ) /* boths channels are inactive but not DTX used*/ { sts[1]->coder_type = INACTIVE; if ( tdm_ratio_idx > 1 && tdm_ratio_idx < 29 ) @@ -352,7 +353,7 @@ void tdm_configure_enc( hStereoTD->tdm_lp_reuse_flag = 1; } } - else if ( !( sts[1]->sp_aud_decision0 ) && sts[1]->tc_cnt <= 0 && ( sts[1]->coder_type_raw == UNVOICED || ( hStereoTD->tdm_LRTD_flag == 1 && hStereoTD->tdm_lp_reuse_flag == 0 && ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( sts[1]->hNoiseEst->Etot_last < 30.0f && ( sts[0]->hSpMusClas->tdm_lt_Etot - sts[1]->hSpMusClas->tdm_lt_Etot ) > 26.0f ) ) ) ) ) + else if ( !( sts[1]->sp_aud_decision0 ) && sts[1]->tc_cnt <= 0 && ( sts[1]->coder_type_raw == UNVOICED || ( hStereoTD->tdm_LRTD_flag == 1 && hStereoTD->tdm_lp_reuse_flag == 0 && ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( Etot_last[1] < 30.0f && ( sts[0]->hSpMusClas->tdm_lt_Etot - sts[1]->hSpMusClas->tdm_lt_Etot ) > 26.0f ) ) ) ) ) { sts[1]->coder_type = UNVOICED; if ( hStereoTD->tdm_LRTD_flag == 1 ) @@ -444,7 +445,7 @@ void tdm_configure_enc( { hStereoTD->tdm_inst_ratio_idx -= LRTD_STEREO_QUARTER_RANGE; } - check_bounds_s( &( hStereoTD->tdm_inst_ratio_idx ), 8, 22 ); + hStereoTD->tdm_inst_ratio_idx = check_bounds_s( hStereoTD->tdm_inst_ratio_idx, 8, 22 ); } /*----------------------------------------------------------------* @@ -538,12 +539,12 @@ void tdm_configure_enc( /*-------------------------------------------------------------------* - * signalling_enc_secondary() + * signaling_enc_secondary() * * Signalling of the secondary channel *-------------------------------------------------------------------*/ -ivas_error signalling_enc_secondary( +ivas_error signaling_enc_secondary( Encoder_State *st, /* i/o: Encoder structure */ const int16_t tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag OR LRTD primary channel */ const int16_t tdm_Pitch_reuse_flag /* i : primary channel pitch reuse flag*/ diff --git a/lib_enc/ivas_tcx_core_enc.c b/lib_enc/ivas_tcx_core_enc.c index f5725b48aff6720a0d2ed3c331d0b8838901180e..3bda423fadd1f51d543cb07329a919f807e8f044 100644 --- a/lib_enc/ivas_tcx_core_enc.c +++ b/lib_enc/ivas_tcx_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "prot.h" #include "rom_com.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /*-------------------------------------------------------------------* @@ -99,7 +99,21 @@ void stereo_tcx_init_enc( st->hTcxCfg->ctx_hm = getCtxHm( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->rf_mode ); st->hTcxCfg->resq = getResq( st->bits_frame_nominal * FRAMES_PER_SEC ); st->hTcxEnc->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->bits_frame_nominal * FRAMES_PER_SEC, st->rf_mode, st->element_mode ); - st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_mode, st->mct_chan_mode ); + st->igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + if ( st->element_mode != EVS_MONO ) + { + st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( st->bits_frame_nominal * FRAMES_PER_SEC, st->igf, st->element_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + st->mct_chan_mode +#endif + ); + } st->core_brate = st->total_brate; @@ -120,8 +134,8 @@ void stereo_tcx_core_enc( float lsp_new[], /* i : LSPs at the end of the frame */ float lsp_mid[], /* i : LSPs in the middle of the frame */ float pitch_buf[NB_SUBFR16k], /* o : floating pitch for each subframe */ - const int16_t last_element_mode, /* i : last element mode */ - const int16_t vad_hover_flag /* i : VAD hangover flag */ + const int16_t last_element_mode, /* i : last element mode */ + const int16_t vad_hover_flag /* i : VAD hangover flag */ ) { TCX_ENC_HANDLE hTcxEnc; @@ -171,7 +185,7 @@ void stereo_tcx_core_enc( pF = fopen( "./res/stereo_tcx_enc_ind.txt", "w" ); #endif - wmops_sub_start( "stereo_tcx_core_enc" ); + push_wmops( "stereo_tcx_core_enc" ); /*Sanity check*/ assert( st->mdct_sw == MODE1 && "MDCT switching should be in TCX MODE 1\n" ); @@ -196,11 +210,7 @@ void stereo_tcx_core_enc( st->bits_frame_core = (int16_t) ( st->total_brate / FRAMES_PER_SEC ) - hBstr->nb_bits_tot; /*Get Bits of TCX header*/ -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - nbits_header = 2; /* Coder types (2) */ -#else nbits_header = 3; /* Coder types (2) + last_core for bfi (1) */ -#endif if ( st->tcxonly ) { @@ -253,17 +263,12 @@ void stereo_tcx_core_enc( { st->core = TCX_10_CORE; n_subframes = 2; -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 nbits_header += ( st->hTcxCfg->tcx_last_overlap_mode == HALF_OVERLAP || st->hTcxCfg->tcx_last_overlap_mode == MIN_OVERLAP ) ? 2 : 1; -#endif } else if ( hTcxEnc->tcxMode == TCX_20 ) { st->core = TCX_20_CORE; n_subframes = 1; -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - nbits_header += 1; /* last core for bfi */ -#endif } #ifdef DEBUG_MODE_TCX @@ -273,36 +278,21 @@ void stereo_tcx_core_enc( nbits_start = hBstr->nb_bits_tot; /*--------------------------------------------------------------------------------* - * Write TCX signalling + * Write TCX signaling *--------------------------------------------------------------------------------*/ /* TCX20/TCX10 and coder type */ -#ifdef FIX_IVAS_185_MDCT_ST_PLC_FADEOUT - writeTCXMode( st, hBstr, 0, /* <- is_mct */ &nbits_start ); -#else - writeTCXMode( st, hBstr, &nbits_start ); -#endif + writeTCXMode( st, hBstr, 0, /* MCT_flag */ &nbits_start ); /* write last_core for error concealment */ -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 - if ( st->core == TCX_20_CORE ) - { - push_next_indice( hBstr, ( st->last_core != ACELP_CORE || st->core == TCX_10_CORE ), 1 ); - } -#else push_next_indice( hBstr, ( st->last_core != ACELP_CORE || st->core == TCX_10_CORE ), 1 ); -#endif /* write TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ -#ifdef FIX_IVAS_180_PLC_SIGNAL_LAST_OVLP_IN_TCX10 writeTCXWindowing( hBstr, st->hTcxCfg->tcx_curr_overlap_mode ); if ( st->core == TCX_10_CORE ) { writeTCXWindowing( hBstr, st->hTcxCfg->tcx_last_overlap_mode ); } -#else - writeTCXWindowing( hBstr, st->hTcxCfg->tcx_curr_overlap_mode ); -#endif assert( nbits_header == ( hBstr->nb_bits_tot - nbits_start ) ); #ifdef DEBUG_MODE_TCX @@ -477,7 +467,7 @@ void stereo_tcx_core_enc( mvr2r( lsp_q, st->lsp_old, M ); } - if ( st->Opt_DTX_ON && !st->tcxonly ) + if ( st->Opt_DTX_ON && !st->tcxonly && st->hTdCngEnc != NULL ) { /* update CNG parameters in active frames */ if ( st->bwidth == NB && st->enableTcxLpc && st->core != ACELP_CORE ) @@ -571,7 +561,7 @@ void stereo_tcx_core_enc( set_f( pitch_buf, L_SUBFR, NB_SUBFR16k ); } - wmops_sub_end(); + pop_wmops(); return; } @@ -700,7 +690,7 @@ int16_t ivas_acelp_tcx20_switching( for ( i = 0; i < L_frame; i++ ) { - x[i] *= (float) L_frame / sqrtf( 2 * NORM_MDCT_FACTOR ); + x[i] *= (float) L_frame * inv_sqrt( 2 * NORM_MDCT_FACTOR ); y[i] = x[i]; } diff --git a/lib_enc/ivas_stereo_td_low_rate_enc.c b/lib_enc/ivas_td_low_rate_enc.c similarity index 98% rename from lib_enc/ivas_stereo_td_low_rate_enc.c rename to lib_enc/ivas_td_low_rate_enc.c index 92abf45e9a5fc93c1d22b276d1279d946b411840..de75faf2f97f46af7df4ca8a628eebb13923450e 100644 --- a/lib_enc/ivas_stereo_td_low_rate_enc.c +++ b/lib_enc/ivas_td_low_rate_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "ivas_cnst.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -72,28 +72,27 @@ void tdm_low_rate_enc( float exc_wo_nf[L_FRAME]; LPD_state_HANDLE hLPDmem = st->hLPDmem; - tmp_nb_bits_tot = 0; - /*---------------------------------------------------------------* - * DCT transform of the residual and create a subsample residual + * Initialization *---------------------------------------------------------------*/ - edct( res, dct_res, L_FRAME, st->element_mode ); - nb_subfr = 2; - /*---------------------------------------------------------------* - * Compute time domain excitation contribution in the subsample domain - *---------------------------------------------------------------*/ + st->GSC_IVAS_mode = 0; + st->GSC_noisy_speech = 1; + st->hGSCEnc->noise_lev = 14; hLPDmem->tilt_code = 0.0f; - - st->GSC_noisy_speech = 1; set_f( dct_epit, 0, L_FRAME ); - set_f( pitch_buf, 64, NB_SUBFR ); - st->hGSCEnc->noise_lev = 14; + set_f( pitch_buf, L_SUBFR, NB_SUBFR ); last_pit_bin = L_FRAME / 2; + /*---------------------------------------------------------------* + * DCT transform of the residual and create a subsample residual + *---------------------------------------------------------------*/ + + edct( res, dct_res, L_FRAME, st->element_mode ); + /*--------------------------------------------------------------------------------------* * GSC encoder *--------------------------------------------------------------------------------------*/ diff --git a/lib_enc/lead_indexing.c b/lib_enc/lead_indexing.c index d97ccc69559526f8211641a5cdb55d1e4652ab4d..6208d66eb8228059fdf727c294a69f24d2086d70 100644 --- a/lib_enc/lead_indexing.c +++ b/lib_enc/lead_indexing.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_enc/lib_enc.c b/lib_enc/lib_enc.c index 93b43ee63fb16355bc75c8bd68bddab472d547e5..ec875b119aa59a49ba3182358a5afc863cc0fcbb 100644 --- a/lib_enc/lib_enc.c +++ b/lib_enc/lib_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,9 +39,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#ifdef WMOPS -#include "wmops.h" -#endif +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local struct @@ -53,7 +51,6 @@ struct IVAS_ENC Indice ind_list[MAX_NUM_DATA][MAX_NUM_INDICES]; /* list of indices */ Indice ind_list_metadata[MAX_NUM_METADATA][MAX_BITS_METADATA]; /* list of indices for metadata */ ENC_CORE_HANDLE hCoreCoder; - /* Some of these can be moved to Encoder_Struct, but for now leave them here to keep merging simpler */ bool isConfigured; #ifdef DEBUGGING bool cmd_stereo; @@ -62,7 +59,11 @@ struct IVAS_ENC int16_t Opt_RF_ON_loc; int16_t rf_fec_offset_loc; bool ismMetadataProvided[MAX_NUM_OBJECTS]; - bool maxBandwidthUser; /* Was a specific max bandwith selected by the user? */ + bool maxBandwidthUser; /* Was a specific max bandwith selected by the user? */ + IVAS_ENC_BANDWIDTH newBandwidthApi; /* maximum encoded bandwidth, as set on API level */ +#ifdef FIX_379_EXT_METADATA + bool extMetadataApi; /* External metadata requested, to be checked against current bit rate */ +#endif }; /*---------------------------------------------------------------------* @@ -76,10 +77,18 @@ static ivas_error setChannelAwareConfig( IVAS_ENC_HANDLE hIvasEnc, const IVAS_EN static int16_t getInputBufferSize( const Encoder_Struct *st_ivas ); static ivas_error doCommonConfigureChecks( IVAS_ENC_HANDLE hIvasEnc ); static ivas_error doCommonSetterChecks( IVAS_ENC_HANDLE hIvasEnc ); -static void updateBandwidthFromFs( const ENCODER_CONFIG_HANDLE hEncoderConfig ); +static ivas_error sanitizeBandwidth( const IVAS_ENC_HANDLE hIvasEnc ); +#ifdef FIX_379_EXT_METADATA +static ivas_error sanitizeBitrateISM( const ENCODER_CONFIG_HANDLE hEncoderConfig, const IVAS_ENC_HANDLE hIvasEnc ); +#else +static ivas_error sanitizeBitrateISM( const ENCODER_CONFIG_HANDLE hEncoderConfig ); +#endif static void init_encoder_config( ENCODER_CONFIG_HANDLE hEncoderConfig ); static void resetIsmMetadataProvidedFlags( IVAS_ENC_HANDLE hIvasEnc ); static ivas_error bandwidthApiToInternal( const IVAS_ENC_BANDWIDTH maxBandwidth, int16_t *internalMaxBandwidth ); +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION +static ivas_error agcAPIToInternal( const IVAS_ENC_AGC agcOption, int16_t *internalAGCOption ); +#endif static ivas_error fecIndicatorApiToInternal( const IVAS_ENC_FEC_INDICATOR fecIndicator, int16_t *fecIndicatorInternal ); #ifdef DEBUGGING static ivas_error forcedModeApiToInternal( IVAS_ENC_FORCED_MODE forcedMode, int16_t *forcedModeInternal ); @@ -104,24 +113,29 @@ ivas_error IVAS_ENC_Open( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } + /*-----------------------------------------------------------------* + * Allocate and initialize IVAS application encoder handle + *-----------------------------------------------------------------*/ + #ifdef BITSTREAM_INDICES_MEMORY - if ( ( *phIvasEnc = (IVAS_ENC_HANDLE) dynamic_malloc( sizeof( struct IVAS_ENC ) ) ) == NULL ) +#define WMC_TOOL_SKIP + if ( ( *phIvasEnc = (IVAS_ENC_HANDLE) malloc( sizeof( struct IVAS_ENC ) ) ) == NULL ) +#undef WMC_TOOL_SKIP #else - if ( ( *phIvasEnc = (IVAS_ENC_HANDLE) count_malloc( sizeof( struct IVAS_ENC ) ) ) == NULL ) + if ( ( *phIvasEnc = (IVAS_ENC_HANDLE) malloc( sizeof( struct IVAS_ENC ) ) ) == NULL ) #endif { return IVAS_ERR_FAILED_ALLOC; } - if ( ( ( *phIvasEnc )->st_ivas = (Encoder_Struct *) count_malloc( sizeof( Encoder_Struct ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS encoder structure" ); - } - - if ( ( ( *phIvasEnc )->st_ivas->hEncoderConfig = (ENCODER_CONFIG_HANDLE) count_malloc( sizeof( ENCODER_CONFIG ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Encoder config structure" ); - } + ( *phIvasEnc )->hCoreCoder = NULL; + ( *phIvasEnc )->isConfigured = false; +#ifdef DEBUGGING + ( *phIvasEnc )->cmd_stereo = false; +#endif + ( *phIvasEnc )->switchingActive = false; + ( *phIvasEnc )->maxBandwidthUser = false; + resetIsmMetadataProvidedFlags( *phIvasEnc ); /*-----------------------------------------------------------------* * Initialize indices @@ -146,29 +160,36 @@ ivas_error IVAS_ENC_Open( } /*-----------------------------------------------------------------* - * Initialize encoder state + * Allocate IVAS-codec encoder state *-----------------------------------------------------------------*/ - st_ivas = ( *phIvasEnc )->st_ivas; - st_ivas->hEncoderConfig->ivas_total_brate = ACELP_12k65; - st_ivas->hEncoderConfig->Opt_SC_VBR = 0; - st_ivas->hEncoderConfig->last_Opt_SC_VBR = 0; + if ( ( ( *phIvasEnc )->st_ivas = (Encoder_Struct *) malloc( sizeof( Encoder_Struct ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS encoder structure" ); + } - st_ivas->mc_mode = MC_MODE_NONE; - st_ivas->ism_mode = ISM_MODE_NONE; - st_ivas->sba_mode = SBA_MODE_NONE; + if ( ( ( *phIvasEnc )->st_ivas->hEncoderConfig = (ENCODER_CONFIG_HANDLE) malloc( sizeof( ENCODER_CONFIG ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Encoder config structure" ); + } + + /*-----------------------------------------------------------------* + * Initialize IVAS-codec encoder state + *-----------------------------------------------------------------*/ + + st_ivas = ( *phIvasEnc )->st_ivas; + /* initialize encoder Config. handle */ init_encoder_config( st_ivas->hEncoderConfig ); - ( *phIvasEnc )->hCoreCoder = NULL; - ( *phIvasEnc )->isConfigured = false; -#ifdef DEBUGGING - ( *phIvasEnc )->cmd_stereo = false; -#endif - ( *phIvasEnc )->switchingActive = false; - ( *phIvasEnc )->maxBandwidthUser = false; - resetIsmMetadataProvidedFlags( *phIvasEnc ); + /* initialize pointers to handles to NULL */ + ivas_initialize_handles_enc( st_ivas ); + /* set high-level parameters */ + st_ivas->mc_mode = MC_MODE_NONE; + st_ivas->ism_mode = ISM_MODE_NONE; + st_ivas->sba_mode = SBA_MODE_NONE; + st_ivas->sba_analysis_order = 0; return IVAS_ERR_OK; } @@ -198,18 +219,20 @@ void IVAS_ENC_Close( { if ( ( *phIvasEnc )->st_ivas->hEncoderConfig ) { - count_free( ( *phIvasEnc )->st_ivas->hEncoderConfig ); + free( ( *phIvasEnc )->st_ivas->hEncoderConfig ); ( *phIvasEnc )->st_ivas->hEncoderConfig = NULL; } - count_free( ( *phIvasEnc )->st_ivas ); + free( ( *phIvasEnc )->st_ivas ); } ( *phIvasEnc )->st_ivas = NULL; #ifdef BITSTREAM_INDICES_MEMORY - dynamic_free( *phIvasEnc ); +#define WMC_TOOL_SKIP + free( *phIvasEnc ); +#undef WMC_TOOL_SKIP #else - count_free( *phIvasEnc ); + free( *phIvasEnc ); #endif *phIvasEnc = NULL; @@ -350,7 +373,8 @@ ivas_error IVAS_ENC_ConfigureForObjects( const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ - const uint16_t numObjects /* i : number of objects to be encoded */ + const uint16_t numObjects, /* i : number of objects to be encoded */ + const bool ism_extended_metadata /* i : Extended metadata used (true/false), where extended metadata includes radius and orientation */ ) { Encoder_Struct *st_ivas; @@ -363,14 +387,20 @@ ivas_error IVAS_ENC_ConfigureForObjects( if ( numObjects > MAX_NUM_OBJECTS ) { - return IVAS_ERR_TOO_MANY_OBJECT_INPUTS; + return IVAS_ERR_TOO_MANY_INPUTS; } st_ivas = hIvasEnc->st_ivas; st_ivas->hEncoderConfig->ivas_format = ISM_FORMAT; st_ivas->hEncoderConfig->element_mode_init = IVAS_SCE; st_ivas->hEncoderConfig->nchan_inp = numObjects; - +#ifdef NCHAN_ISM_PARAMETER + st_ivas->hEncoderConfig->nchan_ism = numObjects; +#endif + st_ivas->hEncoderConfig->ism_extended_metadata_flag = ism_extended_metadata; +#ifdef FIX_379_EXT_METADATA + hIvasEnc->extMetadataApi = ( ism_extended_metadata == 1 ); +#endif hIvasEnc->maxBandwidthUser = max_bwidth_user; error = configureEncoder( hIvasEnc, inputFs, bitrate, maxBandwidth, dtxConfig, IVAS_ENC_GetDefaultChannelAwareConfig() ); @@ -410,7 +440,8 @@ ivas_error IVAS_ENC_FeedObjectMetadata( return IVAS_ERR_INDEX_OUT_OF_BOUNDS; } - error = set_ism_metadata( hIvasEnc->st_ivas->hIsmMetaData[ismIndex], metadata.azimuth, metadata.elevation ); + error = ivas_set_ism_metadata( hIvasEnc->st_ivas->hIsmMetaData[ismIndex], metadata.azimuth, metadata.elevation, metadata.radius, metadata.yaw, metadata.pitch ); + if ( error != IVAS_ERR_OK ) { return error; @@ -437,8 +468,14 @@ ivas_error IVAS_ENC_ConfigureForAmbisonics( const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ const IVAS_ENC_SBA_ORDER order, /* i : order of the Ambisonics input */ const bool isPlanar, /* i : if true, input is treated as planar Ambisonics */ - const bool Opt_AGC_ON, /* i : AGC on/off flag */ - const bool Opt_PCA_ON /* i : PCA option flag */ +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + const IVAS_ENC_AGC Opt_AGC_ON, /* i : AGC on/off/undefined flag */ +#endif + const bool Opt_PCA_ON /* i : PCA option flag */ +#ifdef DEBUG_SBA_AUDIO_DUMP + , + int16_t *numTransportChannels +#endif ) { ENCODER_CONFIG_HANDLE hEncoderConfig; @@ -459,13 +496,23 @@ ivas_error IVAS_ENC_ConfigureForAmbisonics( /* Input in ACN/SN3D in all cases (3D and planar): get number of channels */ hEncoderConfig->nchan_inp = ivas_sba_get_nchan( hEncoderConfig->sba_order, 0 ); /*planar input arg. deliberately set to zero since input always in ACN/SN3D*/ - hEncoderConfig->Opt_AGC_ON = (int16_t) Opt_AGC_ON; +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + if ( ( error = agcAPIToInternal( Opt_AGC_ON, &( hEncoderConfig->Opt_AGC_ON ) ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + hEncoderConfig->Opt_PCA_ON = (int16_t) Opt_PCA_ON; hIvasEnc->maxBandwidthUser = max_bwidth_user; error = configureEncoder( hIvasEnc, inputFs, bitrate, maxBandwidth, dtxConfig, IVAS_ENC_GetDefaultChannelAwareConfig() ); +#ifdef DEBUG_SBA_AUDIO_DUMP + *numTransportChannels = hIvasEnc->st_ivas->nchan_transport; +#endif + return error; } @@ -698,7 +745,14 @@ static ivas_error configureEncoder( { if ( !is_IVAS_bitrate( hEncoderConfig->ivas_total_brate ) ) { - return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Incorrect bitrate specification in IVAS: %d", hEncoderConfig->ivas_total_brate ); + if ( hEncoderConfig->Opt_SC_VBR ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Incorrect bitrate specification in IVAS [bps]: %d", ACELP_5k90 ); + } + else + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Incorrect bitrate specification in IVAS [bps]: %d", hEncoderConfig->ivas_total_brate ); + } } if ( hEncoderConfig->ivas_format == STEREO_FORMAT ) @@ -737,32 +791,18 @@ static ivas_error configureEncoder( } else if ( hEncoderConfig->ivas_format == ISM_FORMAT ) { - if ( hEncoderConfig->ivas_total_brate > IVAS_256k ) - { - return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too high bitrate for ISm specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); - } - if ( hEncoderConfig->ivas_total_brate < IVAS_16k4 && hEncoderConfig->nchan_inp == 2 ) - { - return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for 2 ISm specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); - } - if ( hEncoderConfig->ivas_total_brate < IVAS_24k4 && hEncoderConfig->nchan_inp == 3 ) - { - return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for 3 ISm specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); - } - if ( hEncoderConfig->ivas_total_brate < IVAS_24k4 && hEncoderConfig->nchan_inp == 4 ) +#ifdef FIX_379_EXT_METADATA + if ( ( error = sanitizeBitrateISM( hEncoderConfig, hIvasEnc ) ) != IVAS_ERR_OK ) +#else + if ( ( error = sanitizeBitrateISM( hEncoderConfig ) ) != IVAS_ERR_OK ) +#endif { - return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for 4 ISm specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + return error; } } else if ( hEncoderConfig->ivas_format == SBA_FORMAT ) { - if ( hEncoderConfig->ivas_total_brate < IVAS_256k ) - { - /* set SBA order to 1 for bit rates below 256kbps for correct handling of input with higher order */ - /* IVAS_fmToDo: needs more work in case of bitrate switching */ - hEncoderConfig->sba_order = 1; - } - st_ivas->sba_mode = ivas_sba_mode_select( hEncoderConfig->ivas_total_brate ); // VE: is it needed here? + /* nothing */ } else if ( hEncoderConfig->ivas_format == MASA_FORMAT ) { @@ -807,8 +847,6 @@ static ivas_error configureEncoder( hEncoderConfig->input_Fs = inputFs; - updateBandwidthFromFs( hEncoderConfig ); - /*-----------------------------------------------------------------* * Channel-aware mode *-----------------------------------------------------------------*/ @@ -836,7 +874,7 @@ static ivas_error configureEncoder( } } - if ( hEncoderConfig->ivas_total_brate == 13200 && hEncoderConfig->Opt_RF_ON == 1 ) + if ( hEncoderConfig->ivas_total_brate == IVAS_13k2 && hEncoderConfig->Opt_RF_ON == 1 ) { st_ivas->codec_mode = MODE2; } @@ -855,27 +893,38 @@ static ivas_error configureEncoder( } if ( hEncoderConfig->Opt_DTX_ON && hEncoderConfig->ivas_format != MONO_FORMAT && - !( hEncoderConfig->ivas_format == MASA_FORMAT && hEncoderConfig->ivas_total_brate <= IVAS_128k ) && - hEncoderConfig->ivas_format != SBA_FORMAT && - ( hEncoderConfig->element_mode_init != IVAS_CPE_DFT && hEncoderConfig->element_mode_init != IVAS_CPE_TD ) && !( hEncoderConfig->ivas_format == ISM_FORMAT && hEncoderConfig->nchan_inp == 1 ) && - hEncoderConfig->element_mode_init != IVAS_CPE_MDCT ) + ( +#ifndef DISCRETE_ISM_DTX_CNG + ( hEncoderConfig->ivas_format == ISM_FORMAT && hEncoderConfig->nchan_inp == 2 ) || // ToDo: see Issue 113 + ( hEncoderConfig->ivas_format == ISM_FORMAT && hEncoderConfig->nchan_inp > 2 && hEncoderConfig->ivas_total_brate != IVAS_24k4 && hEncoderConfig->ivas_total_brate != IVAS_32k ) || // ParamISM +#endif + ( hEncoderConfig->ivas_format == MASA_FORMAT && hEncoderConfig->ivas_total_brate > IVAS_128k ) || // ToDo: remove the bitrate limitation + ( hEncoderConfig->ivas_format == SBA_FORMAT && ivas_get_sba_num_TCs( hEncoderConfig->ivas_total_brate, 1 ) > 2 ) || // ToDo: support for 3+ TCs to be done + hEncoderConfig->ivas_format == MC_FORMAT // ToDo: TBD + ) ) { return IVAS_ERROR( IVAS_ERR_DTX_NOT_SUPPORTED, "DTX is not supported in this IVAS format and element mode." ); } - if ( hEncoderConfig->ivas_format != MONO_FORMAT && hEncoderConfig->Opt_RF_ON ) +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION +#ifndef LBR_SBA + if ( hEncoderConfig->Opt_AGC_ON == SBA_AGC_FORCE_ENABLE && !( hEncoderConfig->ivas_format == SBA_FORMAT && ivas_sba_mode_select( hEncoderConfig->ivas_total_brate ) == SBA_MODE_SPAR ) ) +#else + if ( hEncoderConfig->Opt_AGC_ON == SBA_AGC_FORCE_ENABLE && !( hEncoderConfig->ivas_format == SBA_FORMAT && ivas_sba_mode_select( ) == SBA_MODE_SPAR ) ) +#endif { - return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Channel-aware mode is not supported in IVAS yet." ); + return IVAS_ERROR( IVAS_ERR_NOT_SUPPORTED_OPTION, "AGC supported in SBA format at bitrates >= 24.4 kbps only." ); } +#endif - if ( hEncoderConfig->Opt_AGC_ON && !( hEncoderConfig->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) ) + if ( hEncoderConfig->Opt_PCA_ON && !( hEncoderConfig->ivas_format == SBA_FORMAT && hEncoderConfig->ivas_total_brate == PCA_BRATE && hEncoderConfig->sba_order == SBA_FOA_ORDER ) ) { - return IVAS_ERROR( IVAS_ERR_NOT_SUPPORTED_OPTION, "AGC supported in SBA format at bitrates >= 24.4 kbps only." ); + return IVAS_ERROR( IVAS_ERR_NOT_SUPPORTED_OPTION, "PCA supported at SBA FOA 256 kbps only." ); } - if ( hEncoderConfig->Opt_PCA_ON && !( hEncoderConfig->ivas_format == SBA_FORMAT && hEncoderConfig->ivas_total_brate == PCA_BRATE && hEncoderConfig->ivas_total_brate == IVAS_256k && hEncoderConfig->sba_order == 1 ) ) + if ( ( error = sanitizeBandwidth( hIvasEnc ) ) != IVAS_ERR_OK ) { - return IVAS_ERROR( IVAS_ERR_NOT_SUPPORTED_OPTION, "PCA supported at SBA FOA 256 kbps only." ); + return error; } /*-----------------------------------------------------------------* @@ -887,6 +936,13 @@ static ivas_error configureEncoder( return error; } +#ifndef DISCRETE_ISM_DTX_CNG + if ( hEncoderConfig->Opt_DTX_ON && ( hEncoderConfig->ivas_format == ISM_FORMAT ) && !( st_ivas->ism_mode == ISM_MODE_DISC && hEncoderConfig->nchan_inp == 1 ) && !( st_ivas->ism_mode == ISM_MODE_PARAM && ( hEncoderConfig->nchan_inp == 3 || hEncoderConfig->nchan_inp == 4 ) ) ) + { + return IVAS_ERROR( IVAS_ERR_UNKNOWN, "DTX is not supported in this IVAS format and element mode." ); + } +#endif + if ( hEncoderConfig->ivas_format == MONO_FORMAT ) { hIvasEnc->hCoreCoder = st_ivas->hSCE[0]->hCoreCoder[0]; /* Note: this is needed for switching in EVS mono */ @@ -930,7 +986,7 @@ ivas_error IVAS_ENC_GetDelay( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - *delay = NS2SA( hEncoderConfig->input_Fs, (int32_t) ( get_delay( ENC, hEncoderConfig->input_Fs, hEncoderConfig->ivas_format, NULL, RENDERER_DISABLE, 0 ) + 0.5f ) ); + *delay = NS2SA( hEncoderConfig->input_Fs, get_delay( ENC, hEncoderConfig->input_Fs, hEncoderConfig->ivas_format, NULL ) ); *delay *= hEncoderConfig->nchan_inp; @@ -939,24 +995,36 @@ ivas_error IVAS_ENC_GetDelay( /*---------------------------------------------------------------------* - * IVAS_ENC_GetNumInputChannels() + * getInputBufferSize() * * *---------------------------------------------------------------------*/ -ivas_error IVAS_ENC_GetNumInputChannels( - const IVAS_ENC_HANDLE hIvasEnc, /* i : IVAS encoder handle */ - int16_t *numInChannels /* o : number of input channels with current */ +static int16_t getInputBufferSize( + const Encoder_Struct *st_ivas /* i : IVAS encoder handle */ ) { - if ( !hIvasEnc->isConfigured ) + return (int16_t) ( st_ivas->hEncoderConfig->input_Fs * st_ivas->hEncoderConfig->nchan_inp / FRAMES_PER_SEC ); +} + +/*---------------------------------------------------------------------* + * IVAS_ENC_GetNumInChannels() + * + * + *---------------------------------------------------------------------*/ +ivas_error IVAS_ENC_GetNumInChannels( + const IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ + int16_t *numInChannels /* o : total number of samples expected in the input buffer for current encoder configuration */ +) +{ + if ( hIvasEnc == NULL || numInChannels == NULL ) { - return IVAS_ERR_NOT_CONFIGURED; + return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - if ( numInChannels == NULL ) + if ( !hIvasEnc->isConfigured ) { - return IVAS_ERR_UNEXPECTED_NULL_POINTER; + return IVAS_ERR_NOT_CONFIGURED; } *numInChannels = hIvasEnc->st_ivas->hEncoderConfig->nchan_inp; @@ -965,20 +1033,6 @@ ivas_error IVAS_ENC_GetNumInputChannels( } -/*---------------------------------------------------------------------* - * getInputBufferSize() - * - * - *---------------------------------------------------------------------*/ - -static int16_t getInputBufferSize( - const Encoder_Struct *st_ivas /* i: IVAS encoder handle */ -) -{ - return (int16_t) ( st_ivas->hEncoderConfig->input_Fs * st_ivas->hEncoderConfig->nchan_inp / FRAMES_PER_SEC ); -} - - /*---------------------------------------------------------------------* * IVAS_ENC_GetInputBufferSize() * @@ -1042,6 +1096,11 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( return IVAS_ERR_INVALID_INPUT_BUFFER_SIZE; } + if ( ( error = sanitizeBandwidth( hIvasEnc ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( hEncoderConfig->ivas_format == ISM_FORMAT ) { for ( i = 0; i < hEncoderConfig->nchan_inp; ++i ) @@ -1320,7 +1379,7 @@ IVAS_ENC_DTX_CONFIG IVAS_ENC_GetDefaultDtxConfig( void ) IVAS_ENC_CHANNEL_AWARE_CONFIG IVAS_ENC_GetDefaultChannelAwareConfig( void ) { IVAS_ENC_CHANNEL_AWARE_CONFIG defaultCaConfig; - defaultCaConfig.channelAwareModeEnabled = false; + defaultCaConfig.channelAwareModeEnabled = 0; defaultCaConfig.fec_indicator = IVAS_ENC_FEC_HI; defaultCaConfig.fec_offset = 0; @@ -1343,7 +1402,9 @@ const char *IVAS_ENC_GetErrorMessage( case IVAS_ERR_OK: return "no error"; case IVAS_ERR_FAILED_ALLOC: - return "memory error"; + return "Failed allocation error"; + case IVAS_ERR_WRONG_PARAMS: + return "wrong parameters"; case IVAS_ERR_INVALID_BANDWIDTH: return "invalid bandwidth"; case IVAS_ERR_INVALID_DTX_UPDATE_RATE: @@ -1360,11 +1421,12 @@ const char *IVAS_ENC_GetErrorMessage( return "invalid bitrate"; case IVAS_ERR_INVALID_MASA_CONFIG: return "invalid MASA config"; - case IVAS_ERR_TOO_MANY_OBJECT_INPUTS: + case IVAS_ERR_TOO_MANY_INPUTS: return "too many object inputs provided"; case IVAS_ERR_INDEX_OUT_OF_BOUNDS: return "index out of bounds"; case IVAS_ERR_INTERNAL: + case IVAS_ERR_INTERNAL_FATAL: return "internal error"; case IVAS_ERR_RECONFIGURE_NOT_SUPPORTED: return "reconfigure not supported"; @@ -1388,6 +1450,8 @@ const char *IVAS_ENC_GetErrorMessage( return "mismatched timestamp"; case IVAS_ERR_ISM_FILE_READER_INVALID_METADATA_FORMAT: return "invalid metadata format"; + case IVAS_ERR_ISM_INVALID_METADATA_VALUE: + return "invalid metadata value provided"; case IVAS_ERR_FAILED_FILE_READ: return "could not read from file"; case IVAS_ERR_NOT_SUPPORTED_OPTION: @@ -1406,11 +1470,13 @@ const char *IVAS_ENC_GetErrorMessage( *---------------------------------------------------------------------*/ static ivas_error printConfigInfo_enc( - IVAS_ENC_HANDLE hIvasEnc ) + IVAS_ENC_HANDLE hIvasEnc, + const int16_t channelAwareModeEnabled ) { Encoder_Struct *st_ivas; ENCODER_CONFIG_HANDLE hEncoderConfig; - char max_bwidth_string[4]; + int16_t newBandwidthApi; + ivas_error error; st_ivas = hIvasEnc->st_ivas; hEncoderConfig = st_ivas->hEncoderConfig; @@ -1483,24 +1549,38 @@ static ivas_error printConfigInfo_enc( { if ( hEncoderConfig->ivas_total_brate <= ACELP_32k && hEncoderConfig->nchan_inp > 2 ) { - fprintf( stdout, "IVAS format: Param-ISm (%i streams)\n", hEncoderConfig->nchan_inp ); + fprintf( stdout, "IVAS format: Param-ISM (%i streams)\n", hEncoderConfig->nchan_inp ); } else { - fprintf( stdout, "IVAS format: ISm (%i streams)\n", hEncoderConfig->nchan_inp ); + fprintf( stdout, "IVAS format: ISM (%i streams)\n", hEncoderConfig->nchan_inp ); } } else if ( hEncoderConfig->ivas_format == SBA_FORMAT ) { - fprintf( stdout, "IVAS format: Scene Based Analysis %s ", hEncoderConfig->sba_planar ? "(Planar)" : "" ); + fprintf( stdout, "IVAS format: Scene Based Audio, Ambisonic order %i %s ", hEncoderConfig->sba_order, hEncoderConfig->sba_planar ? "(Planar)" : "" ); if ( hEncoderConfig->Opt_PCA_ON ) { fprintf( stdout, "- PCA configured with signal adaptive decision " ); } - if ( hEncoderConfig->Opt_AGC_ON ) + +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + switch ( hEncoderConfig->Opt_AGC_ON ) { - fprintf( stdout, "- AGC ON " ); + case SBA_AGC_FORCE_ENABLE: + fprintf( stdout, "- AGC FORCED ON " ); + break; + case SBA_AGC_FORCE_DISABLE: + fprintf( stdout, "- AGC FORCED OFF " ); + break; + case SBA_AGC_DEFAULT: + fprintf( stdout, "- AGC default mode " ); + break; + default: + fprintf( stdout, "- AGC unknown " ); + break; } +#endif fprintf( stdout, "\n" ); } else if ( hEncoderConfig->ivas_format == MASA_FORMAT ) @@ -1551,58 +1631,40 @@ static ivas_error printConfigInfo_enc( * Print potential limitation of audio bandwidth *-----------------------------------------------------------------*/ - switch ( hEncoderConfig->max_bwidth ) + if ( ( error = bandwidthApiToInternal( hIvasEnc->newBandwidthApi, &newBandwidthApi ) ) != IVAS_ERR_OK ) { - case NB: - strncpy( max_bwidth_string, "NB\0", sizeof( max_bwidth_string ) ); - break; - case WB: - strncpy( max_bwidth_string, "WB\0", sizeof( max_bwidth_string ) ); - break; - case SWB: - strncpy( max_bwidth_string, "SWB\0", sizeof( max_bwidth_string ) ); - break; - case FB: - strncpy( max_bwidth_string, "FB\0", sizeof( max_bwidth_string ) ); - break; + return error; } if ( st_ivas->hEncoderConfig->Opt_SC_VBR && !hEncoderConfig->Opt_DTX_ON ) { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "\nError: SC-VBR 5900 bps not supported without DTX\n\n" ); - } - - if ( hIvasEnc->maxBandwidthUser ) - { - fprintf( stdout, "\nBandwidth limited to %s.\n", max_bwidth_string ); - } - if ( hIvasEnc->maxBandwidthUser && hEncoderConfig->max_bwidth < FB && hEncoderConfig->input_Fs == 48000 ) - { - fprintf( stdout, "\nBandwidth limited to %s. To enable FB coding, please use -max_band FB.\n", max_bwidth_string ); + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "\nError: SC-VBR 5900 bps not supported without DTX\n\n" ); } if ( hEncoderConfig->ivas_format == MONO_FORMAT ) { - if ( hEncoderConfig->max_bwidth == FB && hEncoderConfig->ivas_total_brate < ACELP_16k40 ) + if ( newBandwidthApi != hEncoderConfig->max_bwidth ) { - fprintf( stdout, "\nFB coding not supported below %.2f kbps. ", ACELP_16k40 / 1000.f ); - if ( hEncoderConfig->ivas_total_brate < ACELP_9k60 ) + if ( newBandwidthApi == FB ) { - fprintf( stdout, "Switching to WB.\n" ); + fprintf( stdout, "\nFB coding not supported below %.2f kbps. ", ACELP_16k40 / 1000.f ); + if ( hEncoderConfig->max_bwidth == WB ) + { + fprintf( stdout, "Switching to WB.\n" ); + } + else + { + fprintf( stdout, "Switching to SWB.\n" ); + } } - else + else if ( newBandwidthApi == SWB ) { - fprintf( stdout, "Switching to SWB.\n" ); + fprintf( stdout, "\nSWB coding not supported below %.2f kbps. Switching to WB.\n", ACELP_9k60 / 1000.f ); } } - if ( hEncoderConfig->max_bwidth == SWB && hEncoderConfig->ivas_total_brate < ACELP_9k60 ) - { - fprintf( stdout, "\nSWB coding not supported below %.2f kbps. Switching to WB.", ACELP_9k60 / 1000.f ); - } - /* in case of 8kHz input sampling or "-max_band NB", require the total bitrate to be below 24.40 kbps */ - if ( ( hEncoderConfig->max_bwidth == NB || hEncoderConfig->input_Fs == 8000 ) && hEncoderConfig->ivas_total_brate > ACELP_24k40 ) + if ( ( newBandwidthApi == NB || hEncoderConfig->input_Fs == 8000 ) && hEncoderConfig->ivas_total_brate > ACELP_24k40 ) { fprintf( stdout, "\nError: Unsupported mode NB %d bps, NB mode supports rates 5900-24400 bps\n\n", hEncoderConfig->ivas_total_brate ); return IVAS_ERR_INVALID_BITRATE; @@ -1610,12 +1672,24 @@ static ivas_error printConfigInfo_enc( } else { - if ( hEncoderConfig->max_bwidth == FB && hEncoderConfig->ivas_total_brate < MIN_BRATE_FB_STEREO ) + if ( newBandwidthApi != hEncoderConfig->max_bwidth ) { fprintf( stdout, "\nFB coding not supported below %.2f kbps. Switching to SWB.\n", MIN_BRATE_FB_STEREO / 1000.f ); } } + /*-----------------------------------------------------------------* + * Print Channel-aware limitation + *-----------------------------------------------------------------*/ + + if ( channelAwareModeEnabled ) + { + if ( hEncoderConfig->Opt_RF_ON == 0 ) + { + fprintf( stdout, "\nChannel-aware mode is supported at 13.2 kbps 32/48 kHz only. Switching to normal mode.\n" ); + } + } + return IVAS_ERR_OK; } @@ -1632,6 +1706,7 @@ static ivas_error setBitrate( { Encoder_Struct *st_ivas; ENCODER_CONFIG_HANDLE hEncoderConfig; + ivas_error error; st_ivas = hIvasEnc->st_ivas; hEncoderConfig = st_ivas->hEncoderConfig; @@ -1678,6 +1753,18 @@ static ivas_error setBitrate( } } + if ( hEncoderConfig->ivas_format == ISM_FORMAT ) + { +#ifdef FIX_379_EXT_METADATA + if ( ( error = sanitizeBitrateISM( hEncoderConfig, hIvasEnc ) ) != IVAS_ERR_OK ) +#else + if ( ( error = sanitizeBitrateISM( hEncoderConfig ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + } + st_ivas->codec_mode = MODE1; if ( hEncoderConfig->element_mode_init == EVS_MONO ) @@ -1715,7 +1802,7 @@ static ivas_error setChannelAwareConfig( hEncoderConfig = st_ivas->hEncoderConfig; /* channel-aware mode is supported only at 13.20 kbps and with WB or SWB bandwidth */ - if ( ( hEncoderConfig->Opt_RF_ON && st_ivas->hEncoderConfig->ivas_total_brate != ACELP_13k20 ) || ( hEncoderConfig->Opt_RF_ON && hEncoderConfig->input_Fs == 8000 ) ) + if ( ( caConfig.channelAwareModeEnabled && st_ivas->hEncoderConfig->ivas_total_brate != ACELP_13k20 ) || ( hEncoderConfig->Opt_RF_ON && hEncoderConfig->input_Fs == 8000 ) ) { hEncoderConfig->Opt_RF_ON = 0; hEncoderConfig->rf_fec_offset = 0; @@ -1810,29 +1897,161 @@ static ivas_error doCommonSetterChecks( /*---------------------------------------------------------------------* - * updateBandwidthFromFs() + * sanitizeBandwidth() * * *---------------------------------------------------------------------*/ -static void updateBandwidthFromFs( - const ENCODER_CONFIG_HANDLE hEncoderConfig ) +static ivas_error sanitizeBandwidth( + const IVAS_ENC_HANDLE hIvasEnc ) { + ENCODER_CONFIG_HANDLE hEncoderConfig; + int16_t max_bwidth_tmp; + + hEncoderConfig = hIvasEnc->st_ivas->hEncoderConfig; + + max_bwidth_tmp = hIvasEnc->newBandwidthApi; + /* Prevent st_ivas->max_bwidth from being higher than Fs/2 */ - if ( hEncoderConfig->input_Fs == 8000 && hEncoderConfig->max_bwidth > NB ) + if ( hEncoderConfig->input_Fs == 8000 && max_bwidth_tmp > NB ) { - hEncoderConfig->max_bwidth = NB; + max_bwidth_tmp = NB; } - else if ( hEncoderConfig->input_Fs == 16000 && hEncoderConfig->max_bwidth > WB ) + else if ( hEncoderConfig->input_Fs == 16000 && max_bwidth_tmp > WB ) { - hEncoderConfig->max_bwidth = WB; + max_bwidth_tmp = WB; } - else if ( hEncoderConfig->input_Fs == 32000 && hEncoderConfig->max_bwidth > SWB ) + else if ( hEncoderConfig->input_Fs == 32000 && max_bwidth_tmp > SWB ) { - hEncoderConfig->max_bwidth = SWB; + max_bwidth_tmp = SWB; } - return; + /* NB coding not supported in IVAS. Switching to WB. */ + if ( max_bwidth_tmp == NB && hEncoderConfig->ivas_format != UNDEFINED_FORMAT && hEncoderConfig->ivas_format != MONO_FORMAT ) + { + if ( hEncoderConfig->input_Fs >= 16000 ) + { + max_bwidth_tmp = WB; + } + else + { + return IVAS_ERR_INVALID_BITRATE; + } + } + + if ( hEncoderConfig->ivas_format == MONO_FORMAT ) + { +#if 0 // IVAS_fmToDo: temporary disabled to keep EVS bit-exactness -> to be verified + if ( max_bwidth_tmp == FB && hEncoderConfig->ivas_total_brate < ACELP_16k40 ) + { + if ( hEncoderConfig->ivas_total_brate < ACELP_9k60 ) + { + max_bwidth_tmp = WB; + } + else + { + max_bwidth_tmp = SWB; + } + } + + if ( max_bwidth_tmp == SWB && hEncoderConfig->ivas_total_brate < ACELP_9k60 ) + { + max_bwidth_tmp = WB; + } + + /* in case of 8kHz input sampling or "-max_band NB", require the total bitrate to be below 24.40 kbps */ + if ( ( max_bwidth_tmp == NB || hEncoderConfig->input_Fs == 8000 ) && hEncoderConfig->ivas_total_brate > ACELP_24k40 ) + { + if ( hEncoderConfig->input_Fs >= 16000 ) + { + max_bwidth_tmp = WB; + } + else + { + return IVAS_ERR_INVALID_BITRATE; + } + } +#endif + } + else + { + if ( max_bwidth_tmp == FB && hEncoderConfig->ivas_total_brate < MIN_BRATE_FB_STEREO ) + { + max_bwidth_tmp = SWB; + } + } + + if ( hEncoderConfig->max_bwidth != max_bwidth_tmp ) + { + hEncoderConfig->max_bwidth = max_bwidth_tmp; + hIvasEnc->switchingActive = true; + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * sanitizeBitrateISM() + * + * + *---------------------------------------------------------------------*/ + +static ivas_error sanitizeBitrateISM( +#ifdef FIX_379_EXT_METADATA + const ENCODER_CONFIG_HANDLE hEncoderConfig, + const IVAS_ENC_HANDLE hIvasEnc ) +#else + const ENCODER_CONFIG_HANDLE hEncoderConfig ) +#endif +{ + if ( hEncoderConfig->ivas_total_brate > IVAS_128k && hEncoderConfig->nchan_inp == 1 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too high bitrate for 1 ISM specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } + + if ( hEncoderConfig->ivas_total_brate > IVAS_256k && hEncoderConfig->nchan_inp == 2 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too high bitrate for 2 ISM specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } + + if ( hEncoderConfig->ivas_total_brate > IVAS_384k && hEncoderConfig->nchan_inp == 3 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too high bitrate for 3 ISM specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } + + if ( hEncoderConfig->ivas_total_brate < IVAS_16k4 && hEncoderConfig->nchan_inp == 2 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for 2 ISM specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } + + if ( hEncoderConfig->ivas_total_brate < IVAS_24k4 && hEncoderConfig->nchan_inp == 3 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for 3 ISM specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } + + if ( hEncoderConfig->ivas_total_brate < IVAS_24k4 && hEncoderConfig->nchan_inp == 4 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for 4 ISM specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } + +#ifdef FIX_379_EXT_METADATA + if ( hIvasEnc->extMetadataApi ) + { + hEncoderConfig->ism_extended_metadata_flag = ( hEncoderConfig->ivas_total_brate >= ISM_EXTENDED_METADATA_BRATE ); + } + else + { + hEncoderConfig->ism_extended_metadata_flag = 0; + } +#else + if ( hEncoderConfig->ivas_total_brate < ISM_EXTENDED_METADATA_BRATE && hEncoderConfig->ism_extended_metadata_flag == 1 ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BITRATE, "Too low bitrate for extended metadata format specified in IVAS: %d", hEncoderConfig->ivas_total_brate ); + } +#endif + + return IVAS_ERR_OK; } @@ -1858,6 +2077,8 @@ static ivas_error setBandwidth( return error; } + hIvasEnc->newBandwidthApi = newBandwidth; + /* NB coding not supported in IVAS. Switching to WB. */ if ( newBandwidth == NB && hEncoderConfig->ivas_format != UNDEFINED_FORMAT && hEncoderConfig->ivas_format != MONO_FORMAT ) { @@ -1870,13 +2091,6 @@ static ivas_error setBandwidth( hIvasEnc->switchingActive = true; } - /* Limit bandwidth to half of sampling rate - only possible if - * sampling rate has already been set via configure function */ - if ( hIvasEnc->isConfigured ) - { - updateBandwidthFromFs( hIvasEnc->st_ivas->hEncoderConfig ); - } - return IVAS_ERR_OK; } @@ -1934,6 +2148,37 @@ static ivas_error bandwidthApiToInternal( return IVAS_ERR_OK; } +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION +/*---------------------------------------------------------------------* + * agcAPIToInternal() + * + * + *---------------------------------------------------------------------*/ + +static ivas_error agcAPIToInternal( + const IVAS_ENC_AGC agcOption, + int16_t *internalAGCOption ) +{ + switch ( agcOption ) + { + case IVAS_ENC_AGC_ENABLED: + *internalAGCOption = SBA_AGC_FORCE_ENABLE; + break; + case IVAS_ENC_AGC_DISABLED: + *internalAGCOption = SBA_AGC_FORCE_DISABLE; + break; + case IVAS_ENC_AGC_UNDEFINED: + *internalAGCOption = SBA_AGC_DEFAULT; + break; + default: + return IVAS_ERR_INVALID_AGC; + break; + } + + return IVAS_ERR_OK; +} +#endif + /*---------------------------------------------------------------------* * fecIndicatorApiToInternal() @@ -2011,13 +2256,12 @@ static ivas_error forcedModeApiToInternal( * *---------------------------------------------------------------------*/ -void IVAS_ENC_PrintConfig( - const IVAS_ENC_HANDLE hIvasDec /* i : IVAS encoder handle */ +ivas_error IVAS_ENC_PrintConfig( + const IVAS_ENC_HANDLE hIvasEnc, /* i : IVAS encoder handle */ + const int16_t channelAwareModeEnabled /* i : channel-aware mode enabled flag */ ) { - printConfigInfo_enc( hIvasDec ); - - return; + return printConfigInfo_enc( hIvasEnc, channelAwareModeEnabled ); } @@ -2045,11 +2289,14 @@ static void init_encoder_config( ENCODER_CONFIG_HANDLE hEncoderConfig /* o : configuration structure */ ) { + hEncoderConfig->ivas_total_brate = ACELP_12k65; hEncoderConfig->max_bwidth = SWB; hEncoderConfig->input_Fs = 16000; hEncoderConfig->nchan_inp = 1; hEncoderConfig->element_mode_init = EVS_MONO; hEncoderConfig->ivas_format = UNDEFINED_FORMAT; + hEncoderConfig->Opt_SC_VBR = 0; + hEncoderConfig->last_Opt_SC_VBR = 0; hEncoderConfig->Opt_AMR_WB = 0; hEncoderConfig->Opt_DTX_ON = 0; hEncoderConfig->Opt_RF_ON = 0; @@ -2057,16 +2304,22 @@ static void init_encoder_config( hEncoderConfig->rf_fec_indicator = 1; hEncoderConfig->interval_SID = FIXED_SID_RATE; hEncoderConfig->var_SID_rate_flag = 1; + hEncoderConfig->mc_input_setup = MC_LS_SETUP_INVALID; + hEncoderConfig->stereo_dmx_evs = 0; +#ifdef NCHAN_ISM_PARAMETER + hEncoderConfig->nchan_ism = 0; +#endif + hEncoderConfig->sba_order = 0; + hEncoderConfig->sba_planar = 0; + hEncoderConfig->ism_extended_metadata_flag = 0; #ifdef DEBUGGING hEncoderConfig->stereo_mode_cmdl = 0; hEncoderConfig->force = -1; hEncoderConfig->mdct_stereo_mode_cmdl = SMDCT_MS_DECISION; +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + hEncoderConfig->Opt_AGC_ON = SBA_AGC_DEFAULT; +#endif #endif - hEncoderConfig->mc_input_setup = MC_LS_SETUP_INVALID; - hEncoderConfig->stereo_dmx_evs = 0; - hEncoderConfig->sba_order = 0; - hEncoderConfig->sba_planar = 0; - hEncoderConfig->Opt_AGC_ON = 0; hEncoderConfig->Opt_PCA_ON = 0; return; diff --git a/lib_enc/lib_enc.h b/lib_enc/lib_enc.h index b8744a27318c574587238d505a71693b2a6a5cd6..349c41ebef721a1b65be35235e7a17e63a1de4e4 100644 --- a/lib_enc/lib_enc.h +++ b/lib_enc/lib_enc.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,9 +34,7 @@ #define LIB_ENC_H #include "common_api_types.h" -#include "ivas_error.h" #include -#include /*---------------------------------------------------------------------* @@ -71,19 +69,6 @@ typedef struct _IVAS_ENC_DTX_CONFIG int16_t SID_interval; } IVAS_ENC_DTX_CONFIG; -#ifdef DEBUGGING -typedef enum _IVAS_ENC_STEREO_MODE -{ - IVAS_ENC_STEREO_MODE_UNIFIED, - IVAS_ENC_STEREO_MODE_DFT, - IVAS_ENC_STEREO_MODE_TD, - IVAS_ENC_STEREO_MODE_MDCT_DECISION, - IVAS_ENC_STEREO_MODE_MDCT_FORCE_LR, - IVAS_ENC_STEREO_MODE_MDCT_FORCE_MS, - IVAS_ENC_STEREO_MODE_UNDEFINED = 0xffff -} IVAS_ENC_STEREO_MODE; -#endif /* DEBUGGING */ - typedef enum _IVAS_ENC_SBA_ORDER { IVAS_ENC_SBA_FOA = 1, @@ -110,6 +95,17 @@ typedef enum _IVAS_ENC_MASA_VARIANT } IVAS_ENC_MASA_VARIANT; #ifdef DEBUGGING +typedef enum _IVAS_ENC_STEREO_MODE +{ + IVAS_ENC_STEREO_MODE_UNIFIED, + IVAS_ENC_STEREO_MODE_DFT, + IVAS_ENC_STEREO_MODE_TD, + IVAS_ENC_STEREO_MODE_MDCT_DECISION, + IVAS_ENC_STEREO_MODE_MDCT_FORCE_LR, + IVAS_ENC_STEREO_MODE_MDCT_FORCE_MS, + IVAS_ENC_STEREO_MODE_UNDEFINED = 0xffff +} IVAS_ENC_STEREO_MODE; + typedef enum _IVAS_ENC_FORCED_MODE { IVAS_ENC_FORCE_SPEECH, @@ -121,27 +117,21 @@ typedef enum _IVAS_ENC_FORCED_MODE IVAS_ENC_FORCE_UNFORCED, IVAS_ENC_FORCE_UNDEFINED = 0xffff } IVAS_ENC_FORCED_MODE; -#endif -typedef enum _IVAS_ENC_FEC_INDICATOR +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION +typedef enum _IVAS_ENC_AGC { - IVAS_ENC_FEC_LO, - IVAS_ENC_FEC_HI, - IVAS_ENC_FEC_UNDEFINED = 0xffff -} IVAS_ENC_FEC_INDICATOR; - + IVAS_ENC_AGC_DISABLED = 0, + IVAS_ENC_AGC_ENABLED, + IVAS_ENC_AGC_UNDEFINED = 0xffff +} IVAS_ENC_AGC; +#endif +#endif /*---------------------------------------------------------------------* * Encoder structures *---------------------------------------------------------------------*/ -typedef struct _IVAS_ENC_CHANNEL_AWARE_CONFIG -{ - bool channelAwareModeEnabled; - IVAS_ENC_FEC_INDICATOR fec_indicator; - int16_t fec_offset; -} IVAS_ENC_CHANNEL_AWARE_CONFIG; - typedef struct IVAS_ENC *IVAS_ENC_HANDLE; /* clang-format off */ @@ -190,7 +180,8 @@ ivas_error IVAS_ENC_ConfigureForObjects( const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ - const uint16_t numObjects /* i : number of objects to be encoded */ + const uint16_t numObjects, /* i : number of objects to be encoded */ + const bool ism_extended_metadata /* i : Extended metadata used (true/false), where extended metadata includes radius and orientation */ ); /*! r: error code */ @@ -203,8 +194,14 @@ ivas_error IVAS_ENC_ConfigureForAmbisonics( const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ const IVAS_ENC_SBA_ORDER order, /* i : order of the Ambisonics input */ const bool isPlanar, /* i : if true, input is treated as planar Ambisonics */ - const bool Opt_AGC_ON, /* i : AGC on/off flag */ +#ifdef DEBUG_AGC_ENCODER_CMD_OPTION + const IVAS_ENC_AGC Opt_AGC_ON, /* i : AGC on/off/undefined flag */ +#endif const bool Opt_PCA_ON /* i : PCA option flag */ +#ifdef DEBUG_SBA_AUDIO_DUMP + , + int16_t *numTransportChannels +#endif ); /*! r: error code */ @@ -303,9 +300,9 @@ ivas_error IVAS_ENC_GetDelay( ); /*! r: encoder error code */ -ivas_error IVAS_ENC_GetNumInputChannels( +ivas_error IVAS_ENC_GetNumInChannels( const IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - int16_t *numInChannels /* o : number of input channels with current configuration */ + int16_t *numInChannels /* o : total number of samples expected in the input buffer for current encoder configuration */ ); /*! r: encoder error code */ @@ -336,8 +333,9 @@ const char *IVAS_ENC_GetErrorMessage( ); -void IVAS_ENC_PrintConfig( - const IVAS_ENC_HANDLE hIvasDec /* i : IVAS encoder handle */ +ivas_error IVAS_ENC_PrintConfig( + const IVAS_ENC_HANDLE hIvasEnc, /* i : IVAS encoder handle */ + const int16_t channelAwareModeEnabled /* i : channel-aware mode enabled flag */ ); void IVAS_ENC_PrintDisclaimer( diff --git a/lib_enc/long_enr.c b/lib_enc/long_enr.c index 3dc098af6193abf26bed2f8374d0417432204bc5..c520c642c786962bda2c1e7a83e395c526514b3a 100644 --- a/lib_enc/long_enr.c +++ b/lib_enc/long_enr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * long_enr() @@ -67,6 +67,7 @@ void long_enr( * Compute long term estimate of total noise energy * and total active speech energy *-----------------------------------------------------------------*/ + if ( hFrontVad != NULL ) { if ( hFrontVad[0]->ini_frame < 4 ) @@ -114,6 +115,12 @@ void long_enr( } } } + + /* Update */ + for ( n = 0; n < n_chan; n++ ) + { + hFrontVad[n]->hNoiseEst->Etot_last = Etot_LR[n]; + } } else { @@ -150,6 +157,9 @@ void long_enr( } } } + + /* Update */ + st->hNoiseEst->Etot_last = Etot; } return; diff --git a/lib_enc/lp_exc_e.c b/lib_enc/lp_exc_e.c index e8078c5e0e2d5eb921690a045cefa93bc70bdac8..4fb81a9b75bdade7e74cb2007975462ec4cc3846 100644 --- a/lib_enc/lp_exc_e.c +++ b/lib_enc/lp_exc_e.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/lsf_enc.c b/lib_enc/lsf_enc.c index a6d973b36ef654c53bb9f23aae09e7343b982410..052bfbe96e5756518e94fe0c634fa9fb3fb9aa2e 100644 --- a/lib_enc/lsf_enc.c +++ b/lib_enc/lsf_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -49,14 +49,13 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants *-----------------------------------------------------------------*/ -#define MSVQ_MAXCNT 3000 /* was 300 */ -#define LOWEMPH_LSFI 1.0f /* bigger value means more weight for lower frequencies */ +#define MSVQ_MAXCNT 3000 /*---------------------------------------------------------------------* @@ -1020,7 +1019,7 @@ void first_VQstages( dist[0] = dist_buf; dist[1] = dist_buf + maxC; - set_s( idx_buf, 0, ( const int16_t )( 2 * stagesVQ * maxC ) ); + set_s( idx_buf, 0, 2 * stagesVQ * maxC ); set_s( parents, 0, maxC ); /* Set up inital distance vector */ diff --git a/lib_enc/lsf_msvq_ma_enc.c b/lib_enc/lsf_msvq_ma_enc.c index bf115aa6719b35f8a114d13e2ee3721995cc2efa..a620dfac384f499c5d779d0048fc1ac5d0b89ece 100644 --- a/lib_enc/lsf_msvq_ma_enc.c +++ b/lib_enc/lsf_msvq_ma_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_com.h" #include "rom_enc.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" #define kMaxC 8 @@ -120,14 +120,14 @@ void msvq_enc( cb_stage = cbp; /* Set up pointers to parent and current nodes */ -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP swap( indices[0], indices[1], int16_t * ); MOVE( 3 ); swap( resid[0], resid[1], float * ); MOVE( 3 ); swap( dist[0], dist[1], float * ); MOVE( 3 ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /* p_max points to maximum distortion node (worst of best) */ p_max = 0; diff --git a/lib_enc/ltd_stable.c b/lib_enc/ltd_stable.c index 5650f93e67bb0dc32ce7b0c2fdee50a2f6992f44..a6222a411f11a1e43573879233718d283f85a885 100644 --- a/lib_enc/ltd_stable.c +++ b/lib_enc/ltd_stable.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * ltd_stable() diff --git a/lib_enc/mdct_classifier.c b/lib_enc/mdct_classifier.c index ae7e6f7e3f31513688134da43ddf34cc21a12a44..f26b1277336fbf9352d52af1d7d5a224129de3b6 100644 --- a/lib_enc/mdct_classifier.c +++ b/lib_enc/mdct_classifier.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" #include diff --git a/lib_enc/mdct_selector.c b/lib_enc/mdct_selector.c index 1f118d23d2d03bd73ca3ef02b10970c07fd2b79c..45f3d3174c982e4f3f1434221e419f4a863a70e9 100644 --- a/lib_enc/mdct_selector.c +++ b/lib_enc/mdct_selector.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants diff --git a/lib_enc/mslvq_enc.c b/lib_enc/mslvq_enc.c index 3f7c0715ff592c8b52b735101d9d8728ee84a339..e4e98ea1e63e79e1b27af55cc2f97aedffb34973 100644 --- a/lib_enc/mslvq_enc.c +++ b/lib_enc/mslvq_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "prot.h" #include "rom_com.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /*-----------------------------------------------------------------* @@ -537,7 +537,7 @@ void index_lvq( float *quant, /* i : codevector to be indexed (2 8-dim subvectors) */ int16_t *idx_lead, /* i : leader class index for each subvector */ int16_t *idx_scale, /* i : scale index for each subvector */ - const int16_t mode, /* i : integer signalling the quantizer structure for the current bitrate */ + const int16_t mode, /* i : integer signaling the quantizer structure for the current bitrate */ int16_t *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ const int16_t prediction_flag ) { diff --git a/lib_enc/multi_harm.c b/lib_enc/multi_harm.c index 4427b3376c4cec7121e5ff4d31fc2df5a74db434..c53371e28dc58a5520acd01b3d517c021bc15c74 100644 --- a/lib_enc/multi_harm.c +++ b/lib_enc/multi_harm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants diff --git a/lib_enc/nelp_enc.c b/lib_enc/nelp_enc.c index 8f8f407749e6b7cc59aeb0e5255e9a146cb37ede..a1ae3c20d733696eb296c5e78c63a3329faadcb2 100644 --- a/lib_enc/nelp_enc.c +++ b/lib_enc/nelp_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * quantize_uvg() diff --git a/lib_enc/nois_est.c b/lib_enc/nois_est.c index b8d551a738cea3cb7eb59d1949dfcfe5bb3fd2e2..50dab410281d7ae6e98b803c6a792242b37f9981 100644 --- a/lib_enc/nois_est.c +++ b/lib_enc/nois_est.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constants @@ -232,7 +232,7 @@ void noise_est_pre( /*-----------------------------------------------------------------* * noise_est_down() * - * Down-ward noise udatation routine + * Down-ward noise updatation routine * Total Noise computation, relative frame Energy computation * Noise energy update - here, the energy is updated only if it is * decreasing to improve noise suppression. Otherwise, the noise @@ -298,6 +298,7 @@ void noise_est_down( *------------------------------------------------------------------*/ Etot_v = (float) fabs( *Etot_last - Etot ); + *Etot_v_h2 = ( 1.0f - 0.02f ) * *Etot_v_h2 + 0.02f * min( 3.0f, Etot_v ); if ( *Etot_v_h2 < 0.1f ) { diff --git a/lib_enc/noise_adjust.c b/lib_enc/noise_adjust.c index 5d592d071bf05340a0ed48f75f711f3852e68398..0ba9bd45370e6c1ad28770dddbde4f4aff15c429 100644 --- a/lib_enc/noise_adjust.c +++ b/lib_enc/noise_adjust.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * noise_adjust() diff --git a/lib_enc/normalizecoefs.c b/lib_enc/normalizecoefs.c index 7e039f171e43e2deb13761f78c5707337c69bf74..bd24f2cd2bd2c2ab654ba60dc72cbe3410edc26c 100644 --- a/lib_enc/normalizecoefs.c +++ b/lib_enc/normalizecoefs.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------- * normalizecoefs() diff --git a/lib_enc/peak_vq_enc.c b/lib_enc/peak_vq_enc.c index a77f071112164ee5d99ba68c1b21d53a2c50444b..efdd0b14a90e251da397e8235bfd037c7b2b97ee 100644 --- a/lib_enc/peak_vq_enc.c +++ b/lib_enc/peak_vq_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #include /*-------------------------------------------------------------------------- diff --git a/lib_enc/pit_enc.c b/lib_enc/pit_enc.c index f2c518bd3d007ad19892e7f6aa83146b61af6b2b..d8d51e2a1b7a977b89fc5cc2ea6e488482e8db62 100644 --- a/lib_enc/pit_enc.c +++ b/lib_enc/pit_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "rom_enc.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * pit_encode() @@ -622,7 +622,6 @@ void norm_corr( for ( t = t_min; t <= t_max; t++ ) { /* Compute correlation between xn[] and excf[] */ - ps = 0.0f; for ( j = 0; j < L_subfr; ++j ) { @@ -630,7 +629,6 @@ void norm_corr( } /* Compute 1/sqrt(energie of excf[]) */ - alp = 0.01f; for ( j = 0; j < L_subfr; ++j ) { diff --git a/lib_enc/pitch_ol.c b/lib_enc/pitch_ol.c index 72d454fd3037e9697d4e3680b905112bcd524dc8..8f149a35d8893c6f12924f2ce058f54278a506d2 100644 --- a/lib_enc/pitch_ol.c +++ b/lib_enc/pitch_ol.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #include "cnst.h" #include "rom_com.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_enc/pitch_ol2.c b/lib_enc/pitch_ol2.c index 13f5bd33de6cb6adcc3ca404baf382d57ea5f10b..bc414158e1605fc92c5d3a9a6b21652a7b360b96 100644 --- a/lib_enc/pitch_ol2.c +++ b/lib_enc/pitch_ol2.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_enc.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local constants diff --git a/lib_enc/plc_enc_ext.c b/lib_enc/plc_enc_ext.c index 70b573c5a9aa9cac9d02d1296d27ab3829c1b25a..8e5cfc382da8a37a93807869ed3fae2213181c61 100644 --- a/lib_enc/plc_enc_ext.c +++ b/lib_enc/plc_enc_ext.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,11 +37,10 @@ #include #include "options.h" #include "prot.h" -#include "typedef.h" #include "stat_enc.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #define NBITS_GACELP 5 diff --git a/lib_enc/ppp_enc.c b/lib_enc/ppp_enc.c index 887be74fd573e906e6a16abac4735b1f05ee5ac0..d55cb135dd440de26da83b9d845347779fbf9915 100644 --- a/lib_enc/ppp_enc.c +++ b/lib_enc/ppp_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -355,11 +355,12 @@ ivas_error ppp_quarter_encoder( push_indice( hBstr, IND_GLOBAL_ALIGNMENT, (int16_t) ( tmp + 3 ), 3 ); - count_free( PREVDTFS ); + free( PREVDTFS ); return error; } + /*-------------------------------------------------------------------* * set_ppp_mode() * diff --git a/lib_enc/pre_proc.c b/lib_enc/pre_proc.c index 6b25d86df33f47229c095e222c609b8f3dfcfbed..feb0df75ca24bd5feabfe8006d6ce07b51746384 100644 --- a/lib_enc/pre_proc.c +++ b/lib_enc/pre_proc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -59,7 +59,6 @@ void pre_proc( float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ float **inp, /* o : ptr. to inp. signal in the current frame*/ float fr_bands[2 * NB_BANDS], /* i : energy in frequency bands */ - float *Etot, /* i : total energy */ float *ener, /* o : residual energy from Levinson-Durbin */ #ifndef FIX_I4_OL_PITCH int16_t pitch_orig[3], /* o : open-loop pitch values for quantization */ @@ -84,6 +83,7 @@ void pre_proc( float old_wsp[L_WSP], *wsp; /* weighted input signal buffer */ float pitch_fr[NB_SUBFR]; /* fractional pitch values */ float voicing_fr[NB_SUBFR]; /* fractional pitch gains */ + float Etot; /* total energy */ float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ float tmpN[NB_BANDS]; /* Temporary noise update */ float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ @@ -118,7 +118,7 @@ void pre_proc( int16_t clas_mod; int16_t old_pitch1; - wmops_sub_start( "pre_proc" ); + push_wmops( "pre_proc" ); /*------------------------------------------------------------------* * Initialization @@ -190,14 +190,16 @@ void pre_proc( * Spectral analysis *--------------------------------------------------------------------------*/ - analy_sp( -1, NULL, st->input_Fs, inp_12k8, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, Etot, st->min_band, st->max_band, band_energies, PS, fft_buff ); + analy_sp( -1, NULL, st->input_Fs, inp_12k8, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, &Etot, st->min_band, st->max_band, band_energies, PS, fft_buff ); /*----------------------------------------------------------------* * SAD (1-signal, 0-noise) *----------------------------------------------------------------*/ - noise_est_pre( *Etot, st->ini_frame, st->hNoiseEst, 0, EVS_MONO, EVS_MONO ); + noise_est_pre( Etot, st->ini_frame, st->hNoiseEst, 0, EVS_MONO, EVS_MONO ); + st->vad_flag = wb_vad( st, fr_bands, &noisy_speech_HO, &clean_speech_HO, &NB_speech_HO, &snr_sum_he, &localVAD_HE_SAD, &( st->flag_noisy_speech_snr ), NULL, NULL, -1000.0f, -1000.0f ); + vad_flag_cldfb = vad_proc( realBuffer, imagBuffer, enerBuffer, st->cldfbAnaEnc->no_channels, st->hVAD_CLDFB, &cldfb_addition, st->vad_flag ); if ( st->Pos_relE_cnt < 20 ) /* Ensure the level is high enough and cldfb decision is reliable */ @@ -211,13 +213,18 @@ void pre_proc( st->vad_flag = vad_flag_cldfb; } - vad_flag_dtx = dtx_hangover_addition( st, st->vad_flag, st->lp_speech - st->lp_noise, cldfb_addition, vad_hover_flag, NULL, NULL ); + vad_flag_dtx = dtx_hangover_addition( st, st->vad_flag, st->lp_speech - st->lp_noise, cldfb_addition, vad_hover_flag, NULL, NULL, NULL ); /*----------------------------------------------------------------* * NB/WB/SWB/FB bandwidth detector *----------------------------------------------------------------*/ - bw_detect( st, st->input, NULL, enerBuffer ); + bw_detect( st, st->input, NULL, enerBuffer +#ifdef FIX_MDCT_BASED_BWD + , + 0 +#endif + ); /*----------------------------------------------------------------* * Noise energy down-ward update and total noise energy estimation @@ -225,9 +232,9 @@ void pre_proc( * Correlation correction as a function of total noise level *----------------------------------------------------------------*/ - noise_est_down( fr_bands, st->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->hNoiseEst->totalNoise, *Etot, &st->hNoiseEst->Etot_last, &st->hNoiseEst->Etot_v_h2 ); + noise_est_down( fr_bands, st->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->hNoiseEst->totalNoise, Etot, &st->hNoiseEst->Etot_last, &st->hNoiseEst->Etot_v_h2 ); - relE = *Etot - st->lp_speech; + relE = Etot - st->lp_speech; if ( relE > 1.5f ) { @@ -250,8 +257,7 @@ void pre_proc( /*-----------------------------------------------------------------* * Select SID or FRAME_NO_DATA frame if DTX enabled *-----------------------------------------------------------------*/ - - dtx( st, vad_flag_dtx, inp_12k8 ); + dtx( st, -1, vad_flag_dtx, inp_12k8 ); /*----------------------------------------------------------------* * Adjust FD-CNG Noise Estimator @@ -353,7 +359,7 @@ void pre_proc( * Update estimated noise energy and voicing cut-off frequency *-----------------------------------------------------------------*/ - noise_est( st, old_pitch1, tmpN, epsP, *Etot, relE, corr_shift, tmpE, fr_bands, &cor_map_sum, NULL, &sp_div, &non_staX, &loc_harm, lf_E, &st->hNoiseEst->harm_cor_cnt, st->hNoiseEst->Etot_l_lp, &sp_floor, 0, NULL, NULL, st->ini_frame ); + noise_est( st, old_pitch1, tmpN, epsP, Etot, relE, corr_shift, tmpE, fr_bands, &cor_map_sum, NULL, &sp_div, &non_staX, &loc_harm, lf_E, &st->hNoiseEst->harm_cor_cnt, st->hNoiseEst->Etot_l_lp, &sp_floor, 0, NULL, NULL, st->ini_frame ); /*------------------------------------------------------------------* * Update parameters used in the VAD and DTX @@ -368,7 +374,7 @@ void pre_proc( find_tilt( fr_bands, st->hNoiseEst->bckr, ee, st->pitch, st->voicing, lf_E, corr_shift, st->input_bwidth, st->max_band, hp_E, st->codec_mode, &( st->bckr_tilt_lt ), st->Opt_SC_VBR ); - st->coder_type = find_uv( st, pitch_fr, voicing_fr, inp_12k8, ee, NULL, corr_shift, relE, *Etot, hp_E, &flag_spitch, last_core_orig, NULL ); + st->coder_type = find_uv( st, pitch_fr, voicing_fr, inp_12k8, ee, NULL, corr_shift, relE, Etot, hp_E, &flag_spitch, last_core_orig, NULL ); /*-----------------------------------------------------------------* * channel aware mode configuration * @@ -422,8 +428,9 @@ void pre_proc( st->GSC_IVAS_mode = 0; - speech_music_classif( st, new_inp_12k8, inp_12k8, localVAD_HE_SAD, lsp_new, cor_map_sum, epsP, PS, *Etot, old_cor, attack_flag, non_staX, relE, &high_lpn_flag, flag_spitch ); - long_enr( st, *Etot, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); + speech_music_classif( st, new_inp_12k8, inp_12k8, localVAD_HE_SAD, lsp_new, cor_map_sum, epsP, PS, Etot, old_cor, attack_flag, non_staX, relE, &high_lpn_flag, flag_spitch ); + + long_enr( st, Etot, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); /*----------------------------------------------------------------* * Final VAD correction ( when HE-SAD is used instead of the normal VAD, @@ -575,7 +582,7 @@ void pre_proc( } if ( st->total_brate == ACELP_13k20 && st->bwidth != FB ) { - MDCT_selector( st, sp_floor, *Etot, cor_map_sum, enerBuffer ); + MDCT_selector( st, sp_floor, Etot, cor_map_sum, enerBuffer ); } } else @@ -614,7 +621,12 @@ void pre_proc( st->gamma = GAMMA16k; } - st->igf = getIgfPresent( EVS_MONO, st->total_brate, st->bwidth, st->rf_mode, MCT_CHAN_MODE_REGULAR ); /* TBV: needs checking */ + st->igf = getIgfPresent( EVS_MONO, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + MCT_CHAN_MODE_REGULAR +#endif + ); } st->coder_type = st->coder_type_raw; @@ -707,7 +719,7 @@ void pre_proc( } } - /* channel-aware mode - due to lack of signalling bit, sharpFlag is 1 always in RF mode */ + /* channel-aware mode - due to lack of signaling bit, sharpFlag is 1 always in RF mode */ if ( st->rf_mode && ( st->coder_type == VOICED || st->coder_type == GENERIC ) ) { st->sharpFlag = 1; @@ -871,7 +883,7 @@ void pre_proc( if ( st->total_brate == ACELP_16k40 && st->bwidth != FB ) { - MDCT_selector( st, sp_floor, *Etot, cor_map_sum, enerBuffer ); + MDCT_selector( st, sp_floor, Etot, cor_map_sum, enerBuffer ); } } else @@ -959,6 +971,6 @@ void pre_proc( } } - wmops_sub_end(); + pop_wmops(); return; } diff --git a/lib_enc/pvq_core_enc.c b/lib_enc/pvq_core_enc.c index 3603b950e9bc32f8ec9209dab730cf035367c0e9..5876c8b44a129572c1f36a16c3b2c9dc0452e824 100644 --- a/lib_enc/pvq_core_enc.c +++ b/lib_enc/pvq_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "prot.h" #include "stl.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_enc/pvq_encode.c b/lib_enc/pvq_encode.c index acf7928a6faf4b6c1f6ce890dd8a878b8fb38116..eb066e8ed20fcad4dbfff05f4a7ea8da4e3b11ad 100644 --- a/lib_enc/pvq_encode.c +++ b/lib_enc/pvq_encode.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" static void pyramidSearch( const float *const s, const int16_t L, const int16_t Ptot, const float A, int16_t *ztak, float *stak ); diff --git a/lib_enc/q_gain2p.c b/lib_enc/q_gain2p.c index 8a3bc04b9a86cc7efd717b713bd6b8d6ac339bc6..9c89b44c8753110da3c354b7b0bc6a2cf43c5cb8 100644 --- a/lib_enc/q_gain2p.c +++ b/lib_enc/q_gain2p.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------------* * Local function prototypes diff --git a/lib_enc/qlpc_avq.c b/lib_enc/qlpc_avq.c index 03aeab128e90a8441cbedd83741aa1e5a76350f5..eabbd8128fe80fc718d334d7f0f66b3c0177ca86 100644 --- a/lib_enc/qlpc_avq.c +++ b/lib_enc/qlpc_avq.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include "prot.h" #include "ivas_prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * qlpc_avq() diff --git a/lib_enc/qlpc_stoch.c b/lib_enc/qlpc_stoch.c index 7723f507ec18ac446eaaa128f7b7ea95ea83d54f..8defb07034305ca3298c61478317cd05da8952fa 100644 --- a/lib_enc/qlpc_stoch.c +++ b/lib_enc/qlpc_stoch.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "rom_com.h" #include "rom_enc.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * lpc_quantization() @@ -101,7 +101,6 @@ void lpc_quantization( } /****** Low-rate LPC quantizer *******/ - else if ( st->lpcQuantization == 1 ) { diff --git a/lib_enc/range_enc.c b/lib_enc/range_enc.c index d44ed895a4f7d0a1b04a0d9ae7324a5584f3d399..8ea8c888d22c5d64de577c2346db9c9ba4fd3030 100644 --- a/lib_enc/range_enc.c +++ b/lib_enc/range_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes diff --git a/lib_enc/re8_cod.c b/lib_enc/re8_cod.c index 30030cc394b23a994b8e077bf8e5fa821ccc7465..5facffd8f448caeb2534eecc3aa7913ba5fdc7ec 100644 --- a/lib_enc/re8_cod.c +++ b/lib_enc/re8_cod.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------ diff --git a/lib_enc/reordernorm.c b/lib_enc/reordernorm.c index 2387263aab5abdab44b792ceda6ce65215b78415..831adeee53b0f55aa6b0fb940ff66cf31e73d847 100644 --- a/lib_enc/reordernorm.c +++ b/lib_enc/reordernorm.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------*/ /* Function reordernorm */ diff --git a/lib_enc/rom_enc.c b/lib_enc/rom_enc.c index cc9755ce9243d13f63d47f6f2bfb557a55d4cffe..ae96fdfc31744efad74681b5e509fddc89182a65 100644 --- a/lib_enc/rom_enc.c +++ b/lib_enc/rom_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /* clang-format off */ diff --git a/lib_enc/rom_enc.h b/lib_enc/rom_enc.h index e3e62cb6e90e8021da1118b9f49061709b7b6c4e..7e7659ceb6a46baa1066bf5af7af2096ae5f367a 100644 --- a/lib_enc/rom_enc.h +++ b/lib_enc/rom_enc.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_enc/rst_enc.c b/lib_enc/rst_enc.c index ac8853c7211666ae99d0daf14736eec1137740cd..3a2041875941a62f4e4b09796f49084332c77ad4 100644 --- a/lib_enc/rst_enc.c +++ b/lib_enc/rst_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * CNG_reset_enc() @@ -84,8 +84,11 @@ void CNG_reset_enc( set_f( voice_factors, 1.0, NB_SUBFR16k ); - /* Reset active frame counter */ - st->hTdCngEnc->act_cnt2 = 0; + if ( st->hTdCngEnc != NULL ) + { + /* Reset active frame counter */ + st->hTdCngEnc->act_cnt2 = 0; + } /* deactivate bass post-filter */ st->bpf_off = 1; diff --git a/lib_enc/set_impulse.c b/lib_enc/set_impulse.c index 493d373d1ecb897b7144fb2d5249569fc340fd19..4cafeea9e8a253a5b53ee88df65a4e91b0e5796d 100644 --- a/lib_enc/set_impulse.c +++ b/lib_enc/set_impulse.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local constant diff --git a/lib_enc/setmodeindex.c b/lib_enc/setmodeindex.c index 199933fbaf247d1e116433f0f210924d61a6a662..b2187b89908a93a706682a39516e06b35a8c7cd9 100644 --- a/lib_enc/setmodeindex.c +++ b/lib_enc/setmodeindex.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "prot.h" #include "cnst.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------- @@ -55,10 +55,11 @@ ---------------------------------------------------------------------------*/ void SetModeIndex( - Encoder_State *st, - const int32_t last_total_brate, - const int16_t last_element_mode, - const int16_t is_mct ) + Encoder_State *st, /* i : Encoder state */ + const int32_t last_total_brate, /* i : last total bitrate */ + const int16_t last_element_mode, /* i : last IVAS element mode */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +) { int16_t ini_frame_loc = st->ini_frame; @@ -75,10 +76,9 @@ void SetModeIndex( ( st->rf_mode_last != st->rf_mode ) || ( st->element_mode > EVS_MONO && st->ini_frame == 0 ) ) { - core_coder_mode_switch( st, last_total_brate, is_mct ); + core_coder_mode_switch( st, last_total_brate, MCT_flag ); } - st->ini_frame = ini_frame_loc; return; diff --git a/lib_enc/sig_clas.c b/lib_enc/sig_clas.c index c1438b6b7686d6fd0dfd1801ab861446ef5c9ee6..18ee55df61e0d504d8bd2503ebfc4d4fcef08fbc 100644 --- a/lib_enc/sig_clas.c +++ b/lib_enc/sig_clas.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local constants diff --git a/lib_enc/spec_center.c b/lib_enc/spec_center.c index f565cba7a8eb23f8c2a86fff1fb84a47a202a993..73835a15117876c83542e86b9c1327ed57edfdf3 100644 --- a/lib_enc/spec_center.c +++ b/lib_enc/spec_center.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "prot.h" #include "rom_enc.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * spec_center() diff --git a/lib_enc/spec_flatness.c b/lib_enc/spec_flatness.c index 2ef6bd3b606bf1f6487ded483384eaea312706e1..0473cc6b983950b3b8f880c205fda63f1bfa36f0 100644 --- a/lib_enc/spec_flatness.c +++ b/lib_enc/spec_flatness.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "options.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * spec_flatness() diff --git a/lib_enc/speech_music_classif.c b/lib_enc/speech_music_classif.c index a61e42c1646254ddef87ee57d26ed054bc06cafc..cf8568e649db982127b0cd978a935d7f28b97b2f 100644 --- a/lib_enc/speech_music_classif.c +++ b/lib_enc/speech_music_classif.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "ivas_prot.h" #include "rom_enc.h" #include "rom_com.h" /* Common static table prototypes */ -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 910a31f2dc4beb00c51b9e31f60bea28be2f94e8..ec7fb594d1a9d6c326de1f3964f895fd1c7ba01b 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -123,6 +123,8 @@ typedef struct float firState1; float firState2; + int16_t ramp_up_flag; /* bit map flags to indicate a ramp up in beginning of TCX frame */ + } SubblockEnergies; @@ -138,8 +140,8 @@ typedef struct TransientDetector TCheckSubblocksForAttack CheckSubblocksForAttack; /* Function for checking a presence of an attack. */ float attackRatioThreshold; /* Attack ratio threshold. */ int16_t bIsAttackPresent; /* True when an attack was detected. */ + int16_t prev_bIsAttackPresent; /* True if an attack was detected in the previous frame. */ int16_t attackIndex; /* The index of an attack. */ - } TransientDetector; /* Transient detection: Holds all transient detectors and buffers used by them. */ @@ -1156,8 +1158,7 @@ typedef struct enc_core_structure int16_t Opt_AMR_WB; /* flag indicating AMR-WB IO mode */ int16_t Opt_DTX_ON; /* flag indicating DTX operation */ int16_t cng_type; /* flag indicating LP or CLDFB based SID/CNG */ - int16_t cng_dirac_flag; /* flag indicating CNG/SID for DirAC 2TC */ - int16_t cng_spar_flag; /* flag indicating CNG/SID for SPAR 2TC */ + int16_t cng_sba_flag; /* flag indicating CNG/SID for SBA 2TC */ int16_t Opt_SC_VBR; /* flag indicating SC-VBR mode */ int16_t last_Opt_SC_VBR; /* flag indicating prev frame's SC-VBR mode */ int16_t low_rate_mode; /* low-rate mode flag */ diff --git a/lib_enc/stat_noise_uv_enc.c b/lib_enc/stat_noise_uv_enc.c index 3cb876097b9b35fe2c531fba1c6282f97749e98d..a1adfb052a7c3e3f3ba070f27343d8b0e62ffe14 100644 --- a/lib_enc/stat_noise_uv_enc.c +++ b/lib_enc/stat_noise_uv_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -41,7 +41,7 @@ #endif #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * stat_noise_uv_enc() diff --git a/lib_enc/subband_fft.c b/lib_enc/subband_fft.c index 9f02fa04aeec09ad1e2ab133dca047ab2b76b764..638a6d63f830bc1e24cf4575d3e9e201c9296d50 100644 --- a/lib_enc/subband_fft.c +++ b/lib_enc/subband_fft.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include #include "prot.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/swb_bwe_enc.c b/lib_enc/swb_bwe_enc.c index b54fbede575842fc8f7055eb93c303136fdb30ad..e2c8812eca9d6b2af15435b40b5dc5a16162eed5 100644 --- a/lib_enc/swb_bwe_enc.c +++ b/lib_enc/swb_bwe_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -46,7 +46,7 @@ #include "rom_enc.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * Local function prototypes @@ -1361,7 +1361,9 @@ static int16_t SWB_BWE_encoding( st->hBWE_FD->EnergyLF = energy; } + calc_tilt_bwe( insig, &tilt, L_FRAME32k ); + if ( IsTransient == 1 && ( tilt > 8.0 || st->clas > 1 ) ) { IsTransient = 0; @@ -1793,6 +1795,11 @@ void hq_generic_hf_encoding( { Word16 tmp, frac, exp; Word32 L_tmp; +#ifdef BASOP_NOGLOB + Flag Overflow; + + Overflow = 0; +#endif tmp = add( (int16_t) ( hq_generic_fenv[n_band] * 256 ), (int16_t) ( Mean_env[n_band] * 256 ) ); /*Q8 */ L_tmp = L_mult( tmp, 21771 ); /* 0.166096 in Q17 -> Q26 */ @@ -1803,7 +1810,11 @@ void hq_generic_hf_encoding( /* output of Pow2() will be: */ /* 16384 < Pow2() <= 32767 */ exp = sub( exp, 13 ); - tmp = shl( tmp, add( exp, 1 ) ); /*Q1 */ +#ifdef BASOP_NOGLOB + tmp = shl_o( tmp, add( exp, 1 ), &Overflow ); /*Q1 */ +#else + tmp = shl( tmp, add( exp, 1 ) ); /*Q1 */ +#endif hq_generic_fenv[n_band] = (float) tmp * 0.5f; /*Q1 */ } diff --git a/lib_enc/swb_bwe_enc_hr.c b/lib_enc/swb_bwe_enc_hr.c index 63e5753650fdb51b1bf2bf3a7c7f1db2b250d6d6..7b2f3687a0dc69eda51d3528ad6598920ac293b2 100644 --- a/lib_enc/swb_bwe_enc_hr.c +++ b/lib_enc/swb_bwe_enc_hr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * en_band_quant() diff --git a/lib_enc/swb_bwe_enc_lr.c b/lib_enc/swb_bwe_enc_lr.c index 7273972d7c463f186bad04d6e2b0dffb0d2ae7fb..afa9e75ac792c6d74bc4b5e1b1ef7dcbdc0a91d6 100644 --- a/lib_enc/swb_bwe_enc_lr.c +++ b/lib_enc/swb_bwe_enc_lr.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "stat_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*--------------------------------------------------------------------------* * GetSubbandCorrIndex2_har() diff --git a/lib_enc/swb_pre_proc.c b/lib_enc/swb_pre_proc.c index 99c410ed47298a963fd54cc446df7262a7c0a6dc..3ec175958aa4e12f12a2c33c95522e050f00f9cd 100644 --- a/lib_enc/swb_pre_proc.c +++ b/lib_enc/swb_pre_proc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" #include "ivas_rom_enc.h" @@ -287,17 +287,15 @@ void swb_pre_proc( FD_BWE_ENC_HANDLE hBWE_FD; int32_t inner_Fs, input_Fs; float old_input[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; - float spchTmp[640]; - int16_t i, j; + float spchTmp[L_FRAME32k], spchTmp2[L_FRAME32k]; + int16_t i, j, L_resamp; int16_t startB, endB; float *realBufferFlipped[CLDFB_NO_COL_MAX]; float *imagBufferFlipped[CLDFB_NO_COL_MAX]; float realBufferTmp[CLDFB_NO_COL_MAX][20]; float imagBufferTmp[CLDFB_NO_COL_MAX][20]; int16_t ts, nB, uB; - float sign; - float lbEner, v, t; - float regression; + float sign, lbEner, v, t, regression; const float *thr, *regV; int16_t Sample_Delay_SWB_BWE32k, lMemRecalc32k, dft_ovl32k; @@ -677,35 +675,50 @@ void swb_pre_proc( } else { - if ( st->bwidth == FB || st->core == ACELP_CORE || ( st->element_mode == IVAS_CPE_DFT && input_Fs == 48000 ) ) + if ( ( st->bwidth == FB || st->core == ACELP_CORE ) && ( st->element_mode == EVS_MONO ) ) { - set_f( hBWE_TD->old_speech_shb, 0, L_LOOK_16k + L_SUBFR16k ); - set_f( shb_speech, 0, L_FRAME16k ); /* shb_speech for FB/SWB BWE_HIGHRATE is not used at 64kbps */ - set_f( st->hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); - set_f( st->hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); - st->hBWE_TD->old_mean_EnvSHBres = 0.0f; - st->hBWE_TD->prev_enr_EnvSHBres = 1.0f; - st->hBWE_TD->prev_shb_env_tilt = 0.0f; - st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; - st->hBWE_TD->prev_mix_factor = 1.0f; - st->hBWE_TD->prev_Env_error = 0.0f; - - if ( st->element_mode == IVAS_CPE_DFT ) - { - set_f( hCPE->hStereoDft->output_mem_dmx_16k_shb, 0, STEREO_DFT_OVL_16k ); - } + InitSWBencBufferStates( st->hBWE_TD, shb_speech ); } else { - /* flip the spectrm */ - mvr2r( new_swb_speech, spchTmp, L_FRAME32k ); + if ( st->element_mode == IVAS_CPE_DFT ) + { + if ( st->L_frame == L_FRAME ) + { + L_resamp = 560; /* 6.4 kHz core -> 6 - 14 kHz SHB target. 20 ms is 560 samples in 28 kHz sample rate */ + } + else + { + L_resamp = 620; /* 8 kHz core -> 7.5 - 15.5 kHz SHB target. 20 ms is 620 samples in 31 kHz sample rate */ + } + + /* Dirty downsampling to match Nyquist to upper frequency limit of target */ + lerp( st->input, new_swb_speech, L_resamp, (int16_t) ( input_Fs / 50 ) ); - for ( i = 0; i < L_FRAME32k; i = i + 2 ) + /* flip the spectrum */ + mvr2r( new_swb_speech, spchTmp, L_resamp ); + for ( i = 0; i < L_resamp; i = i + 2 ) + { + spchTmp[i] = -spchTmp[i]; + } + + /* Dirty upsampling to match Nyquist/2 to lower frequency limit of target (reversed spectrum)*/ + lerp( spchTmp, spchTmp2, L_FRAME32k, L_resamp ); + mvr2r( spchTmp2, spchTmp, L_FRAME32k ); + } + else { - spchTmp[i] = -spchTmp[i]; + /* flip the spectrum */ + mvr2r( new_swb_speech, spchTmp, L_FRAME32k ); + + for ( i = 0; i < L_FRAME32k; i = i + 2 ) + { + spchTmp[i] = -spchTmp[i]; + } } Decimate_allpass_steep( spchTmp, hBWE_TD->state_ana_filt_shb, L_FRAME32k, shb_speech ); + mvr2r( shb_speech + L_FRAME16k - ( L_LOOK_16k + L_SUBFR16k ), hBWE_TD->old_speech_shb, L_LOOK_16k + L_SUBFR16k ); /*Compute the past overlap for potential next iDFTs SHB*/ @@ -723,13 +736,16 @@ void swb_pre_proc( /* Reset CLDFB synthesis buffer */ set_f( st->cldfbSynTd->cldfb_state, 0.0f, st->cldfbSynTd->p_filter_length ); } + else + { + hCPE->hStereoDft->flip_sign = -hCPE->hStereoDft->flip_sign; /* Make sure sign is updated even if DFT SHB target is not generated */ + } } /* Memory reset to compensate for 0.9375 ms offset when transitioning from IO to SWB */ /* When switching from n >1 to n = 1, we keep the enc/dec delay as 8.75/3.25 and below code not needed; only when n = 1 start, it will be 9.6875/2.3125 in that case this reset is needed for IO->BWE.*/ - /* IVAS_fmToDo: revisit for IVAS (the condition is currently entered for both TD and DFT stereo - is it desirable?) */ - if ( st->last_extl == -1 ) + if ( st->last_extl == -1 && st->element_mode == EVS_MONO ) { delay = NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ); for ( i = 0; i < delay; i++ ) diff --git a/lib_enc/swb_tbe_enc.c b/lib_enc/swb_tbe_enc.c index 32b1118c15bc7d33c5711fe006e5a2d766d024ed..38a0fb73ff28753dcc9b97b21e722cc1cfe3f00f 100644 --- a/lib_enc/swb_tbe_enc.c +++ b/lib_enc/swb_tbe_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /*-----------------------------------------------------------------* @@ -63,7 +63,7 @@ static void return_M_Least( const float *inp, const int16_t n_cols, const float static void singlevectortest_gain( const float *inp, const int16_t dimen, const int16_t cb_size, int16_t *index, const float *weight, float *recon, const float *codebook ); static void determine_gain_weights( const float *gain, float *weights, const int16_t dims ); static void QuantizeSHBsubgains( Encoder_State *st, float *subgains, const int16_t extl ); -static void QuantizeSHBframegain( Encoder_State *st, float *GainFrame, const int16_t extl, const int32_t extl_brate, int16_t *rf_gainFrame_ind, int16_t flag_conservative ); +static void QuantizeSHBframegain( Encoder_State *st, float *GainFrame, const int16_t extl, const int32_t extl_brate, int16_t *rf_gainFrame_ind, const int16_t flag_conservative ); static int16_t closest_centroid( const float *data, const float *weights, const float *quantizer, const int16_t centroids, const int16_t length ); static void EstimateSHBFrameGain( const int16_t length, const float *oriSHB, const float *synSHB, float *subgain, float *GainFrame, const float *win_shb, const float *subwin ); static void EstimateSHBGainShape( const int16_t length, const float *oriSHB, const float *synSHB, float *subgain, const float *subwin ); @@ -76,9 +76,9 @@ static void gainFrSmooth_En( TD_BWE_ENC_HANDLE hBWE_TD, const int16_t last_extl, static void Quant_BWE_LSF( BSTR_ENC_HANDLE hBstr, TD_BWE_ENC_HANDLE hBWE_TD, const int16_t codec_mode, const float lsp_shb[], float Q_lsfs[], const int32_t extl_brate ); static void Quant_shb_ener_sf( Encoder_State *st, float *shb_ener_sf ); static void Quant_shb_res_gshape( Encoder_State *st, float *shb_res_gshape ); - static void LVQQuant_BWE_LSF( BSTR_ENC_HANDLE hBstr, const float lsf_shb[], float Q_lsfs[], int16_t nbits ); + /*-------------------------------------------------------------------* * InitSWBencBuffer() * @@ -108,14 +108,8 @@ void InitSWBencBuffer( set_f( hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); set_f( hBWE_TD->old_speech_wb, 0.0f, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); set_f( hBWE_TD->old_input_fhb, 0.0f, NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) - L_FRAME48k / 2 ); - set_f( hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); - set_f( hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); - hBWE_TD->old_mean_EnvSHBres = 0.0f; - hBWE_TD->prev_enr_EnvSHBres = 1.0f; - hBWE_TD->prev_shb_env_tilt = 0.0f; - hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; - hBWE_TD->prev_mix_factor = 1.0f; - hBWE_TD->prev_Env_error = 0.0f; + + InitSWBencBufferStates( hBWE_TD, NULL ); for ( i = 0; i < LPC_SHB_ORDER; i++ ) { @@ -156,6 +150,36 @@ void InitSWBencBuffer( } +/*-------------------------------------------------------------------* + * InitSWBencBufferStates() + * + * Initialize SWB buffer states + *-------------------------------------------------------------------*/ + +void InitSWBencBufferStates( + TD_BWE_ENC_HANDLE hBWE_TD, /* i/o: TD BWE data handle */ + float *shb_speech /* o : SHB target signal (6-14kHz) at 16kHz */ +) +{ + if ( shb_speech != NULL ) + { + set_f( shb_speech, 0.0f, L_FRAME16k ); + } + + set_f( hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); + set_f( hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); + set_f( hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); + hBWE_TD->old_mean_EnvSHBres = 0.0f; + hBWE_TD->prev_enr_EnvSHBres = 1.0f; + hBWE_TD->prev_shb_env_tilt = 0.0f; + hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; + hBWE_TD->prev_mix_factor = 1.0f; + hBWE_TD->prev_Env_error = 0.0f; + + return; +} + + /*-------------------------------------------------------------------* * ResetSHBbuffer_Enc() * @@ -405,7 +429,9 @@ void wb_tbe_enc( p2m_in = pow_off_pk_corrected( GainShape, NUM_SHB_SUBFR / 4, 1 ); } else + { p2m_in = pow_off_pk( GainShape, NUM_SHB_SUBFR / 4, 1 ); + } if ( st->extl_brate == WB_TBE_0k35 ) { @@ -428,7 +454,9 @@ void wb_tbe_enc( p2m_out = pow_off_pk_corrected( GainShape, NUM_SHB_SUBFR / 2, 2 ); } else + { p2m_out = pow_off_pk( GainShape, NUM_SHB_SUBFR / 2, 2 ); + } /* Estimate the gain parameter */ EstimateSHBFrameGain( SHB_OVERLAP_LEN / 2, hb_frame, shaped_wb_excitation, GainShape, &GainFrame, window_wb, subwin_wb ); @@ -475,13 +503,11 @@ void wb_tbe_enc( if ( st->rf_mode ) { - QuantizeSHBframegain( st, &GainFrame, st->extl, st->extl_brate, &st->hRF->RF_bwe_gainFr_ind, - 0 ); + QuantizeSHBframegain( st, &GainFrame, st->extl, st->extl_brate, &st->hRF->RF_bwe_gainFr_ind, 0 ); } else { - QuantizeSHBframegain( st, &GainFrame, st->extl, st->extl_brate, NULL, - 0 ); + QuantizeSHBframegain( st, &GainFrame, st->extl, st->extl_brate, NULL, 0 ); } /* Adjust the subframe and frame gain of the synthesized SHB signal */ @@ -557,7 +583,6 @@ void swb_tbe_enc( float sum_gain, normFact; float Env_error_part[NUM_SHB_SUBGAINS]; - Env_error = 0.0f; pitBufAvg = 0.0f; voicingBufAvg = 0.0f; @@ -1172,7 +1197,9 @@ void swb_tbe_enc( p2m_in = pow_off_pk_corrected( GainShape, NUM_SHB_SUBGAINS, 1 ); } else + { p2m_in = pow_off_pk( GainShape, NUM_SHB_SUBGAINS, 1 ); + } /* Quantization of the gain shape parameter */ QuantizeSHBsubgains( st, GainShape, st->extl ); @@ -1183,7 +1210,9 @@ void swb_tbe_enc( p2m_out = pow_off_pk_corrected( GainShape, NUM_SHB_SUBFR, 4 ); } else + { p2m_out = pow_off_pk( GainShape, NUM_SHB_SUBFR, 4 ); + } /* Gain shape smoothing after quantization */ if ( st->extl_brate == SWB_TBE_1k10 || st->extl_brate == SWB_TBE_1k75 ) @@ -1362,13 +1391,11 @@ void swb_tbe_enc( /* Quantization of the frame gain parameter */ if ( st->rf_mode ) { - QuantizeSHBframegain( st, &GainFrame, st->extl, 0, &st->hRF->RF_bwe_gainFr_ind, - 0 ); + QuantizeSHBframegain( st, &GainFrame, st->extl, 0, &st->hRF->RF_bwe_gainFr_ind, 0 ); } else { - QuantizeSHBframegain( st, &GainFrame, st->extl, 0, NULL, - ( st->extl_brate == SWB_TBE_1k10 || st->extl_brate == SWB_TBE_1k75 ) ? 1 : 0 ); + QuantizeSHBframegain( st, &GainFrame, st->extl, 0, NULL, ( st->extl_brate == SWB_TBE_1k10 || st->extl_brate == SWB_TBE_1k75 ) ? 1 : 0 ); } if ( hStereoICBWE != NULL ) @@ -1568,7 +1595,6 @@ static float pow_off_pk( * pow_off_pk_corrected() * * Sums squares of SWB shape gain parameters away from peak values - * VM: !! includes correction of indexing !! *-------------------------------------------------------------------*/ static float pow_off_pk_corrected( @@ -1974,7 +2000,6 @@ static void LVQQuant_BWE_LSF( int16_t i, c2, dim1 = 6; int16_t levels[1], numbits_VQ; - float w[8] = { 5.0f, 5.0f, 2.0f, 2.0f, 2.0f, 1.0f, 1.0f, 1.0f }; float cand[LPC_SHB_ORDER], quant[LPC_SHB_ORDER], e[2], ftmp; const float *cb_stage; @@ -2306,7 +2331,6 @@ static void Quant_shb_ener_sf( ) { int16_t idxSubEner; - float temp_shb_ener_sf, sum; sum = *shb_ener_sf; @@ -2344,6 +2368,7 @@ static void Quant_shb_res_gshape( for ( i = 0; i < NB_SUBFR16k; i++ ) { idxSubGain[i] = usquant( shb_res_gshape[i], &shb_res_gshape[i], 0.125, 0.125f, 1 << NUM_BITS_SHB_RES_GS ); + if ( st->codec_mode == MODE2 ) { st->hBWE_TD->idx_res_gs[i] = idxSubGain[i]; @@ -2369,7 +2394,7 @@ static void QuantizeSHBframegain( const int16_t extl, /* i : extension layer */ const int32_t extl_brate, /* i : extension layer bitrate */ int16_t *rf_gainFrame_ind, - int16_t flag_conservative /* i : flag to indicate more conservative gain quantization */ + const int16_t flag_conservative /* i : flag to indicate more conservative gain quantization */ ) { int16_t idxFrameGain; @@ -2634,7 +2659,6 @@ static void return_M_Least( return; } - /*-------------------------------------------------------------------* * fb_tbe_reset_enc() * @@ -2725,13 +2749,12 @@ void fb_tbe_enc( } else { - push_indice( st->hBstr, IND_FB_SLOPE, idxGain, 4 ); + push_indice( st->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN_TBE ); } return; } - /*---------------------------------------------------------------------* * tbe_write_bitstream() * @@ -2811,7 +2834,6 @@ void tbe_write_bitstream( return; } - /*---------------------------------------------------------------------* * TBEreset_enc() * diff --git a/lib_enc/tcq_core_enc.c b/lib_enc/tcq_core_enc.c index 11d96e2015eb17302e8bc96449af051a7d36a38f..aad3e54e7366f33374b6da098ca9d94e8ee81370 100644 --- a/lib_enc/tcq_core_enc.c +++ b/lib_enc/tcq_core_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "cnst.h" #include "basop_util.h" #include "basop_proto_func.h" -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------------* * tcq_core_LR_enc() @@ -181,7 +181,7 @@ ivas_error tcq_core_LR_enc( } } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP bsub_fx = L_shl( L_add( tcq_arbits, lsbtcq_bits ), 16 ); IF( bsub_fx > 0 ) { @@ -206,7 +206,7 @@ ivas_error tcq_core_LR_enc( } srt_vec_ind_fx( Rk_fx, Rk_sort_fx, k_sort, BANDS ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP /* Quantize spectral band shapes using TCQ */ /* Select ISC */ @@ -282,7 +282,7 @@ ivas_error tcq_core_LR_enc( if ( Rk_fx[k_sort[k]] > 0 && surplus_fx < 0 ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP IF( nzbands <= 1 ) { divider = 0; @@ -302,7 +302,7 @@ ivas_error tcq_core_LR_enc( delta_fx = 0; } surplus_fx = L_sub( surplus_fx, delta_fx ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP } else { @@ -311,13 +311,13 @@ ivas_error tcq_core_LR_enc( } } -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP if ( ( L_sub( surplus_fx, 524288 ) > 0 && sub( input_frame, L_FRAME8k ) == 0 ) || ( L_sub( surplus_fx, 786432 ) > 0 && sub( input_frame, L_FRAME16k ) == 0 ) ) { bit_surplus_fx[0] = Mult_32_16( surplus_fx, 24576 ); /* Q16 */ bit_surplus_fx[1] = Mult_32_16( surplus_fx, 8192 ); /* Q16 */ } -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP else { bit_surplus_fx[0] = surplus_fx; @@ -329,9 +329,9 @@ ivas_error tcq_core_LR_enc( { if ( k == k_num[j] ) { -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP Rk_fx[k_sort[k]] = L_add( Rk_fx[k_sort[k]], bit_surplus_fx[j] ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP if ( Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) /* Then have non-zero block AND WILL BE ENCODED BY TCQ */ { diff --git a/lib_enc/tcx_ltp_enc.c b/lib_enc/tcx_ltp_enc.c index fbac9b164075f5f00c9473f7618e50960a0613fa..0ea2e0424a4ddca8a922ce4b8cee25d905c5d3a9 100644 --- a/lib_enc/tcx_ltp_enc.c +++ b/lib_enc/tcx_ltp_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "prot.h" #include "rom_enc.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_PLOT #include "deb_out.h" #endif diff --git a/lib_enc/tcx_utils_enc.c b/lib_enc/tcx_utils_enc.c index ca88663355cb349f91be35da433e65ecea5bd9d8..ba709f0158fee7c34847204f8e5984c5a50b61c9 100644 --- a/lib_enc/tcx_utils_enc.c +++ b/lib_enc/tcx_utils_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "rom_com.h" #include "cnst.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /*---------------------------------------------------------------------* @@ -1509,7 +1509,7 @@ void ProcessStereoIGF( Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ int16_t ms_mask[2][MAX_SFB], /* i : bandwise MS mask */ float *pITFMDCTSpectrum[CPE_CHANNELS][2], /* i : MDCT spectrum fir ITF */ - float pPowerSpectrum[CPE_CHANNELS][N_MAX], /* i : MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ float *pPowerSpectrumMsInv[CPE_CHANNELS][2], /* i : inverse power spectrum */ float *inv_spectrum[CPE_CHANNELS][2], /* i : inverse spectrum */ const int16_t frameno, /* i : flag indicating index of current subfr. */ diff --git a/lib_enc/tfa_enc.c b/lib_enc/tfa_enc.c index dca8b62623ed05cb1a44540637b4d7d668e5379f..50dd7c36687fd0faf46ecdc78805c99a99599b53 100644 --- a/lib_enc/tfa_enc.c +++ b/lib_enc/tfa_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * tfaCalcEnv() diff --git a/lib_enc/tns_base_enc.c b/lib_enc/tns_base_enc.c index f008ed728fbf9dd34ebfde9ae98559bc355b4c4a..594f7824111edb5568679dea1315f25c5a431918 100644 --- a/lib_enc/tns_base_enc.c +++ b/lib_enc/tns_base_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,7 +37,7 @@ #include #include #include "options.h" -#include "wmops.h" +#include "wmc_auto.h" #include "cnst.h" #include "rom_com.h" #include "prot.h" diff --git a/lib_enc/transient_detection.c b/lib_enc/transient_detection.c index 469c7c4d8d0f0bb10ff49837504a3455a8309bd4..83f9e2e7a09e26353b7a8ded866256d33fae89d4 100644 --- a/lib_enc/transient_detection.c +++ b/lib_enc/transient_detection.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,7 +44,7 @@ #include "prot.h" #include "ivas_prot.h" #include -#include "wmops.h" +#include "wmc_auto.h" /*---------------------------------------------------------------* @@ -53,6 +53,12 @@ #define MIN_BLOCK_ENERGY 107.37f +#define THR_HIGH 8.5f +#define THR_NORM_HIGH 8.0f +#define THR_NORM_LOW 4.5f +#define THR_LOW 4.25f +#define THR_LOW_STEP 1.0f + /*---------------------------------------------------------------* * Local function prototypes @@ -218,6 +224,7 @@ void RunTransientDetection( float filteredInput[L_FRAME_MAX]; SubblockEnergies *pSubblockEnergies = &hTranDet->subblockEnergies; TransientDetector *pTransientDetector = &hTranDet->transientDetector; + float e0, e1; assert( ( input != NULL ) && ( hTranDet != NULL ) && ( pSubblockEnergies != NULL ) && ( pTransientDetector != NULL ) ); @@ -233,10 +240,22 @@ void RunTransientDetection( /* Update the delay buffer. */ UpdateDelayBuffer( filteredInput, length, &hTranDet->delayBuffer ); + /* compute ramp up flag */ + pSubblockEnergies->ramp_up_flag = pSubblockEnergies->ramp_up_flag << 1; + e0 = dotp( filteredInput + length / 2, filteredInput + length / 2, pSubblockEnergies->pDelayBuffer->nSubblockSize / 2 ) + 0.5f * MIN_BLOCK_ENERGY; + e1 = pSubblockEnergies->subblockNrg[pSubblockEnergies->nDelay + 4] - e0; + if ( e1 > e0 ) + { + pSubblockEnergies->ramp_up_flag |= 0x0001; + } + return; } -static uint16_t isLongTermTransient( const float frameTFM, float *lastTFM ) + +static uint16_t isLongTermTransient( + const float frameTFM, + float *lastTFM ) { float currTFM; @@ -250,11 +269,13 @@ static uint16_t isLongTermTransient( const float frameTFM, float *lastTFM ) { currTFM = *lastTFM * 0.96875f + frameTFM * 0.03125f; } + *lastTFM = max( 0.015625f, currTFM ); return ( currTFM < 0.5625f ? 1 : 0 ); } + /*-------------------------------------------------------------------* * SetTCXModeInfo() * @@ -303,17 +324,18 @@ void SetTCXModeInfo( hTcxEnc->tcxMode = NO_TCX; } } - +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode == MCT_CHAN_MODE_LFE ) { hTcxEnc->tcxMode = TCX_20; *tcxModeOverlap = FULL_OVERLAP; st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; } - - +#endif +#ifndef ISSUE_24_CLEANUP_MCT_LFE if ( st->mct_chan_mode != MCT_CHAN_MODE_LFE ) { +#endif /* set the left window overlap */ if ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) { @@ -382,7 +404,9 @@ void SetTCXModeInfo( hTcxEnc->tfm_mem = 0.75f; } } +#ifndef ISSUE_24_CLEANUP_MCT_LFE } +#endif /* for the ACELP -> TCX transition frames use full right window overlap */ if ( ( st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) && ( *tcxModeOverlap == ALDO_WINDOW ) ) @@ -556,7 +580,9 @@ static void InitTransientDetector( pTransientDetector->CheckSubblocksForAttack = pCheckSubblocksForAttack; pTransientDetector->attackRatioThreshold = attackRatioThreshold; pTransientDetector->bIsAttackPresent = FALSE; + pTransientDetector->prev_bIsAttackPresent = FALSE; pTransientDetector->attackIndex = -1; + pTransientDetector->pSubblockEnergies->ramp_up_flag = 0x0; return; } @@ -609,9 +635,9 @@ static void RunTransientDetector( assert( ( pTransientDetector->CheckSubblocksForAttack != NULL ) ); /* Variable initialization */ -#define WMC_TOOL_MAN +#define WMC_TOOL_SKIP pTransientDetector->CheckSubblocksForAttack( pSubblockNrg, pAccSubblockNrg, NSUBBLOCKS + nDelay, nRelativeDelay, attackRatioThreshold, &pTransientDetector->bIsAttackPresent, &pTransientDetector->attackIndex ); -#undef WMC_TOOL_MAN +#undef WMC_TOOL_SKIP return; } @@ -824,3 +850,99 @@ void set_transient_stereo( return; } + +/*-------------------------------------------------------------------* + * transient_analysis() + * + * + *-------------------------------------------------------------------*/ + +/*! r: preliminary flag to force ACELP */ +int16_t transient_analysis( + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + const float cor_map_LT[], /* i : LT correlation map */ + const float multi_harm_limit /* i : multi harminic threshold */ +) +{ + const float *pSubblockNrg; + float accSubblockNrgRev[NSUBBLOCKS]; /* store acc Nrg in reversed signal */ + float *pTmp; /* point to acc Nrg */ + int16_t offset; + int16_t i; + float thr_fwd; + float thr_rev; + const int16_t nRelativeDelay = hTranDet->subblockEnergies.nDelay - hTranDet->transientDetector.nDelay; + int16_t prel_force_td; + float cor_map_LT_sum; + + pTmp = &accSubblockNrgRev[NSUBBLOCKS - 1]; + offset = nRelativeDelay - 4; + prel_force_td = FALSE; + + /* summation of the LT correlation map */ + cor_map_LT_sum = sum_f( cor_map_LT, L_FFT / 2 ); /* Note maybe BE optimized by computing inside noise_est */ + + thr_fwd = THR_NORM_HIGH; + if ( cor_map_LT_sum > multi_harm_limit * 0.8f ) + { + thr_fwd = THR_HIGH; + } + thr_rev = THR_LOW; + if ( cor_map_LT_sum > multi_harm_limit * 0.6f ) + { + thr_rev = THR_NORM_LOW; + } + + /* forward attack analysis */ + for ( i = -2; i < 7; i++ ) + { + if ( hTranDet->subblockEnergies.subblockNrg[nRelativeDelay + i] > hTranDet->subblockEnergies.accSubblockNrg[nRelativeDelay + i] * thr_fwd ) + { + prel_force_td |= 0x0001; + } + } + if ( prel_force_td == 0 && hTranDet->transientDetector.prev_bIsAttackPresent == 1 ) + { + /* release analysis */ + pSubblockNrg = hTranDet->transientDetector.pSubblockEnergies->subblockNrg; + set_zero( accSubblockNrgRev, NSUBBLOCKS ); + + for ( i = NSUBBLOCKS - 1; i > -1; i-- ) + { + if ( i == NSUBBLOCKS - 1 ) + { + accSubblockNrgRev[i] = pSubblockNrg[i + offset]; + } + else + { + accSubblockNrgRev[i] = *pTmp; + *pTmp *= hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg; + if ( pSubblockNrg[i + offset] > *pTmp ) + { + *pTmp = pSubblockNrg[i + offset]; + } + } + } + + /* -3 check */ + if ( pSubblockNrg[1 + offset] > accSubblockNrgRev[1] * thr_rev ) + { + prel_force_td |= 0x0002; + } + + /* -4 check */ + if ( prel_force_td == 0 && pSubblockNrg[offset] > accSubblockNrgRev[0] * thr_rev ) + { + if ( pSubblockNrg[offset] > accSubblockNrgRev[0] * ( thr_rev + THR_LOW_STEP ) ) + { + prel_force_td |= 0x0004; + } + else if ( ( hTranDet->subblockEnergies.ramp_up_flag & 0x0002 ) != 0 ) + { + prel_force_td |= 0x0008; + } + } + } + + return prel_force_td != 0; +} diff --git a/lib_enc/transition_enc.c b/lib_enc/transition_enc.c index 9b3acee612de33f2d334089def1ec3d1952a98d5..ce13d7fa36ecf6e44293c41ba52b8c9f49efd7bf 100644 --- a/lib_enc/transition_enc.c +++ b/lib_enc/transition_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------* * Local function prototypes @@ -178,8 +178,7 @@ void transition_enc( if ( *tc_subfr == TC_0_0 ) { /* this is called only to compute unused bits */ - config_acelp1( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, L_FRAME, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, TRANSITION, TC_0_0, 3, NULL, unbits_ACELP, st->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st->idchan, 0 /*tdm_Pitch_reuse_flag*/, st->tdm_LRTD_flag, 0 /*GSC_IVAS_mode*/ - ); + config_acelp1( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, L_FRAME, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, TRANSITION, TC_0_0, 3, NULL, unbits_ACELP, st->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st->idchan, 0 /*tdm_Pitch_reuse_flag*/, st->tdm_LRTD_flag, 0 /*GSC_IVAS_mode*/ ); } *clip_gain = gp_clip( st->element_mode, st->core_brate, st->voicing, i_subfr, TRANSITION, xn, gp_cl ); @@ -275,8 +274,7 @@ void transition_enc( if ( i_subfr - *tc_subfr <= L_SUBFR ) { - config_acelp1( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, TRANSITION, *tc_subfr, 2, NULL, unbits_ACELP, st->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st->idchan, 0 /*tdm_Pitch_reuse_flag*/, st->tdm_LRTD_flag, 0 /*GSC_IVAS_mode*/ - ); + config_acelp1( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, TRANSITION, *tc_subfr, 2, NULL, unbits_ACELP, st->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st->idchan, 0 /*tdm_Pitch_reuse_flag*/, st->tdm_LRTD_flag, 0 /*GSC_IVAS_mode*/ ); } /*-----------------------------------------------------------------* diff --git a/lib_enc/update_decision.c b/lib_enc/update_decision.c index 05877f7a7ec4b2772c61e2e927bc3aeea3ceb307..1269ca68da6e44c4618b2c6c38b32bc5657bfd55 100644 --- a/lib_enc/update_decision.c +++ b/lib_enc/update_decision.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/updt_enc.c b/lib_enc/updt_enc.c index cb573fd07b85895ea5f18c738c38a1580d2051ec..b194de06d5d117483e8b0b3e936a878d8866298a 100644 --- a/lib_enc/updt_enc.c +++ b/lib_enc/updt_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * updt_enc() @@ -188,17 +188,10 @@ void updt_IO_switch_enc( preemph( st->old_inp_16k, PREEMPH_FAC_16k, L_INP_MEM, &( st->mem_preemph16k ) ); /* reset TD BWE buffers */ - set_f( st->hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); set_f( st->hBWE_TD->old_speech_wb, 0.0f, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); set_f( st->hBWE_TD->old_bwe_exc, 0.0f, PIT16k_MAX * 2 ); set_f( st->hBWE_TD->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); - set_f( st->hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); - set_f( st->hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); - st->hBWE_TD->old_mean_EnvSHBres = 0.0f; - st->hBWE_TD->prev_enr_EnvSHBres = 1.0f; - st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; - st->hBWE_TD->prev_mix_factor = 1.0f; - st->hBWE_TD->prev_Env_error = 0.0f; + InitSWBencBufferStates( st->hBWE_TD, NULL ); st->hBWE_TD->bwe_non_lin_prev_scale = 0.0; set_f( st->hBWE_TD->decim_state1, 0.0f, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); @@ -258,7 +251,7 @@ void updt_IO_switch_enc( /* gain quantization memory */ set_f( st->hAmrwb_IO->past_qua_en, -14.0f, GAIN_PRED_ORDER ); - /* reset VBR signalling */ + /* reset VBR signaling */ if ( st->Opt_SC_VBR ) { st->hSC_VBR->ppp_mode = 0; @@ -297,8 +290,7 @@ void updt_IO_switch_enc( *-------------------------------------------------------------------*/ void updt_enc_common( - Encoder_State *st, /* i/o: encoder state structure */ - const float Etot /* i : total energy */ + Encoder_State *st /* i/o: encoder state structure */ ) { /*---------------------------------------------------------------------* @@ -316,7 +308,6 @@ void updt_enc_common( st->last_extl = st->extl; st->last_input_bwidth = st->input_bwidth; st->last_bwidth = st->bwidth; - st->hNoiseEst->Etot_last = Etot; st->last_coder_type_raw = st->coder_type_raw; if ( st->core_brate > SID_2k40 && st->hDtxEnc != NULL ) @@ -417,7 +408,12 @@ void updt_enc_common( st->gamma = GAMMA16k; } - st->igf = getIgfPresent( EVS_MONO, st->total_brate, st->bwidth, st->rf_mode, MCT_CHAN_MODE_REGULAR ); + st->igf = getIgfPresent( EVS_MONO, st->total_brate, st->bwidth, st->rf_mode +#ifndef ISSUE_24_CLEANUP_MCT_LFE + , + MCT_CHAN_MODE_REGULAR +#endif + ); } /* update FER clas */ diff --git a/lib_enc/updt_tar.c b/lib_enc/updt_tar.c index 4cf7f78680cf9037a9e7f62f8b560ab3b3c6ad7f..4c3ff4843cf2aa4c36a1280952ad274da7277f2c 100644 --- a/lib_enc/updt_tar.c +++ b/lib_enc/updt_tar.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "debug.h" #endif #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*----------------------------------------------------------------------------------* * procedure updt_tar() diff --git a/lib_enc/vad.c b/lib_enc/vad.c index 8d3c0beb4fe795acefc925493d3205fe13bb68de..62c7ccb913441af7c4c4c008e54812a358afaa8d 100644 --- a/lib_enc/vad.c +++ b/lib_enc/vad.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -43,7 +43,7 @@ #include "cnst.h" #include "prot.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" #include "ivas_prot.h" /*-----------------------------------------------------------------* @@ -155,13 +155,14 @@ static void sign_thr_snr_acc( *-----------------------------------------------------------------*/ int16_t dtx_hangover_addition( - Encoder_State *st, /* i/o: encoder state structure */ - const int16_t vad_flag, /* i : VAD flag */ - const float lp_snr, /* i : input single SNR estimate */ - const int16_t cldfb_subtraction, /* i : */ - int16_t *vad_hover_flag, /* o : VAD hangover flag */ - VAD_HANDLE hVAD, /* i/o: VAD handle for L or R channel */ - NOISE_EST_HANDLE hNoiseEst /* i : Noise estimation handle */ + Encoder_State *st, /* i/o: encoder state structure */ + const int16_t vad_flag, /* i : VAD flag */ + const float lp_snr, /* i : input single SNR estimate */ + const int16_t cldfb_subtraction, /* i : */ + int16_t *vad_hover_flag, /* o : VAD hangover flag */ + VAD_HANDLE hVAD, /* i/o: VAD handle for L or R channel */ + NOISE_EST_HANDLE hNoiseEst, /* i : Noise estimation handle */ + int16_t *rem_dtx_ho /* o : Expected remaining hangover frames */ ) { int16_t hangover_short_dtx, flag_dtx; @@ -303,6 +304,10 @@ int16_t dtx_hangover_addition( if ( flag_dtx != 0 && st->localVAD == 0 ) { *vad_hover_flag = 1; + if ( rem_dtx_ho != NULL ) + { + *rem_dtx_ho = max( hangover_short_dtx - hVAD->hangover_cnt_dtx, 0 ); + } } return flag_dtx; diff --git a/lib_enc/vad_param_updt.c b/lib_enc/vad_param_updt.c index cbbf5c37d9adaf78bbdac097dde4e8f71e442eb3..b7adac46ea2047ef9545f92296841969e4720fcc 100644 --- a/lib_enc/vad_param_updt.c +++ b/lib_enc/vad_param_updt.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * vad_param_updt() diff --git a/lib_enc/vad_proc.c b/lib_enc/vad_proc.c index f40ca2cb5fe86733a018dbed709174e38f3e1f65..07814aacf38d27eff15d4885f35cd78f76134946 100644 --- a/lib_enc/vad_proc.c +++ b/lib_enc/vad_proc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,7 +39,7 @@ #include "options.h" #include "prot.h" #include "rom_enc.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/vbr_average_rate.c b/lib_enc/vbr_average_rate.c index a32091f690ba8c649280af992a81403eecc0b946..8e7330c8b824ea86011dc670c2ce6f9d4f48ed03 100644 --- a/lib_enc/vbr_average_rate.c +++ b/lib_enc/vbr_average_rate.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * Local constants diff --git a/lib_enc/vlpc_1st_cod.c b/lib_enc/vlpc_1st_cod.c index 9f9316705405cfb31269e9de043cab03e28e5d61..553cf7e264a57d47ff596702d6dfe5a1ab3d01fd 100644 --- a/lib_enc/vlpc_1st_cod.c +++ b/lib_enc/vlpc_1st_cod.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,7 +42,7 @@ #include "cnst.h" #include "prot.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* diff --git a/lib_enc/vlpc_2st_cod.c b/lib_enc/vlpc_2st_cod.c index 86abfec1b03f9ce6e7faf90e6c734a2b9693779e..9e1e9fe5508416aced348832cab45457f0b15611 100644 --- a/lib_enc/vlpc_2st_cod.c +++ b/lib_enc/vlpc_2st_cod.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include "cnst.h" #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------* * vlpc_2st_cod() diff --git a/lib_enc/voiced_enc.c b/lib_enc/voiced_enc.c index 55ee77a47668ae71b05fc1f03d6b0c8363935909..b32692b983a426cdd3b8435fcdd666e943612901 100644 --- a/lib_enc/voiced_enc.c +++ b/lib_enc/voiced_enc.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -40,7 +40,7 @@ #include "prot.h" #include "cnst.h" #include "rom_com.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * Local function prototypes @@ -554,12 +554,12 @@ ivas_error ppp_voiced_encoder( { hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -580,12 +580,13 @@ ivas_error ppp_voiced_encoder( { hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); + return error; } @@ -607,12 +608,12 @@ ivas_error ppp_voiced_encoder( { hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -748,12 +749,12 @@ ivas_error ppp_voiced_encoder( { hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -779,12 +780,12 @@ ivas_error ppp_voiced_encoder( { hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -799,13 +800,12 @@ ivas_error ppp_voiced_encoder( if ( hSC_VBR->bump_up == 1 ) { - - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -815,12 +815,12 @@ ivas_error ppp_voiced_encoder( { hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -834,12 +834,13 @@ ivas_error ppp_voiced_encoder( { if ( ( error = ppp_quarter_encoder( &flag, hBstr, CURRP_Q_E, TMPDTFS, dtfs_temp->lag, *CURRP_NQ, lpc2, &( hSC_VBR->lastLgainE ), &( hSC_VBR->lastHgainE ), &( hSC_VBR->lasterbE[0] ), *dtfs_temp ) ) != IVAS_ERR_OK ) { - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); + return error; } } @@ -1025,12 +1026,12 @@ ivas_error ppp_voiced_encoder( { hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -1045,12 +1046,12 @@ ivas_error ppp_voiced_encoder( PPP_MODE_E = 'B'; hSC_VBR->bump_up = 1; - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } @@ -1082,12 +1083,12 @@ ivas_error ppp_voiced_encoder( mvr2r( dtfs_temp->a, hSC_VBR->dtfs_enc_a, MAXLAG_WI ); mvr2r( dtfs_temp->b, hSC_VBR->dtfs_enc_b, MAXLAG_WI ); - count_free( CURRP_NQ ); - count_free( TMPDTFS ); - count_free( TMPDTFS2 ); - count_free( TMPDTFS3 ); - count_free( CURRP_Q_E ); - count_free( dtfs_temp ); + free( CURRP_NQ ); + free( TMPDTFS ); + free( TMPDTFS2 ); + free( TMPDTFS3 ); + free( CURRP_Q_E ); + free( dtfs_temp ); return error; } diff --git a/lib_enc/waveadjust_fec_cod.c b/lib_enc/waveadjust_fec_cod.c index e0b87477be6b3d4a054043f3112206f66f57c60a..bd57e4a09330c63bef7baa6ba7a0595bab3f06c6 100644 --- a/lib_enc/waveadjust_fec_cod.c +++ b/lib_enc/waveadjust_fec_cod.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -38,7 +38,7 @@ #include "options.h" #include #include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*-------------------------------------------------------------------* * SFM_Cal() diff --git a/lib_dec/ivas_allrad_dec.c b/lib_rend/ivas_allrad_dec.c similarity index 94% rename from lib_dec/ivas_allrad_dec.c rename to lib_rend/ivas_allrad_dec.c index 72a1983d3ea3a78b551b81b6126b7cc347d6478c..fc840755aac643e05fd0fc9f514ab29373433b7e 100644 --- a/lib_dec/ivas_allrad_dec.c +++ b/lib_rend/ivas_allrad_dec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,19 +31,17 @@ *******************************************************************************************************/ #include +#include "options.h" #include #include -#include -#include -#include "options.h" #include "prot.h" #include "ivas_prot.h" -#include "ivas_stat_dec.h" -#include "ivas_rom_dec.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_rend.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" #ifdef DEBUG_MODE_INFO_ALLRAD @@ -108,7 +106,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( /* Allocate memory */ assert( *hoa_dec_mtx == NULL && "hoa_dec_mtx != NULL" ); - if ( ( *hoa_dec_mtx = (float *) count_malloc( SBA_NHARM_HOA3 * MAX_OUTPUT_CHANNELS * sizeof( float ) ) ) == NULL ) + if ( ( *hoa_dec_mtx = (float *) malloc( SBA_NHARM_HOA3 * ( hOutSetup.nchan_out_woLFE ) * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "ALLRAD: Cannot allocate memory!" ) ); } @@ -144,11 +142,10 @@ ivas_error ivas_sba_get_hoa_dec_matrix( return error; } - - num_harm = ( ambisonics_order + 1 ) * ( ambisonics_order + 1 ); + num_harm = ivas_sba_get_nchan( ambisonics_order, 0 ); /* Get t-design values */ - num_td = t_design_11_size; + num_td = SBA_T_DESIGN_11_SIZE; t_design_azi = t_design_11_azimuth; t_design_ele = t_design_11_elevation; diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c new file mode 100644 index 0000000000000000000000000000000000000000..c05ae7c2626401afd599719743834488a63786fd --- /dev/null +++ b/lib_rend/ivas_crend.c @@ -0,0 +1,1187 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_cnst.h" +#include "ivas_rom_rend.h" +#include +#include "ivas_rom_binaural_crend_head.h" +#include "ivas_stat_rend.h" +#include "lib_rend.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*------------------------------------------------------------------------- + * ivas_hrtf_init() + * + * Initialize hHrtf handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_hrtf_init( + HRTFS_DATA *hHrtf /* i/o: HRTF handle */ +) +{ + int16_t i, j; + + if ( hHrtf == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hHrtf->latency_s = 0; + hHrtf->max_num_ir = 0; + hHrtf->max_num_iterations = 0; + hHrtf->gain_lfe = 0; + hHrtf->index_frequency_max_diffuse = 0; + + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + hHrtf->inv_diffuse_weight[i] = 0; + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = 0; + hHrtf->pIndex_frequency_max[i][j] = NULL; + hHrtf->pOut_to_bin_re[i][j] = NULL; + hHrtf->pOut_to_bin_im[i][j] = NULL; + } + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations_diffuse[j] = 0; + hHrtf->pIndex_frequency_max_diffuse[j] = NULL; + hHrtf->pOut_to_bin_diffuse_re[j] = NULL; + hHrtf->pOut_to_bin_diffuse_im[j] = NULL; + } + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * ivas_hrtf_open() + * + * Open hHrtf handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_hrtf_open( + HRTFS_HANDLE *hHrtf_out /* o : HRTF handle */ +) +{ + HRTFS_HANDLE hHrtf; + + if ( *hHrtf_out == NULL ) + { + if ( ( hHrtf = (HRTFS_HANDLE) malloc( sizeof( HRTFS_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR decoder\n" ); + } + + ivas_hrtf_init( hHrtf ); + + *hHrtf_out = hHrtf; + } + else + { + return IVAS_ERR_INTERNAL; + } + + return ( IVAS_ERR_OK ); +} + + +/*------------------------------------------------------------------------- + * ivas_hrtf_close() + * + * Close hHrtf handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_hrtf_close( + HRTFS_HANDLE *hHrtf /* i/o: HRTF handle */ +) +{ + if ( *hHrtf == NULL || hHrtf == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + free( *hHrtf ); + *hHrtf = NULL; + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * initCrend_from_rom() + * + * Allocate and initialize crend renderer handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_rend_initCrend( + CREND_WRAPPER *pCrend, + const AUDIO_CONFIG inIvasConfig, + const AUDIO_CONFIG outIvasConfig, + RENDER_CONFIG_DATA *hRendCfg, + HRTFS_CREND_HANDLE hSetOfHRTF, + const int32_t output_Fs ) +{ + int16_t i, j, tmp; + int16_t nchan_in; + bool use_brir; + IVAS_REND_AudioConfigType inConfigType; + HRTFS_HANDLE hHrtf; + ivas_error error; + IVAS_REND_AudioConfig inConfig; + IVAS_REND_AudioConfig outConfig; + + inConfig = getRendAudioConfigFromIvasAudioConfig( inIvasConfig ); + outConfig = getRendAudioConfigFromIvasAudioConfig( outIvasConfig ); + + inConfigType = getAudioConfigType( inConfig ); + hHrtf = pCrend->hHrtfCrend; + + /* Do all error checks up front so that the nested if later is easier */ + if ( inConfigType != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED && inConfigType != IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Encountered unsupported input config in Crend" ); + } + + if ( outConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL && outConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Encountered unsupported output type in Crend" ); + } + + if ( hHrtf == NULL ) + { + if ( ivas_hrtf_open( &hHrtf ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for HRTF handle" ); + } + } + + /* set BRIR flag */ + use_brir = false; + if ( ( ( hRendCfg != NULL ) && hRendCfg->roomAcoustics.use_brir ) || ( ( hRendCfg == NULL ) && ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) ) ) + { + use_brir = true; + } + + + if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_in ) ) != IVAS_ERR_OK ) + { + return error; + } + hHrtf->max_num_ir = nchan_in; + + if ( hHrtf->max_num_ir <= 0 ) + { + return IVAS_ERR_INTERNAL_FATAL; + } + + if ( hSetOfHRTF == NULL ) + { + if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + hHrtf->max_num_ir -= 1; /* subtract LFE */ + hHrtf->gain_lfe = GAIN_LFE; + + if ( output_Fs == 48000 ) + { + if ( use_brir ) + { + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_48kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_48kHz; + } + else + { + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_48kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_48kHz; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[j]; + } + else + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[j]; + } + } + } + else if ( output_Fs == 32000 ) + { + if ( use_brir ) + { + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_32kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_32kHz; + } + else + { + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_32kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_32kHz; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[j]; + } + else + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[j]; + } + } + } + else if ( output_Fs == 16000 ) + { + if ( use_brir ) + { + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_16kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_16kHz; + } + else + { + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_16kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_16kHz; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_16kHz[j]; + } + else + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[j]; + } + } + } + else + { + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); + } + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 ) + { + tmp = channelIndex_CICP6[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) + { + tmp = channelIndex_CICP12[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 ) + { + tmp = channelIndex_CICP14[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) + { + tmp = channelIndex_CICP16[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1_4 ) + { + tmp = channelIndex_CICP19[i]; + } + else + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); + } + + if ( output_Fs == 48000 ) + { + if ( use_brir ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_48kHz[tmp]; + } + else + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_48kHz[tmp]; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_48kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_48kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_48kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_48kHz[tmp][j]; + } + else + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_48kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_48kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_48kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_48kHz[tmp][j]; + } + } + } + else if ( output_Fs == 32000 ) + { + if ( use_brir ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_32kHz[tmp]; + } + else + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_32kHz[tmp]; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_32kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_32kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_32kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_32kHz[tmp][j]; + } + else + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_32kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_32kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_32kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_32kHz[tmp][j]; + } + } + } + else if ( output_Fs == 16000 ) + { + if ( use_brir ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_16kHz[tmp]; + } + else + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_16kHz[tmp]; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_16kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_16kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_16kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_16kHz[tmp][j]; + } + else + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_16kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_16kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_16kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_16kHz[tmp][j]; + } + } + } + else + { + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); + } + } + } + else if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) + { + if ( output_Fs == 48000 ) + { + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz; + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_48kHz[i]; + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_48kHz[i][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_48kHz[i][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_48kHz[i][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_48kHz[i][j]; + } + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[j]; + } + } + else if ( output_Fs == 32000 ) + { + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz; + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_32kHz[i]; + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_32kHz[i][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_32kHz[i][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_32kHz[i][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_32kHz[i][j]; + } + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[j]; + } + } + else if ( output_Fs == 16000 ) + { + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz; + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_16kHz[i]; + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_16kHz[i][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_16kHz[i][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_16kHz[i][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_16kHz[i][j]; + } + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[j]; + } + } + else + { + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); + } + } + else + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported renderer type in Crend" ); + } + } + else + { + if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + hHrtf->max_num_ir -= 1; /* subtract LFE */ + hHrtf->gain_lfe = GAIN_LFE; + + if ( use_brir ) + { + hHrtf->latency_s = hSetOfHRTF->hHRTF_brir_combined->latency_s; + hHrtf->max_num_iterations = hSetOfHRTF->hHRTF_brir_combined->max_num_iterations; + hHrtf->index_frequency_max_diffuse = hSetOfHRTF->hHRTF_brir_combined->index_frequency_max_diffuse; + } + else + { + hHrtf->latency_s = hSetOfHRTF->hHRTF_hrir_combined->latency_s; + hHrtf->max_num_iterations = hSetOfHRTF->hHRTF_hrir_combined->max_num_iterations; + hHrtf->index_frequency_max_diffuse = hSetOfHRTF->hHRTF_hrir_combined->index_frequency_max_diffuse; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations_diffuse[j] = hSetOfHRTF->hHRTF_brir_combined->num_iterations_diffuse[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = hSetOfHRTF->hHRTF_brir_combined->pIndex_frequency_max_diffuse[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_diffuse_re[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_diffuse_im[j]; + } + else + { + hHrtf->num_iterations_diffuse[j] = hSetOfHRTF->hHRTF_hrir_combined->num_iterations_diffuse[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = hSetOfHRTF->hHRTF_hrir_combined->pIndex_frequency_max_diffuse[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_diffuse_re[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_diffuse_im[j]; + } + } + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 ) + { + tmp = channelIndex_CICP6[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) + { + tmp = channelIndex_CICP12[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 ) + { + tmp = channelIndex_CICP14[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) + { + tmp = channelIndex_CICP16[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1_4 ) + { + tmp = channelIndex_CICP19[i]; + } + else + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); + } + + if ( use_brir ) + { + hHrtf->inv_diffuse_weight[i] = hSetOfHRTF->hHRTF_brir_combined->inv_diffuse_weight[tmp]; + } + else + { + hHrtf->inv_diffuse_weight[i] = hSetOfHRTF->hHRTF_hrir_combined->inv_diffuse_weight[tmp]; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations[i][j] = hSetOfHRTF->hHRTF_brir_combined->num_iterations[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = hSetOfHRTF->hHRTF_brir_combined->pIndex_frequency_max[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_re[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_im[tmp][j]; + } + else + { + hHrtf->num_iterations[i][j] = hSetOfHRTF->hHRTF_hrir_combined->num_iterations[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = hSetOfHRTF->hHRTF_hrir_combined->pIndex_frequency_max[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_re[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_im[tmp][j]; + } + } + } + } + else if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) + { + hHrtf->latency_s = hSetOfHRTF->hHRTF_hrir_hoa3->latency_s; + hHrtf->max_num_iterations = hSetOfHRTF->hHRTF_hrir_hoa3->max_num_iterations; + hHrtf->index_frequency_max_diffuse = hSetOfHRTF->hHRTF_hrir_hoa3->index_frequency_max_diffuse; + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + hHrtf->inv_diffuse_weight[i] = hSetOfHRTF->hHRTF_hrir_hoa3->inv_diffuse_weight[i]; + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->num_iterations[i][j]; + hHrtf->pIndex_frequency_max[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->pIndex_frequency_max[i][j]; + hHrtf->pOut_to_bin_re[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_re[i][j]; + hHrtf->pOut_to_bin_im[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_im[i][j]; + } + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations_diffuse[j] = hSetOfHRTF->hHRTF_hrir_hoa3->num_iterations_diffuse[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = hSetOfHRTF->hHRTF_hrir_hoa3->pIndex_frequency_max_diffuse[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_diffuse_re[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_diffuse_im[j]; + } + } + else + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported renderer type in Crend" ); + } + } + + pCrend->hHrtfCrend = hHrtf; + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * ivas_rend_initCrendWrapper() + * + * Allocate and initialize crend renderer handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_rend_initCrendWrapper( + CREND_WRAPPER_HANDLE *pCrend ) +{ + int16_t i; + + if ( pCrend == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for renderer handle" ); + } + + if ( ( *pCrend = (CREND_WRAPPER_HANDLE) malloc( sizeof( CREND_WRAPPER ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Wrapper\n" ); + } + + ( *pCrend )->binaural_latency_ns = 0; + ( *pCrend )->hCrend = NULL; + ( *pCrend )->hHrtfCrend = NULL; + + if ( ( ( *pCrend )->hCrend = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for renderer handle" ); + } + + ( *pCrend )->hCrend->lfe_delay_line = NULL; + + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + ( *pCrend )->hCrend->freq_buffer_re[i] = NULL; + ( *pCrend )->hCrend->freq_buffer_im[i] = NULL; + } + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + ( *pCrend )->hCrend->prev_out_buffer[i] = NULL; + } + + ( *pCrend )->hCrend->freq_buffer_re_diffuse = NULL; + ( *pCrend )->hCrend->freq_buffer_im_diffuse = NULL; + ( *pCrend )->hCrend->hReverb = NULL; + ( *pCrend )->hCrend->delay_line_rw_index = 0; + ( *pCrend )->hCrend->diffuse_delay_line_rw_index = 0; + ( *pCrend )->hCrend->hTrack = NULL; + ( *pCrend )->hCrend->m_fYaw = 0; + ( *pCrend )->hCrend->m_fPitch = 0; + ( *pCrend )->hCrend->m_fRoll = 0; + + return IVAS_ERR_OK; +} +/*------------------------------------------------------------------------- + * ivas_rend_openCrend() + * + * Allocate and initialize crend renderer handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_rend_openCrend( + CREND_WRAPPER_HANDLE *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + RENDER_CONFIG_DATA *hRendCfg, + HRTFS_CREND_HANDLE hSetOfHRTF, + const int32_t output_Fs ) +{ + /* TODO tmu : Based on ivas_crend_open() - could be harmonized / refactored */ + int16_t i, subframe_length; + int16_t max_total_ir_len; + HRTFS_HANDLE hHrtf; + CREND_HANDLE hCrend; + ivas_error error; + + error = IVAS_ERR_OK; + if ( ( error = ivas_rend_initCrendWrapper( pCrend ) ) != IVAS_ERR_OK ) + { + return error; + } + hCrend = ( *pCrend )->hCrend; + + subframe_length = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES; + + if ( ( *pCrend )->hHrtfCrend == NULL ) + { + if ( ( error = ivas_rend_initCrend( *pCrend, inConfig, outConfig, hRendCfg, hSetOfHRTF, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + hHrtf = ( *pCrend )->hHrtfCrend; + + if ( hHrtf != NULL ) + { + max_total_ir_len = hHrtf->max_num_iterations * subframe_length; + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + if ( ( hCrend->freq_buffer_re[i] = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->freq_buffer_re[i], max_total_ir_len ); + + if ( ( hCrend->freq_buffer_im[i] = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->freq_buffer_im[i], max_total_ir_len ); + } + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + if ( ( hCrend->prev_out_buffer[i] = (float *) malloc( sizeof( float ) * subframe_length ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->prev_out_buffer[i], subframe_length ); + } + + max_total_ir_len = hHrtf->num_iterations_diffuse[0] * subframe_length; + + if ( max_total_ir_len > 0 ) + { + if ( ( hCrend->freq_buffer_re_diffuse = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->freq_buffer_re_diffuse, max_total_ir_len ); + + if ( ( hCrend->freq_buffer_im_diffuse = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->freq_buffer_im_diffuse, max_total_ir_len ); + } + else + { + hCrend->freq_buffer_re_diffuse = NULL; + hCrend->freq_buffer_im_diffuse = NULL; + } + + max_total_ir_len = (int16_t) ( hHrtf->latency_s * output_Fs + 0.5f ) + subframe_length; + if ( max_total_ir_len > 0 ) + { + if ( ( hCrend->lfe_delay_line = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->lfe_delay_line, max_total_ir_len ); + } + else + { + hCrend->lfe_delay_line = NULL; + } + + if ( ( hRendCfg != NULL ) && ( hRendCfg->roomAcoustics.late_reverb_on ) ) + { + if ( ( error = ivas_reverb_open( &( hCrend->hReverb ), inConfig, ( *pCrend )->hHrtfCrend, hRendCfg, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + hCrend->hReverb = NULL; + } + + ( *pCrend )->binaural_latency_ns = (int32_t) ( ( *pCrend )->hHrtfCrend->latency_s * 1000000000.f ); + } + + ( *pCrend )->hCrend = hCrend; + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * ivas_crend_close() + * + * Deallocate Crend renderer handle + *------------------------------------------------------------------------*/ + +void ivas_rend_closeCrend( + CREND_WRAPPER_HANDLE *pCrend ) +{ + int16_t i; + + if ( pCrend == NULL || *pCrend == NULL ) + { + return; + } + + if ( ( *pCrend )->hHrtfCrend != NULL ) + { + ivas_hrtf_close( &( *pCrend )->hHrtfCrend ); + } + + if ( ( *pCrend )->hCrend != NULL ) + { + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + if ( ( *pCrend )->hCrend->freq_buffer_re[i] != NULL ) + { + free( ( *pCrend )->hCrend->freq_buffer_re[i] ); + ( *pCrend )->hCrend->freq_buffer_re[i] = NULL; + } + if ( ( *pCrend )->hCrend->freq_buffer_im[i] != NULL ) + { + free( ( *pCrend )->hCrend->freq_buffer_im[i] ); + ( *pCrend )->hCrend->freq_buffer_im[i] = NULL; + } + } + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + if ( ( *pCrend )->hCrend->prev_out_buffer[i] != NULL ) + { + free( ( *pCrend )->hCrend->prev_out_buffer[i] ); + ( *pCrend )->hCrend->prev_out_buffer[i] = NULL; + } + } + + if ( ( *pCrend )->hCrend->lfe_delay_line != NULL ) + { + free( ( *pCrend )->hCrend->lfe_delay_line ); + ( *pCrend )->hCrend->lfe_delay_line = NULL; + } + + if ( ( *pCrend )->hCrend->freq_buffer_re_diffuse != NULL ) + { + free( ( *pCrend )->hCrend->freq_buffer_re_diffuse ); + ( *pCrend )->hCrend->freq_buffer_re_diffuse = NULL; + } + + if ( ( *pCrend )->hCrend->freq_buffer_im_diffuse != NULL ) + { + free( ( *pCrend )->hCrend->freq_buffer_im_diffuse ); + ( *pCrend )->hCrend->freq_buffer_im_diffuse = NULL; + } + + if ( ( *pCrend )->hCrend->hTrack != NULL ) + { + free( ( *pCrend )->hCrend->hTrack ); + ( *pCrend )->hCrend->hTrack = NULL; + } + + ivas_reverb_close( &( *pCrend )->hCrend->hReverb ); + + free( ( *pCrend )->hCrend ); + ( *pCrend )->hCrend = NULL; + free( *pCrend ); + *pCrend = NULL; + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_crend_convolver() + * + * Convolver block + *-----------------------------------------------------------------------------------------*/ + +static ivas_error ivas_rend_crendConvolver( + const CREND_WRAPPER *pCrend, + IVAS_REND_AudioConfig inConfig, + IVAS_REND_AudioConfig outConfig, + float pcm_in[][L_FRAME48k], + float pcm_out[][L_FRAME48k], + const int32_t output_Fs, + const int16_t i_ts ) +{ + int16_t i, j, k, m; + int16_t subframe_length, idx_in; + int16_t lfe_idx_in; + int16_t offset, offset_in, offset_diffuse; + int16_t nchan_in, nchan_out; + float *pIn; + float *pFreq_buf_re, *pFreq_buf_im; + float *pFreq_filt_re, *pFreq_filt_im; + float pOut[L_FRAME48k * 2]; + float tmp_out_re[L_FRAME48k], tmp_out_im[L_FRAME48k]; + ivas_error error; + + if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_in ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getAudioConfigNumChannels( outConfig, &nchan_out ) ) != IVAS_ERR_OK ) + { + return error; + } + + subframe_length = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES; + + lfe_idx_in = -1; + if ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + if ( inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + lfe_idx_in = LFE_CHANNEL; + } + else + { + assert( 0 && "Custom LS not supported in CRend" ); + } + } + + offset = pCrend->hCrend->delay_line_rw_index * subframe_length; /* subframe_length * ( pCrend->hHrtfCrend->max_num_iterations - 1 ); */ + offset_diffuse = pCrend->hCrend->diffuse_delay_line_rw_index * subframe_length; /* subframe_length *( pCrend->hHrtfCrend->num_iterations_diffuse[0] - 1 ); */ + + if ( pCrend->hHrtfCrend->num_iterations_diffuse[0] > 0 ) + { + set_zero( &pCrend->hCrend->freq_buffer_re_diffuse[offset_diffuse], subframe_length ); + set_zero( &pCrend->hCrend->freq_buffer_im_diffuse[offset_diffuse], subframe_length ); + } + + i = 0; + for ( idx_in = 0; idx_in < nchan_in; idx_in++ ) + { + pIn = &pcm_in[idx_in][i_ts * subframe_length]; + if ( idx_in != lfe_idx_in ) + { + if ( pCrend->hHrtfCrend->num_iterations_diffuse[0] > 0 ) + { + pFreq_buf_re = &pCrend->hCrend->freq_buffer_re_diffuse[offset_diffuse]; + pFreq_buf_im = &pCrend->hCrend->freq_buffer_im_diffuse[offset_diffuse]; + pFreq_filt_re = &pCrend->hCrend->freq_buffer_re[i][offset]; + pFreq_filt_im = &pCrend->hCrend->freq_buffer_im[i][offset]; + + for ( k = 0; k < pCrend->hHrtfCrend->index_frequency_max_diffuse; k++ ) + { + pFreq_buf_re[k] += pFreq_filt_re[k] * pCrend->hHrtfCrend->inv_diffuse_weight[i]; + pFreq_buf_im[k] += pFreq_filt_im[k] * pCrend->hHrtfCrend->inv_diffuse_weight[i]; + } + } + + pFreq_buf_re = &pCrend->hCrend->freq_buffer_re[i][offset]; + pFreq_buf_im = &pCrend->hCrend->freq_buffer_im[i][offset]; + + ivas_mdft( pIn, pFreq_buf_re, pFreq_buf_im, subframe_length, subframe_length ); + i++; + } + } + + for ( j = 0; j < nchan_out; j++ ) + { + set_zero( tmp_out_re, subframe_length ); + set_zero( tmp_out_im, subframe_length ); + + i = 0; + for ( idx_in = 0; idx_in < nchan_in; idx_in++ ) + { + if ( idx_in != lfe_idx_in ) + { + offset = 0; + for ( m = 0; m < pCrend->hHrtfCrend->num_iterations[i][j]; m++ ) + { + offset_in = ( pCrend->hCrend->delay_line_rw_index + pCrend->hHrtfCrend->max_num_iterations - pCrend->hHrtfCrend->num_iterations[i][j] + m + 1 ); + offset_in = offset_in % ( pCrend->hHrtfCrend->max_num_iterations ); + offset_in = offset_in * subframe_length; + pFreq_buf_re = &pCrend->hCrend->freq_buffer_re[i][offset_in]; + pFreq_buf_im = &pCrend->hCrend->freq_buffer_im[i][offset_in]; + pFreq_filt_re = &pCrend->hHrtfCrend->pOut_to_bin_re[i][j][offset]; + pFreq_filt_im = &pCrend->hHrtfCrend->pOut_to_bin_im[i][j][offset]; + + for ( k = 0; k < pCrend->hHrtfCrend->pIndex_frequency_max[i][j][m]; k++ ) + { + tmp_out_re[k] += pFreq_buf_re[k] * pFreq_filt_re[k] - pFreq_buf_im[k] * pFreq_filt_im[k]; + tmp_out_im[k] += pFreq_buf_re[k] * pFreq_filt_im[k] + pFreq_buf_im[k] * pFreq_filt_re[k]; + } + offset = offset + k; + } + i++; + } + } + + offset = 0; + for ( m = 0; m < pCrend->hHrtfCrend->num_iterations_diffuse[j]; m++ ) + { + offset_diffuse = ( pCrend->hCrend->diffuse_delay_line_rw_index + m + 1 ); + offset_diffuse = offset_diffuse % pCrend->hHrtfCrend->num_iterations_diffuse[0]; + offset_diffuse = offset_diffuse * subframe_length; + pFreq_buf_re = &pCrend->hCrend->freq_buffer_re_diffuse[offset_diffuse]; + pFreq_buf_im = &pCrend->hCrend->freq_buffer_im_diffuse[offset_diffuse]; + pFreq_filt_re = &pCrend->hHrtfCrend->pOut_to_bin_diffuse_re[j][offset]; + pFreq_filt_im = &pCrend->hHrtfCrend->pOut_to_bin_diffuse_im[j][offset]; + + for ( k = 0; k < pCrend->hHrtfCrend->pIndex_frequency_max_diffuse[j][m]; k++ ) + { + tmp_out_re[k] += pFreq_buf_re[k] * pFreq_filt_re[k] - pFreq_buf_im[k] * pFreq_filt_im[k]; + tmp_out_im[k] += pFreq_buf_re[k] * pFreq_filt_im[k] + pFreq_buf_im[k] * pFreq_filt_re[k]; + } + offset = offset + k; + } + + ivas_imdft( tmp_out_re, tmp_out_im, pOut, subframe_length ); + + pFreq_buf_re = &pcm_out[j][i_ts * subframe_length]; + for ( k = 0; k < subframe_length; k++ ) + { + pFreq_buf_re[k] = pOut[k] + pCrend->hCrend->prev_out_buffer[j][k]; + pCrend->hCrend->prev_out_buffer[j][k] = pOut[k + subframe_length]; + } + } + + pCrend->hCrend->delay_line_rw_index++; + pCrend->hCrend->delay_line_rw_index = pCrend->hCrend->delay_line_rw_index % ( pCrend->hHrtfCrend->max_num_iterations ); + if ( pCrend->hHrtfCrend->num_iterations_diffuse[0] > 0 ) + { + pCrend->hCrend->diffuse_delay_line_rw_index++; + pCrend->hCrend->diffuse_delay_line_rw_index = pCrend->hCrend->diffuse_delay_line_rw_index % ( pCrend->hHrtfCrend->num_iterations_diffuse[0] ); + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_rend_crend_Process() + * + * Process call for IVAS Crend renderer + *-----------------------------------------------------------------------------------------*/ + +ivas_error ivas_rend_crendProcess( + const CREND_WRAPPER *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + DECODER_CONFIG_HANDLE hDecoderConfig, + HEAD_TRACK_DATA_HANDLE hHeadTrackData, + IVAS_OUTPUT_SETUP_HANDLE hIntSetup, + EFAP_HANDLE hEFAPdata, + float output[][L_FRAME48k], /* i/o: input/output audio channels */ + const int32_t output_Fs ) +{ + int16_t i, subframe_idx, output_frame, subframe_len; + int16_t nchan_out; + float pcm_tmp[BINAURAL_CHANNELS][L_FRAME48k]; + AUDIO_CONFIG in_config; + IVAS_REND_AudioConfigType inConfigType; + ivas_error error; + IVAS_REND_AudioConfig inRendConfig; + IVAS_REND_AudioConfig outRendConfig; + + push_wmops( "ivas_rend_crendProcess" ); + + inRendConfig = getRendAudioConfigFromIvasAudioConfig( inConfig ); + outRendConfig = getRendAudioConfigFromIvasAudioConfig( outConfig ); + + in_config = getIvasAudioConfigFromRendAudioConfig( inRendConfig ); + + inConfigType = getAudioConfigType( inRendConfig ); + + if ( ( error = getAudioConfigNumChannels( outRendConfig, &nchan_out ) ) != IVAS_ERR_OK ) + { + return error; + } + + output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) + { + if ( hDecoderConfig && hDecoderConfig->Opt_Headrotation && hHeadTrackData && hHeadTrackData->num_quaternions >= 0 ) + { + /* Orientation tracking */ + + /* Rotation in SHD for: + MC with elevation (5_1_2 / 5_1_4 / 7_1_4) -> BINAURAL + SBA SPAR -> BINAURAL or BINAURAL_ROOM + */ + if ( in_config == AUDIO_CONFIG_FOA || in_config == AUDIO_CONFIG_HOA2 || in_config == AUDIO_CONFIG_HOA3 ) + { + rotateFrame_shd( hHeadTrackData, output, subframe_len, *hIntSetup, subframe_idx ); + } + /* Rotation in SD for MC -> BINAURAL_ROOM */ + else if ( ( hIntSetup != NULL ) && hIntSetup->is_loudspeaker_setup ) + { + rotateFrame_sd( hHeadTrackData, output, subframe_len, *hIntSetup, hEFAPdata, subframe_idx ); + } + } + + if ( ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) || ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ) + { + if ( ( error = ivas_rend_crendConvolver( pCrend, inRendConfig, outRendConfig, output, pcm_tmp, output_Fs, subframe_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( pCrend->hCrend->hReverb != NULL ) + { + if ( ( error = ivas_reverb_process( pCrend->hCrend->hReverb, in_config, 1, output, pcm_tmp, subframe_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else + { + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + } + + /* move to output */ + for ( i = 0; i < nchan_out; i++ ) + { + mvr2r( pcm_tmp[i], output[i], output_frame ); + } + + pop_wmops(); + + return IVAS_ERR_OK; +} diff --git a/lib_dec/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c similarity index 79% rename from lib_dec/ivas_dirac_dec_binaural_functions.c rename to lib_rend/ivas_dirac_dec_binaural_functions.c index 2d5c83588168caa0c3392a485997eda1bfcf3fa1..09704b969e21ba1cd443e6ed929fffcf6b459b9f 100644 --- a/lib_dec/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,13 +36,18 @@ #include #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_cnst.h" #include "ivas_rom_binauralRenderer.h" -#include "ivas_rom_dec.h" +#include "ivas_rom_rend.h" +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS +#include "ivas_rom_com.h" +#endif + #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------- @@ -53,6 +58,20 @@ #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN ( 2.0f ) #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 3.0f ) +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS_OPT +/* powf(0.95f, 4.0f) for sub-frame smoothing instead of CLDFB slot */ +#define ADAPT_HTPROTO_IIR_FAC 0.81450625f +#else +#define ADAPT_HTPROTO_IIR_FAC 0.95f +#endif + +#define ADAPT_HTPROTO_ILD_LIM_DB0 1.0f +#define ADAPT_HTPROTO_ILD_LIM_DB1 4.0f +#define ADAPT_HTPROTO_ROT_LIM_0 0.4f +#define ADAPT_HTPROTO_ROT_LIM_1 0.8f +#endif + /*------------------------------------------------------------------------- * Local function prototypes *------------------------------------------------------------------------*/ @@ -67,6 +86,10 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( Decoder_Struc static void ivas_dirac_dec_binaural_process_output( Decoder_Struct *st_ivas, float output_f[][L_FRAME48k], float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const uint8_t numInputChannels, const uint8_t firstSlot, const uint8_t slotEnd ); +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS +static void adaptTransportSignalsHeadtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const uint8_t firstSlot, const uint8_t slotEnd, const uint8_t nBins, float Rmat[3][3] ); +#endif + static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const uint8_t firstSlot, const uint8_t slotEnd, const uint8_t nBins, float Rmat[3][3] ); static void formulate2x2MixingMatrix( float Ein1, float Ein2, float CinRe, float CinIm, float Eout1, float Eout2, float CoutRe, float CoutIm, float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], const float regularizationFactor ); @@ -79,6 +102,9 @@ static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Ai static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] ); +#ifdef NOKIA_PARAMBIN_REQULARIZATION +static float configure_reqularization_factor( const IVAS_FORMAT ivas_format, const int32_t ivas_brate ); +#endif /*------------------------------------------------------------------------- * ivas_dirac_dec_init_binaural_data() @@ -87,7 +113,8 @@ static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], f *------------------------------------------------------------------------*/ ivas_error ivas_dirac_dec_init_binaural_data( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ ) { DIRAC_DEC_BIN_HANDLE hBinaural; @@ -98,9 +125,17 @@ ivas_error ivas_dirac_dec_init_binaural_data( float binCenterFreq, tmpFloat; ivas_error error; - if ( ( hBinaural = (DIRAC_DEC_BIN_HANDLE) count_malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) + hBinaural = st_ivas->hDiracDecBin; + + if ( hBinaural == NULL ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); + if ( ( hBinaural = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); + } + + hBinaural->hTdDecorr = NULL; + hBinaural->hReverb = NULL; } nBins = st_ivas->hDirAC->num_freq_bands; @@ -129,18 +164,7 @@ ivas_error ivas_dirac_dec_init_binaural_data( set_zero( hBinaural->ChCrossImOutPrev, nBins ); hBinaural->renderStereoOutputInsteadOfBinaural = 0; - if ( st_ivas->ivas_format == SBA_FORMAT && st_ivas->sba_mode == SBA_MODE_SPAR ) /* Use subframe-mode with SPAR, since the metadata is not in sync on a frame level */ - { - hBinaural->useSubframeMode = 1; - } - else - { -#ifdef DEBUGGING - hBinaural->useSubframeMode = st_ivas->hDecoderConfig->forceSubframeBinauralization; -#else - hBinaural->useSubframeMode = 0; /* Default to 20 ms mode. */ -#endif - } + hBinaural->useSubframeMode = 1; hBinaural->useTdDecorr = 0; if ( st_ivas->ivas_format == SBA_FORMAT ) @@ -150,7 +174,7 @@ ivas_error ivas_dirac_dec_init_binaural_data( hBinaural->useTdDecorr = 1; } } - if ( st_ivas->ivas_format == MASA_FORMAT ) + else if ( st_ivas->ivas_format == MASA_FORMAT ) { if ( ( st_ivas->hDecoderConfig->ivas_total_brate < IVAS_48k && st_ivas->nchan_transport == 1 ) || st_ivas->hDecoderConfig->ivas_total_brate < MASA_STEREO_MIN_BITRATE ) { @@ -187,24 +211,48 @@ ivas_error ivas_dirac_dec_init_binaural_data( } else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */ { - mvr2r( parametricEarlyPartEneCorrection, hBinaural->earlyPartEneCorrection, nBins ); - if ( hBinaural->useSubframeMode ) + mvr2r( hHrtfParambin->parametricEarlyPartEneCorrection, hBinaural->earlyPartEneCorrection, nBins ); + + /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */ + if ( hBinaural->hReverb != NULL && ( ( hBinaural->hReverb->numBins != nBins ) || + ( hBinaural->useSubframeMode && hBinaural->hReverb->blockSize != CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ) || + ( !hBinaural->useSubframeMode && hBinaural->hReverb->blockSize != CLDFB_NO_COL_MAX ) ) ) { - if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ) ) != IVAS_ERR_OK ) - { - return error; - } + ivas_binaural_reverb_close( &( hBinaural->hReverb ) ); } - else + + if ( hBinaural->hReverb == NULL ) { - if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, nBins, CLDFB_NO_COL_MAX ) ) != IVAS_ERR_OK ) + if ( hBinaural->useSubframeMode ) { - return error; + if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, + nBins, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, + st_ivas->hIntSetup.output_config, + output_Fs, + RENDERER_BINAURAL_PARAMETRIC_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, + nBins, + CLDFB_NO_COL_MAX, + NULL, + st_ivas->hIntSetup.output_config, + output_Fs, + RENDERER_BINAURAL_PARAMETRIC_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } } } - ivas_binaural_reverb_setReverbTimes( hBinaural->hReverb, output_Fs, parametricReverberationTimes, parametricReverberationEneCorrections ); - hBinaural->hReverb->useBinauralCoherence = 1; - ivas_binaural_reverb_setPreDelay( hBinaural->hReverb, 10 ); } else if ( renderer_type == RENDERER_STEREO_PARAMETRIC ) { @@ -221,7 +269,11 @@ ivas_error ivas_dirac_dec_init_binaural_data( { if ( st_ivas->hDecoderConfig->ivas_total_brate >= IVAS_13k2 && st_ivas->ivas_format == SBA_FORMAT ) { - ivas_spar_td_decorr_dec_open( &( hBinaural->hTdDecorr ), output_Fs, 3, 1 ); + if ( hBinaural->hTdDecorr == NULL ) + { + ivas_td_decorr_dec_open( &( hBinaural->hTdDecorr ), output_Fs, 3, 1 ); + } + if ( st_ivas->hDecoderConfig->ivas_total_brate < IVAS_24k4 ) { hBinaural->hTdDecorr->pTrans_det->duck_mult_fac = IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR; @@ -233,19 +285,24 @@ ivas_error ivas_dirac_dec_init_binaural_data( } else { - ivas_spar_td_decorr_dec_open( &( hBinaural->hTdDecorr ), output_Fs, 3, 0 ); + ivas_td_decorr_dec_open( &( hBinaural->hTdDecorr ), output_Fs, 3, 0 ); } } else { - hBinaural->hTdDecorr = NULL; + ivas_td_decorr_dec_close( &( hBinaural->hTdDecorr ) ); } +#ifdef NOKIA_PARAMBIN_REQULARIZATION + hBinaural->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); +#endif + st_ivas->hDiracDecBin = hBinaural; return IVAS_ERR_OK; } + /*------------------------------------------------------------------------- * ivas_dirac_dec_close_binaural_data() * @@ -256,7 +313,7 @@ void ivas_dirac_dec_close_binaural_data( DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle */ ) { - if ( *hBinaural == NULL ) + if ( hBinaural == NULL || *hBinaural == NULL ) { return; } @@ -266,14 +323,59 @@ void ivas_dirac_dec_close_binaural_data( ivas_binaural_reverb_close( &( ( *hBinaural )->hReverb ) ); } - ivas_spar_td_decorr_dec_close( &( ( *hBinaural )->hTdDecorr ) ); + ivas_td_decorr_dec_close( &( ( *hBinaural )->hTdDecorr ) ); - count_free( *hBinaural ); + free( *hBinaural ); *hBinaural = NULL; return; } +/*------------------------------------------------------------------------- + * ivas_dirac_dec_binaural_copy_hrtfs() + * + * Temporary function for copying HRTF data from rom tables if no binary + * file was given. + *------------------------------------------------------------------------*/ + +ivas_error ivas_dirac_dec_binaural_copy_hrtfs( + HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ +) +{ + int16_t i, j; + if ( hHrtfParambin != NULL && *hHrtfParambin != NULL ) + { + /* Tables already loaded from file */ + return IVAS_ERR_OK; + } + else + { + /* Initialise tables from ROM */ + HRTFS_PARAMBIN *hrtfParambin; + + if ( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" ); + } + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + mvr2r( hrtfShCoeffsRe[i][j], hrtfParambin->hrtfShCoeffsRe[i][j], HRTF_NUM_BINS ); + mvr2r( hrtfShCoeffsIm[i][j], hrtfParambin->hrtfShCoeffsIm[i][j], HRTF_NUM_BINS ); + } + } + + mvr2r( parametricReverberationTimes, hrtfParambin->parametricReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX ); + + *hHrtfParambin = hrtfParambin; + } + + return IVAS_ERR_OK; +} /*------------------------------------------------------------------------- * ivas_dirac_dec_binaural() @@ -385,9 +487,7 @@ static void ivas_dirac_dec_binaural_internal( else /* when nchan_transport == 1 and ch == 1 */ { /* CNA and HB FD-CNG*/ - if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && - ( st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag || - st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag ) ) + if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ) { int16_t numCoreBands, b; @@ -399,7 +499,7 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_RealBuffer_in[2][slot], Cldfb_ImagBuffer_in[2][slot], slot, st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, - ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag ); + ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/ @@ -407,7 +507,7 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_RealBuffer_in[1][slot], Cldfb_ImagBuffer_in[1][slot], slot, st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, - ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_dirac_flag ); + ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ); /* LB: Copy first channel + LB-CNG to first and second channels with same scaling (dual-mono)*/ for ( b = 0; b < numCoreBands; b++ ) @@ -417,6 +517,7 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_ImagBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_ImagBuffer_in[0][slot][b] + Cldfb_ImagBuffer_in[2][slot][b] ); Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b]; } + /* HB: Copy first channel to second channel and add HB-CNGs with different scalings*/ for ( ; b < nBins; b++ ) { @@ -433,8 +534,9 @@ static void ivas_dirac_dec_binaural_internal( { /* At mono input duplicate the channel to dual-mono, and apply gain correction to ensure same overall level as in stereo mode */ - v_multc( Cldfb_RealBuffer_in[0][slot], 1.0f / SQRT2, Cldfb_RealBuffer_in[0][slot], nBins ); - v_multc( Cldfb_ImagBuffer_in[0][slot], 1.0f / SQRT2, Cldfb_ImagBuffer_in[0][slot], nBins ); + v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins ); + v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins ); + mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins ); mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins ); } @@ -449,10 +551,11 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_RealBuffer_in[ch][slot], Cldfb_ImagBuffer_in[ch][slot], nBins, st_ivas->cldfbAnaDec[ch] ); + if ( st_ivas->nchan_transport == 1 && st_ivas->ivas_format == SBA_FORMAT ) { - v_multc( Cldfb_RealBuffer_in[ch][slot], 1.0f / SQRT2, Cldfb_RealBuffer_in[ch][slot], nBins ); - v_multc( Cldfb_ImagBuffer_in[ch][slot], 1.0f / SQRT2, Cldfb_ImagBuffer_in[ch][slot], nBins ); + v_multc( Cldfb_RealBuffer_in[ch][slot], INV_SQRT_2, Cldfb_RealBuffer_in[ch][slot], nBins ); + v_multc( Cldfb_ImagBuffer_in[ch][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[ch][slot], nBins ); } } } @@ -473,6 +576,10 @@ static void ivas_dirac_dec_binaural_internal( if ( nchan_transport == 2 ) { +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS + adaptTransportSignalsHeadtracked( st_ivas->hHeadTrackData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, firstSlot, slotEnd, nBins, Rmat ); +#endif + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( st_ivas->hHeadTrackData, Cldfb_ImagBuffer_in, Cldfb_RealBuffer_in, firstSlot, slotEnd, nBins, Rmat ); } } @@ -564,7 +671,7 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric { uint8_t ch, slot, bin, subframe; uint8_t separateCenterChannelRendering; - int16_t nBins; + int16_t nBins, idx; float frameMeanDiffusenessEneWeight[CLDFB_NO_CHANNELS_MAX]; DIRAC_DEC_HANDLE hDirAC; DIRAC_DEC_BIN_HANDLE h; @@ -574,7 +681,6 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric uint8_t applyLowBitRateEQ; int16_t dirac_read_idx; - hDirAC = st_ivas->hDirAC; h = st_ivas->hDiracDecBin; separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled; @@ -764,7 +870,7 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric { /* 0.5f <= spreadCoh < 1.0f */ centerMul = 2.0f - ( 2.0f * spreadCoh ); - sidesMul = 1.0f / sqrtf( centerMul + 2.0f ); + sidesMul = inv_sqrt( centerMul + 2.0f ); centerMul *= sidesMul; } @@ -815,15 +921,16 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric if ( ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) ) { + idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + /* Apply the target spectrum to the eneCorrectionFactor */ if ( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */ { - eneCorrectionFactor *= w1 * 1.0f + ( w2 + w3 ) * spreadCohEne1[min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 )]; + eneCorrectionFactor *= w1 * 1.0f + ( w2 + w3 ) * spreadCohEne1[idx]; } else { - eneCorrectionFactor *= w1 * 1.0f + w2 * spreadCohEne05[min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 )] + - w3 * spreadCohEne1[min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 )]; + eneCorrectionFactor *= w1 * 1.0f + w2 * spreadCohEne05[idx] + w3 * spreadCohEne1[idx]; } } @@ -856,8 +963,9 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric { if ( !h->renderStereoOutputInsteadOfBinaural ) { + idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */ - diffEne *= ( 1.0f - surCoh ) + surCoh * surCohEne[min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 )]; + diffEne *= ( 1.0f - surCoh ) + surCoh * surCohEne[idx]; } } h->ChEneOut[0][bin] += diffEne; /* Diff ene part*/ @@ -989,11 +1097,19 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( CrEneR = 0.0f; /* Formulate main processing matrix M */ +#ifdef NOKIA_PARAMBIN_REQULARIZATION + formulate2x2MixingMatrix( h->ChEne[0][bin], h->ChEne[1][bin], + h->ChCrossRe[bin], h->ChCrossIm[bin], + h->ChEneOut[0][bin], h->ChEneOut[1][bin], + h->ChCrossReOut[bin], h->ChCrossImOut[bin], + prototypeMtx, Mre, Mim, h->reqularizationFactor ); +#else formulate2x2MixingMatrix( h->ChEne[0][bin], h->ChEne[1][bin], h->ChCrossRe[bin], h->ChCrossIm[bin], h->ChEneOut[0][bin], h->ChEneOut[1][bin], h->ChCrossReOut[bin], h->ChCrossImOut[bin], prototypeMtx, Mre, Mim, 1.0f ); +#endif /* Load estimated covariance matrix to the [2][2] matrix form */ CxRe[0][0] = h->ChEne[0][bin]; @@ -1242,6 +1358,198 @@ static void ivas_dirac_dec_binaural_process_output( } +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS +static void adaptTransportSignalsHeadtracked( + HEAD_TRACK_DATA_HANDLE hHeadTrackData, + float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const uint8_t firstSlot, + const uint8_t slotEnd, + const uint8_t nBins, + float Rmat[3][3] ) +{ + int16_t slot, ch, bin, louderCh; +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS_OPT + float ILD, mono_factor_ILD, mono_factor_rotation, mono_factor, y_val, ene_proc, ene_target; + uint8_t n_slots_per_sf, sf_idx, n_sf; + int16_t max_band; +#else + float re[2], im[2], ILD, mono_factor_ILD, mono_factor_rotation, mono_factor, y_val; + float proc_re[2], proc_im[2], sum_re, sum_im, ene_proc, ene_target, mf; +#endif + + /* Determine head-orientation-based mono factor. + Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */ + y_val = 1.0f - fabsf( Rmat[1][1] ); + mono_factor_rotation = ( y_val - ADAPT_HTPROTO_ROT_LIM_0 ) / ( ADAPT_HTPROTO_ROT_LIM_1 - ADAPT_HTPROTO_ROT_LIM_0 ); + mono_factor_rotation = fmaxf( 0.0f, fminf( 1.0f, mono_factor_rotation ) ); + + /* Adapt transport signals in frequency bands */ +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS_OPT + /* optimization grouping CLDFB bins into MASA bands (they are readily available in ROM and suitable for the task) AND group CLDFB slots into sub-frames */ + n_slots_per_sf = CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; + n_sf = ( slotEnd - firstSlot ) / n_slots_per_sf; + + max_band = 0; + while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins ) + { + max_band++; + } + + for ( sf_idx = 0; sf_idx < n_sf; sf_idx++ ) + { + float eqVal; + uint8_t start_slot, stop_slot; + int16_t band_idx, bin_lo, bin_hi; + + start_slot = firstSlot + sf_idx * n_slots_per_sf; + stop_slot = start_slot + n_slots_per_sf; + + for ( band_idx = 0; band_idx < max_band; band_idx++ ) + { + float ch_nrg[2]; /* storage for input signal channel energies */ + bin_lo = MASA_band_grouping_24[band_idx]; + bin_hi = min( MASA_band_grouping_24[band_idx + 1], (int16_t) nBins ); + for ( ch = 0; ch < 2; ch++ ) + { + ch_nrg[ch] = 0.0f; + for ( slot = start_slot; slot < stop_slot; slot++ ) + { + for ( bin = bin_lo; bin < bin_hi; bin++ ) + { + ch_nrg[ch] += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + } + } + hHeadTrackData->chEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->chEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch]; + } + + /* Determine ILD */ + ILD = fabsf( 10.0f * log10f( fmaxf( 1e-12f, hHeadTrackData->chEneIIR[0][band_idx] ) / fmaxf( 1e-12f, hHeadTrackData->chEneIIR[1][band_idx] ) ) ); + if ( hHeadTrackData->chEneIIR[1][band_idx] > hHeadTrackData->chEneIIR[0][band_idx] ) + { + louderCh = 1; + } + else + { + louderCh = 0; + } + + /* Determine ILD-based mono factor */ + mono_factor_ILD = ( ILD - ADAPT_HTPROTO_ILD_LIM_DB0 ) / ( ADAPT_HTPROTO_ILD_LIM_DB1 - ADAPT_HTPROTO_ILD_LIM_DB0 ); + mono_factor_ILD = fmaxf( 0.0f, fminf( 1.0f, mono_factor_ILD ) ); + + /* Combine mono factors */ + mono_factor = mono_factor_ILD * mono_factor_rotation; + + /* Mix original audio and sum signal according to determined mono factor */ + for ( ch = 0; ch < 2; ch++ ) + { + if ( ch != louderCh ) + { + float band_nrg = 0.0f; + + for ( slot = start_slot; slot < stop_slot; slot++ ) + { + for ( bin = bin_lo; bin < bin_hi; bin++ ) + { + /* mono sum signal with the computed weight + rest from the original channel */ + inRe[ch][slot][bin] = mono_factor * ( inRe[0][slot][bin] + inRe[1][slot][bin] ) + ( 1.0f - mono_factor ) * inRe[ch][slot][bin]; + inIm[ch][slot][bin] = mono_factor * ( inIm[0][slot][bin] + inIm[1][slot][bin] ) + ( 1.0f - mono_factor ) * inIm[ch][slot][bin]; + band_nrg += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + } + } + hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * band_nrg; + } + else + { + /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */ + hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch]; + } + } + + /* Equalize */ + ene_target = hHeadTrackData->chEneIIR[0][band_idx] + hHeadTrackData->chEneIIR[1][band_idx]; + ene_proc = hHeadTrackData->procChEneIIR[0][band_idx] + hHeadTrackData->procChEneIIR[1][band_idx]; + eqVal = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) ); + + for ( slot = start_slot; slot < stop_slot; slot++ ) + { + for ( ch = 0; ch < 2; ch++ ) + { + for ( bin = bin_lo; bin < bin_hi; bin++ ) + { + inRe[ch][slot][bin] *= eqVal; + inIm[ch][slot][bin] *= eqVal; + } + } + } + } + } +#else + /* original contribution */ + for ( slot = firstSlot; slot < slotEnd; slot++ ) + { + float eqVal[60]; + + for ( bin = 0; bin < nBins; bin++ ) + { + /* Determine channel energies */ + for ( ch = 0; ch < 2; ch++ ) + { + re[ch] = inRe[ch][slot][bin]; + im[ch] = inIm[ch][slot][bin]; + + hHeadTrackData->chEneIIR[ch][bin] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->chEneIIR[ch][bin] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ( ( re[ch] * re[ch] ) + ( im[ch] * im[ch] ) ); + } + + /* Determine ILD */ + ILD = fabsf( 10.0f * log10f( fmaxf( 1e-12f, hHeadTrackData->chEneIIR[0][bin] ) / fmaxf( 1e-12f, hHeadTrackData->chEneIIR[1][bin] ) ) ); + louderCh = ( hHeadTrackData->chEneIIR[1][bin] > hHeadTrackData->chEneIIR[0][bin] ); + + /* Determine ILD-based mono factor */ + mono_factor_ILD = ( ILD - ADAPT_HTPROTO_ILD_LIM_DB0 ) / ( ADAPT_HTPROTO_ILD_LIM_DB1 - ADAPT_HTPROTO_ILD_LIM_DB0 ); + mono_factor_ILD = fmaxf( 0.0f, fminf( 1.0f, mono_factor_ILD ) ); + + /* Combine mono factors */ + mono_factor = mono_factor_ILD * mono_factor_rotation; + + /* Mix original audio and sum signal according to determined mono factor */ + sum_re = re[0] + re[1]; + sum_im = im[0] + im[1]; + for ( ch = 0; ch < 2; ch++ ) + { + mf = ( ch == louderCh ) ? 0.0f : mono_factor; + + proc_re[ch] = mf * sum_re + ( 1.0f - mf ) * re[ch]; + proc_im[ch] = mf * sum_im + ( 1.0f - mf ) * im[ch]; + + hHeadTrackData->procChEneIIR[ch][bin] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->procChEneIIR[ch][bin] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ( ( proc_re[ch] * proc_re[ch] ) + ( proc_im[ch] * proc_im[ch] ) ); + } + + /* Equalize */ + ene_target = hHeadTrackData->chEneIIR[0][bin] + hHeadTrackData->chEneIIR[1][bin]; + ene_proc = hHeadTrackData->procChEneIIR[0][bin] + hHeadTrackData->procChEneIIR[1][bin]; + eqVal[bin] = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) ); + + for ( ch = 0; ch < 2; ch++ ) + { + inRe[ch][slot][bin] = proc_re[ch] * eqVal[bin]; + inIm[ch][slot][bin] = proc_im[ch] * eqVal[bin]; + } + } + } +#endif + + return; +} +#endif + + static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( HEAD_TRACK_DATA_HANDLE hHeadTrackData, float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], @@ -1779,3 +2087,82 @@ static void hrtfShGetHrtf( return; } + + +#ifdef NOKIA_PARAMBIN_REQULARIZATION +/*------------------------------------------------------------------------- + * configure_reqularization_factor() + * + * Configure regularization factor for the mixing matrix generation of the + * parametric binauralizer using IVAS codec format and current bitrate. + *------------------------------------------------------------------------*/ + +/*! r: Configured reqularization factor value to be set. */ +static float configure_reqularization_factor( + const IVAS_FORMAT ivas_format, /* i: IVAS codec format in use */ + const int32_t ivas_brate ) /* i: Current IVAS bitrate */ +{ + float reqularizationFactor; + reqularizationFactor = 1.0f; /* Default value */ + + if ( ivas_format == MASA_FORMAT ) + { + if ( ivas_brate >= IVAS_256k ) + { + reqularizationFactor = 0.2f; + } + else if ( ivas_brate == IVAS_192k ) + { + reqularizationFactor = 0.3f; + } + else if ( ivas_brate == IVAS_160k ) + { + reqularizationFactor = 0.4f; + } + else if ( ivas_brate == IVAS_128k ) + { + reqularizationFactor = 0.5f; + } + else if ( ivas_brate == IVAS_96k ) + { + reqularizationFactor = 0.6f; + } + else if ( ivas_brate >= IVAS_64k ) + { + reqularizationFactor = 0.8f; + } + else + { + reqularizationFactor = 1.0f; + } + } + + if ( ivas_format == MC_FORMAT ) /* This is always McMASA for parametric binauralizer. */ + { + if ( ivas_brate >= IVAS_96k ) + { + reqularizationFactor = 0.3f; + } + else if ( ivas_brate >= IVAS_80k ) + { + reqularizationFactor = 0.5f; + } + else if ( ivas_brate >= IVAS_64k ) + { + reqularizationFactor = 0.7f; + } + else if ( ivas_brate >= IVAS_48k ) + { + reqularizationFactor = 0.8f; + } + else + { + reqularizationFactor = 1.0f; + } + } + + /* For SBA and parametric ISM, currently in default value of 1.0f. */ + + return reqularizationFactor; +} +#endif diff --git a/lib_dec/ivas_efap.c b/lib_rend/ivas_efap.c similarity index 94% rename from lib_dec/ivas_efap.c rename to lib_rend/ivas_efap.c index efd7795dfe735c0a23e5a777343947a0216b88ae..4301d75dec749b89b32404dbcad9c59de9dd329e 100644 --- a/lib_dec/ivas_efap.c +++ b/lib_rend/ivas_efap.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,12 +37,12 @@ #include "options.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "ivas_stat_dec.h" -#include "ivas_rom_dec.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------* * Local constants @@ -83,7 +83,7 @@ static void get_poly_gains( const float azi, const float ele, const float aziPol static float get_tri_gain( const float A[2], const float B[2], const float C[2], const float P_minus_A[2] ); -#if defined( DEBUG_EFAP_POLY_TOFILE ) +#ifdef DEBUG_EFAP_POLY_TOFILE static void get_poly_select( EFAP_POLYSET_DATA *polyData ); #endif @@ -96,11 +96,12 @@ static void add_vertex( EFAP_VERTEX *vtxArray, const float azi, const float ele, static void efap_sort_s( int16_t *x, int16_t *idx, const int16_t len ); - static float vertex_distance( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE tri, const int16_t vtxIdx ); static float point_plane_distance( const float P1[3], const float P2[3], const float P3[3], const float X[3] ); +static float point_poly_distance( const EFAP_POLYSET poly, const float X[3] ); + static void efap_crossp( const float *v1, const float *v2, float *v ); static int16_t find_int_in_tri( const EFAP_LS_TRIANGLE *tri, const int16_t n, const int16_t r, int16_t *pos ); @@ -125,6 +126,7 @@ static int16_t in_poly( const float P[2], const EFAP_POLYSET poly ); static int16_t in_tri( float A[2], float B[2], float C[2], float P_minus_A[2] ); +static void sph2cart( const float azi, const float ele, float *pos ); /*-----------------------------------------------------------------------* * Global function definitions @@ -154,8 +156,7 @@ ivas_error efap_init_data( if ( !speaker_node_azi_deg || !speaker_node_ele_deg ) { hEFAPdata = NULL; - /* TODO: is this path correct behaviour or and error ? */ - return IVAS_ERR_OK; + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "EFAP requires arrays of speaker azimuths and elevations" ); } /*-----------------------------------------------------------------* @@ -163,29 +164,29 @@ ivas_error efap_init_data( *-----------------------------------------------------------------*/ /* Memory Allocations for efap */ - if ( ( efap = (EFAP *) count_malloc( sizeof( EFAP ) ) ) == NULL ) + if ( ( efap = (EFAP *) malloc( sizeof( EFAP ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP handle\n" ) ); } /* Memory Allocation and update for aziSpk & eleSpk arrays*/ - if ( ( efap->aziSpk = (float *) count_malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + if ( ( efap->aziSpk = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker azimuths\n" ) ); } - if ( ( efap->eleSpk = (float *) count_malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + if ( ( efap->eleSpk = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker elevations\n" ) ); } /* Memory Allocation for vertexArray */ - if ( ( efap->vtxData.vertexArray = (EFAP_VERTEX *) count_malloc( ( num_speaker_nodes + EFAP_MAX_GHOST_LS ) * sizeof( EFAP_VERTEX ) ) ) == NULL ) + if ( ( efap->vtxData.vertexArray = (EFAP_VERTEX *) malloc( ( num_speaker_nodes + EFAP_MAX_GHOST_LS ) * sizeof( EFAP_VERTEX ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Array\n" ) ); } /* Memory allocation for the tmp buffer short */ - if ( ( efap->bufferShort = (float *) count_malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + if ( ( efap->bufferShort = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferS\n" ) ); } @@ -214,7 +215,7 @@ ivas_error efap_init_data( /* Memory allocation for the tmp buffer long */ - if ( ( efap->bufferLong = (float *) count_malloc( efap->vtxData.numVtx * sizeof( float ) ) ) == NULL ) + if ( ( efap->bufferLong = (float *) malloc( efap->vtxData.numVtx * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferL\n" ) ); } @@ -266,7 +267,7 @@ void efap_determine_gains( } normBuffer = normBuffer + hEFAPdata->bufferShort[j] * hEFAPdata->bufferShort[j]; } - normBuffer = 1.f / sqrtf( normBuffer ); + normBuffer = inv_sqrt( normBuffer ); for ( j = 0; j < hEFAPdata->numSpk; ++j ) { @@ -322,33 +323,33 @@ void efap_free_data( dim1 = ( *hEFAPdata )->numTot; /* instance buffer members */ - count_free( ( *hEFAPdata )->aziSpk ); + free( ( *hEFAPdata )->aziSpk ); ( *hEFAPdata )->aziSpk = NULL; - count_free( ( *hEFAPdata )->eleSpk ); + free( ( *hEFAPdata )->eleSpk ); ( *hEFAPdata )->eleSpk = NULL; - count_free( ( *hEFAPdata )->vtxData.vertexArray ); + free( ( *hEFAPdata )->vtxData.vertexArray ); ( *hEFAPdata )->vtxData.vertexArray = NULL; - count_free( ( *hEFAPdata )->vtxData.vtxOrder ); + free( ( *hEFAPdata )->vtxData.vtxOrder ); ( *hEFAPdata )->vtxData.vtxOrder = NULL; - count_free( ( *hEFAPdata )->bufferLong ); + free( ( *hEFAPdata )->bufferLong ); ( *hEFAPdata )->bufferLong = NULL; - count_free( ( *hEFAPdata )->bufferShort ); + free( ( *hEFAPdata )->bufferShort ); ( *hEFAPdata )->bufferShort = NULL; p_dmTranspose = (void **) ( *hEFAPdata )->dmTranspose; for ( i = 0; i < dim1; i++ ) { - count_free( p_dmTranspose[i] ); + free( p_dmTranspose[i] ); } - count_free( p_dmTranspose ); + free( p_dmTranspose ); /* instance */ - count_free( *hEFAPdata ); + free( *hEFAPdata ); *hEFAPdata = NULL; return; @@ -462,14 +463,14 @@ static ivas_error poly_init( efap->polyData.numPoly = finalLength; -#if defined( DEBUG_EFAP_POLY_TOFILE ) +#ifdef DEBUG_EFAP_POLY_TOFILE get_poly_select( &efap->polyData ); #endif return error; } -#if defined( DEBUG_EFAP_POLY_TOFILE ) +#ifdef DEBUG_EFAP_POLY_TOFILE static void get_poly_select( EFAP_POLYSET_DATA *polyData /* o : Polygon data structure */ ) @@ -533,7 +534,7 @@ static ivas_error sphere_triangulation( add_ghost_speakers( vtxData->vertexArray, &vtxData->numVtx, efip_flag ); /* Sort the vertices according to their index */ - if ( ( vtxData->vtxOrder = (int16_t *) count_malloc( vtxData->numVtx * sizeof( int16_t ) ) ) == NULL ) + if ( ( vtxData->vtxOrder = (int16_t *) malloc( vtxData->numVtx * sizeof( int16_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Order\n" ) ); } @@ -552,7 +553,7 @@ static ivas_error sphere_triangulation( assert( polyData->numTri != 0 && "EFAP: failed to construct convex hull!" ); /* Allocate the DM matrix transpose */ - if ( ( p_dmTranspose = count_malloc( vtxData->numVtx * sizeof( float * ) ) ) == NULL ) + if ( ( p_dmTranspose = malloc( vtxData->numVtx * sizeof( float * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); } @@ -562,7 +563,7 @@ static ivas_error sphere_triangulation( for ( i = 0; i < vtxData->numVtx; i++ ) { - if ( ( p_dmTranspose[i] = count_malloc( numSpk * sizeof( float ) ) ) == NULL ) + if ( ( p_dmTranspose[i] = malloc( numSpk * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); } @@ -1324,17 +1325,11 @@ static void efap_panning( float tmpBuff[EFAP_MAX_CHAN_NUM]; float normTmpBuff; float P[2]; - float P_tmp[2]; P[0] = azi; P[1] = ele; /* Finding in which polygon the point is */ - P_tmp[0] = roundf( P[0] / PANNING_AZI_RESOLUTION ); - P_tmp[1] = roundf( P[1] / PANNING_ELE_RESOLUTION ); - - P[0] = P_tmp[0] * PANNING_AZI_RESOLUTION; - P[1] = P_tmp[1] * PANNING_ELE_RESOLUTION; polyIdx = get_poly_num( P, polyData ); @@ -1497,9 +1492,7 @@ static void add_vertex( vtxArray[pos].ele = ( ( -180.0f > tmp ) ? -180.0f : tmp ); /* Converting spherical coordinates to cartesians, assuming radius = 1 */ - vtxArray[pos].pos[0] = cosf( vtxArray[pos].azi * PI_OVER_180 ) * cosf( vtxArray[pos].ele * PI_OVER_180 ); - vtxArray[pos].pos[1] = sinf( vtxArray[pos].azi * PI_OVER_180 ) * cosf( vtxArray[pos].ele * PI_OVER_180 ); - vtxArray[pos].pos[2] = sinf( vtxArray[pos].ele * PI_OVER_180 ); + sph2cart( vtxArray[pos].azi, vtxArray[pos].ele, &vtxArray[pos].pos[0] ); /* Computing the index defined by idx = idxAziTmp + 181 * idxEleTmp */ @@ -1591,11 +1584,30 @@ static float vertex_distance( return point_plane_distance( A, B, C, P ); } +/*-------------------------------------------------------------------------* + * point_poly_distance() + * + * Compute the signed distance between a point and polygon + *-------------------------------------------------------------------------*/ + +static float point_poly_distance( + const EFAP_POLYSET poly, /* i : The polygon which forms a plane */ + const float X[3] /* i : Cartesian coordinates of the point of interest */ +) +{ + float P1[3], P2[3], P3[3]; + + sph2cart( poly.polyAzi[0], poly.polyEle[0], &P1[0] ); + sph2cart( poly.polyAzi[1], poly.polyEle[1], &P2[0] ); + sph2cart( poly.polyAzi[2], poly.polyEle[2], &P3[0] ); + + return point_plane_distance( P1, P2, P3, X ); +} /*-------------------------------------------------------------------------* * point_plane_distance() * - * Compute the signed distance between a point a given plane + * Compute the signed distance between a point and a given plane *-------------------------------------------------------------------------*/ static float point_plane_distance( @@ -1628,7 +1640,7 @@ static float point_plane_distance( /* Dot Product */ tmpNorm = dotp( resultCross, resultCross, 3 ); - tmpNorm = 1.f / sqrtf( tmpNorm ); + tmpNorm = inv_sqrt( tmpNorm ); v_sub( X, P1, tmpDot1, 3 ); v_multc( resultCross, tmpNorm, tmpDot2, 3 ); dist = dotp( tmpDot1, tmpDot2, 3 ); @@ -2082,16 +2094,54 @@ static int16_t get_poly_num( ) { int16_t i; + int16_t num_poly, found_poly; + int16_t poly_tmp[EFAP_MAX_CHAN_NUM]; + float poly_dist[EFAP_MAX_CHAN_NUM]; + + float dist_tmp; + float pos[3]; + + num_poly = 0; + sph2cart( P[0], P[1], &pos[0] ); + + /* Filter the polygon list with a fast 2d check */ for ( i = 0; i < polyData->numPoly; ++i ) { if ( in_poly( P, polyData->polysetArray[i] ) ) { - return i; + /* select only polygons which are visible from the point */ + dist_tmp = point_poly_distance( polyData->polysetArray[i], pos ); + if ( dist_tmp == 0 ) + { + return i; + } + else if ( dist_tmp > 0 ) + { + poly_tmp[num_poly] = i; + poly_dist[num_poly] = dist_tmp; + num_poly++; + } } } + if ( num_poly == 0 ) + { + return -1; + } - return -1; + /* select the polygon with the smallest distance */ + found_poly = poly_tmp[0]; + dist_tmp = poly_dist[0]; + for ( i = 1; i < num_poly; i++ ) + { + if ( poly_dist[i] < dist_tmp ) + { + found_poly = poly_tmp[i]; + dist_tmp = poly_dist[i]; + } + } + + return found_poly; } @@ -2201,7 +2251,7 @@ static int16_t in_tri( /* Verification of the non-colinearity */ invFactor = tmpDot1[0] * tmpDot2[1] - tmpDot1[1] * tmpDot2[0]; - if ( invFactor < thresh ) + if ( fabsf( invFactor ) < thresh ) { return 0; } @@ -2216,7 +2266,7 @@ static int16_t in_tri( S[0] = ( matInv[0][0] * P_minus_A[0] ) + ( matInv[0][1] * P_minus_A[1] ); S[1] = ( matInv[1][0] * P_minus_A[0] ) + ( matInv[1][1] * P_minus_A[1] ); - /* Checking if we are in the triangle; For the theory, check Christian Borss article, section 3.2 */ + /* Checking if we are in the triangle; For the theory, check Christian Borss article, section 3.2 */ if ( S[0] < -thresh || S[1] < -thresh || S[0] + S[1] > 1 + thresh ) { return 0; @@ -2226,3 +2276,20 @@ static int16_t in_tri( return 1; } } + +/*-------------------------------------------------------------------------* + * sph2cart() + * + * Converts a vertex position to cartesian coordinates + *-------------------------------------------------------------------------*/ + +static void sph2cart( + const float azi, /* i : Azimuth in degrees */ + const float ele, /* i : Elevation in degrees */ + float *pos /* o : Cartesian coordinates vector (x, y, z) */ +) +{ + pos[0] = cosf( azi * PI_OVER_180 ) * cosf( ele * PI_OVER_180 ); + pos[1] = sinf( azi * PI_OVER_180 ) * cosf( ele * PI_OVER_180 ); + pos[2] = sinf( ele * PI_OVER_180 ); +} diff --git a/lib_rend/ivas_hrtf.c b/lib_rend/ivas_hrtf.c new file mode 100644 index 0000000000000000000000000000000000000000..2b1f16d025cfb0c9166a5c5c80c6c5489e0ca305 --- /dev/null +++ b/lib_rend/ivas_hrtf.c @@ -0,0 +1,203 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot_rend.h" +#include "ivas_error.h" +#include "wmc_auto.h" + +/*-----------------------------------------------------------------------* + * ivas_HRTF_binary_open() + * + * Allocate HRTF binary handle + *-----------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_binary_open( + TDREND_HRFILT_FiltSet_t **hHrtfTD ) +{ + /* Allocate HR filter set for headphones configuration */ + *hHrtfTD = (TDREND_HRFILT_FiltSet_t *) malloc( sizeof( TDREND_HRFILT_FiltSet_t ) ); + if ( *hHrtfTD == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF binary!" ); + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_HRTF_binary_close() + * + * Close HRTF binary handle + *-------------------------------------------------------------------*/ + +void ivas_HRTF_binary_close( + TDREND_HRFILT_FiltSet_t **hHrtfTD ) +{ + if ( hHrtfTD == NULL || *hHrtfTD == NULL ) + { + return; + } + + free( *hHrtfTD ); + *hHrtfTD = NULL; + + return; +} + + +/*-----------------------------------------------------------------------* + * ivas_HRTF_CRend_binary_open() + * + * Allocate HRTF binary handle + *-----------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_CRend_binary_open( + HRTFS_CREND **hSetOfHRTF ) +{ + /* Allocate HR filter set for headphones configuration */ + *hSetOfHRTF = (HRTFS_CREND *) malloc( sizeof( HRTFS_CREND ) ); + if ( *hSetOfHRTF == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for set of HRTF binary!" ); + } + + ( *hSetOfHRTF )->hHRTF_hrir_combined = NULL; + ( *hSetOfHRTF )->hHRTF_hrir_hoa3 = NULL; + ( *hSetOfHRTF )->hHRTF_brir_combined = NULL; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_HRTF_CRend_binary_close() + * + * Close HRTF CRend binary handle + *-------------------------------------------------------------------*/ + +void ivas_HRTF_CRend_binary_close( + HRTFS_CREND **hSetOfHRTF ) +{ + if ( hSetOfHRTF == NULL || *hSetOfHRTF == NULL ) + { + return; + } + + free( *hSetOfHRTF ); + *hSetOfHRTF = NULL; + + return; +} + + +/*-----------------------------------------------------------------------* + * ivas_HRTF_fastconv_binary_open() + * + * Allocate HRTF binary handle for FASTCONV renderer + *-----------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_fastconv_binary_open( + HRTFS_FASTCONV **hHrtfFastConv ) +{ + *hHrtfFastConv = (HRTFS_FASTCONV *) malloc( sizeof( HRTFS_FASTCONV ) ); + if ( *hHrtfFastConv == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FASTCONV HRTF tables!" ); + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------* + * ivas_HRTF_fastconv_binary_close() + * + * Close HRTF binary handle for FASTCONV renderer + *-----------------------------------------------------------------------*/ + +void ivas_HRTF_fastconv_binary_close( + HRTFS_FASTCONV **hHrtfFastConv ) +{ + if ( hHrtfFastConv == NULL || *hHrtfFastConv == NULL ) + { + return; + } + + free( *hHrtfFastConv ); + *hHrtfFastConv = NULL; + + return; +} + + +/*-----------------------------------------------------------------------* + * ivas_HRTF_parambin_binary_open() + * + * Allocate HRTF binary handle for parametric binauralizer + *-----------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_parambin_binary_open( + HRTFS_PARAMBIN **hHrtfParambin ) +{ + *hHrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ); + if ( *hHrtfParambin == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for parametric binauralizer HRTF tables!" ); + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------* + * ivas_HRTF_parambin_binary_close() + * + * Close HRTF binary handle for parametric binauralizer + *-----------------------------------------------------------------------*/ + +void ivas_HRTF_parambin_binary_close( + HRTFS_PARAMBIN **hHrtfParambin ) +{ + if ( hHrtfParambin == NULL || *hHrtfParambin == NULL ) + { + return; + } + + free( *hHrtfParambin ); + *hHrtfParambin = NULL; + + return; +} diff --git a/lib_dec/ivas_limiter.c b/lib_rend/ivas_limiter.c similarity index 92% rename from lib_dec/ivas_limiter.c rename to lib_rend/ivas_limiter.c index e483318be8c08350ee00ea008baeb48707d92da4..28c272bc0c820c180908817035d9446a12d6b819 100644 --- a/lib_dec/ivas_limiter.c +++ b/lib_rend/ivas_limiter.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,22 +30,14 @@ *******************************************************************************************************/ +#include +#include "options.h" #include -#include -#include - -#include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "ivas_prot_rend.h" +#include "wmc_auto.h" #include -/*----------------------------------------------------------------------------------* - * Local constants - *----------------------------------------------------------------------------------*/ - -#define LIMITER_THRESHOLD 32729 /* -0.01 dBFS */ -#define LIMITER_ATTACK_SECONDS 0.005f - /*-------------------------------------------------------------------* * detect_strong_saturations() @@ -71,11 +63,11 @@ static int16_t detect_strong_saturations( *strong_saturation_cnt = 50; apply_strong_limiting = 1; } - else if ( max_val > 3 * LIMITER_THRESHOLD && *strong_saturation_cnt > 0 ) + else if ( max_val > 3 * IVAS_LIMITER_THRESHOLD && *strong_saturation_cnt > 0 ) { apply_strong_limiting = 1; } - else if ( max_val > 10 * LIMITER_THRESHOLD ) + else if ( max_val > 10 * IVAS_LIMITER_THRESHOLD ) { *strong_saturation_cnt += 20; *strong_saturation_cnt = min( *strong_saturation_cnt, 50 ); @@ -122,15 +114,18 @@ IVAS_LIMITER_HANDLE ivas_limiter_open( return NULL; } - hLimiter = count_malloc( sizeof( IVAS_LIMITER ) ); + if ( ( hLimiter = malloc( sizeof( IVAS_LIMITER ) ) ) == NULL ) + { + return NULL; + } hLimiter->max_num_channels = max_num_channels; hLimiter->num_channels = max_num_channels; - hLimiter->channel_ptrs = count_malloc( max_num_channels * sizeof( float * ) ); + hLimiter->channel_ptrs = malloc( max_num_channels * sizeof( float * ) ); hLimiter->sampling_rate = sampling_rate; hLimiter->gain = 1.f; hLimiter->release_heuristic = 0.f; - hLimiter->attack_constant = powf( 0.01f, 1.0f / ( LIMITER_ATTACK_SECONDS * sampling_rate ) ); + hLimiter->attack_constant = powf( 0.01f, 1.0f / ( IVAS_LIMITER_ATTACK_SECONDS * sampling_rate ) ); hLimiter->strong_saturation_count = 0; #ifdef DEBUGGING hLimiter->cnt_frames_limited = 0; @@ -160,8 +155,8 @@ void ivas_limiter_close( return; } - count_free( ( *phLimiter )->channel_ptrs ); - count_free( *phLimiter ); + free( ( *phLimiter )->channel_ptrs ); + free( *phLimiter ); *phLimiter = NULL; return; @@ -202,7 +197,7 @@ void ivas_limiter_dec( channels[c] = output[c]; } - limiter_process( hLimiter, output_frame, LIMITER_THRESHOLD, BER_detect, &hLimiter->strong_saturation_count ); + limiter_process( hLimiter, output_frame, IVAS_LIMITER_THRESHOLD, BER_detect, &hLimiter->strong_saturation_count ); return; } diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c new file mode 100644 index 0000000000000000000000000000000000000000..ed36fa26b11a1e90fcd71276d542ad431b79d8a7 --- /dev/null +++ b/lib_rend/ivas_objectRenderer.c @@ -0,0 +1,653 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "ivas_stat_rend.h" +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot_rend.h" +#include +#include "ivas_rom_com.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*---------------------------------------------------------------------* + * Local function prototypes + *---------------------------------------------------------------------*/ + +static void TDREND_Clear_Update_flags( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd ); +static void angles_to_vec( const float radius, const float azimuth, const float elevation, float *vec ); + +/*---------------------------------------------------------------------* + * ivas_td_binaural_open_unwrap() + * + * Call TD open/init function without st_ivas + *---------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_open_unwrap( + TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */ + const int32_t output_Fs, /* i : Output sampling rate */ + const int16_t nchan_transport, /* i : Number of channels */ + const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */ + const AUDIO_CONFIG transport_config, /* i : Transport configuration */ + const float *directivity, /* i : Directivity pattern (used for ISM) */ + const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */ + int32_t *binaural_latency_ns /* i : Binauralization delay */ +) +{ + BINAURAL_TD_OBJECT_RENDERER_HANDLE pBinRendTd; + TDREND_PosType_t PosType; + int16_t nS; + int16_t SrcInd[MAX_NUM_TDREND_CHANNELS]; + const float *ls_azimuth, *ls_elevation; + float Pos[3]; + float Dir[3]; + TDREND_DirAtten_t *DirAtten_p; + int16_t nchan_rend; + ivas_error error; + + error = IVAS_ERR_OK; + + if ( ( pBinRendTd = malloc( sizeof( BINAURAL_TD_OBJECT_RENDERER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); + } + if ( ( pBinRendTd->TdRend_MixSpatSpec_p = malloc( sizeof( TDREND_MixSpatSpec_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); + } + if ( ( pBinRendTd->DirAtten_p = malloc( sizeof( TDREND_DirAtten_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); + } + if ( ( pBinRendTd->Listener_p = malloc( sizeof( TDREND_MIX_Listener_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD renderer\n" ) ); + } + + pBinRendTd->NumOfSrcs = 0; + pBinRendTd->MaxSrcInd = -1; + + /* Mixer spatial setup */ + pBinRendTd->TdRend_MixSpatSpec_p->UseCommonDistAttenModel = TRUE; + pBinRendTd->TdRend_MixSpatSpec_p->DistAttenModel = 0; /* 0=Turned off, else use TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED */ + + if ( ( error = TDREND_MIX_Init( pBinRendTd, hHrtfTD, pBinRendTd->TdRend_MixSpatSpec_p, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Set the attenuation (or can set MixSpatSpec.DistAttenModel above) */ + if ( ( error = TDREND_MIX_SetDistAttenModel( pBinRendTd, TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Add sources to module and mixer, headphones */ + PosType = TDREND_POSTYPE_ABSOLUTE; /* or TDREND_POSTYPE_RELATIVE_TO_LISTENER */ + + nchan_rend = nchan_transport; + if ( ( ivas_format == MC_FORMAT ) && ( transport_config != AUDIO_CONFIG_LS_CUSTOM ) ) + { + nchan_rend--; /* Skip LFE channel -- added to the others */ + } + + for ( nS = 0; nS < nchan_rend; nS++ ) + { + if ( ( error = TDREND_MIX_AddSrc( pBinRendTd, &SrcInd[nS], PosType ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ivas_format == MC_FORMAT ) + { + switch ( transport_config ) + { + case AUDIO_CONFIG_5_1: + ls_azimuth = ls_azimuth_CICP6; + ls_elevation = ls_elevation_CICP6; + break; + case AUDIO_CONFIG_7_1: + ls_azimuth = ls_azimuth_CICP12; + ls_elevation = ls_elevation_CICP12; + break; + case AUDIO_CONFIG_5_1_2: + ls_azimuth = ls_azimuth_CICP14; + ls_elevation = ls_elevation_CICP14; + break; + case AUDIO_CONFIG_5_1_4: + ls_azimuth = ls_azimuth_CICP16; + ls_elevation = ls_elevation_CICP16; + break; + case AUDIO_CONFIG_7_1_4: + ls_azimuth = ls_azimuth_CICP19; + ls_elevation = ls_elevation_CICP19; + break; + case AUDIO_CONFIG_LS_CUSTOM: + ls_azimuth = hTransSetup.ls_azimuth; + ls_elevation = hTransSetup.ls_elevation; + break; + default: + ls_azimuth = NULL; + ls_elevation = NULL; + } + + DirAtten_p = pBinRendTd->DirAtten_p; + + for ( nS = 0; nS < nchan_rend; nS++ ) + { + /* Set source positions according to loudspeaker layout */ + angles_to_vec( 1.0f, ls_azimuth[nS], ls_elevation[nS], Pos ); + Dir[0] = 1.0f; + Dir[1] = 0.0f; + Dir[2] = 0.0f; + + /* Source directivity info */ + DirAtten_p->ConeInnerAngle = 360.0f; + DirAtten_p->ConeOuterAngle = 360.0f; + DirAtten_p->ConeOuterGain = 1.0f; + + TDREND_MIX_SRC_SetPos( pBinRendTd, nS, Pos ); + TDREND_MIX_SRC_SetDir( pBinRendTd, nS, Dir ); + TDREND_MIX_SRC_SetPlayState( pBinRendTd, nS, TDREND_PLAYSTATUS_PLAYING ); + TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ); + } + } + if ( ivas_format == ISM_FORMAT ) + { + DirAtten_p = pBinRendTd->DirAtten_p; + if ( NULL == directivity ) + { + DirAtten_p->ConeInnerAngle = 360.0f; /* Front cone */ + DirAtten_p->ConeOuterAngle = 360.0f; /* Back cone */ + DirAtten_p->ConeOuterGain = 1.0f; /* Back attenuation */ + } + else + { + DirAtten_p->ConeInnerAngle = directivity[0]; + DirAtten_p->ConeOuterAngle = directivity[1]; + DirAtten_p->ConeOuterGain = directivity[2]; + } + + for ( nS = 0; nS < nchan_rend; nS++ ) + { + TDREND_MIX_SRC_SetDirAtten( pBinRendTd, nS, DirAtten_p ); + } + } + + *hBinRendererTd = pBinRendTd; + *binaural_latency_ns = (int32_t) ( ( *hBinRendererTd )->HrFiltSet_p->latency_s * 1000000000.f ); + + return error; +} + + +/*---------------------------------------------------------------------* + * ivas_td_binaural_close() + * + * Close TD Object binaural renderer + *---------------------------------------------------------------------*/ + +void ivas_td_binaural_close( + BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */ +) +{ + if ( hBinRendererTd == NULL || *hBinRendererTd == NULL ) + { + return; + } + + free( ( *hBinRendererTd )->TdRend_MixSpatSpec_p ); + free( ( *hBinRendererTd )->DirAtten_p ); + + TDREND_MIX_Dealloc( *hBinRendererTd ); + + free( *hBinRendererTd ); + *hBinRendererTd = NULL; + + return; +} + +/*---------------------------------------------------------------------* + * ivas_td_binaural_renderer_unwrap() + * + * Call ivas_td_binaural_renderer() without st_ivas. + *---------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_renderer_unwrap( + const REVERB_HANDLE hReverb, /* i : Reverberator handle */ + const AUDIO_CONFIG transport_config, /* i : Transport configuration */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD binaural object renderer handle */ + const int16_t num_src, /* i : number of sources to render */ + const int16_t lfe_idx, /* i : LFE channel index */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */ + const int16_t Opt_Headrotation, /* i : Head rotation flag */ + const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */ + const IVAS_POSITION *Pos, /* i : Listener position data per subframe */ + float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ + const int16_t output_frame /* i : output frame length */ +) +{ + int16_t subframe_length; + int16_t subframe_idx; + float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k]; + ivas_error error; + + subframe_length = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + + /* Update object position(s) */ + TDREND_Update_object_positions( hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, output ); + + for ( subframe_idx = 0; subframe_idx < MAX_PARAM_SPATIAL_SUBFRAMES; subframe_idx++ ) + { + /* Update the listener's location/orientation */ + TDREND_Update_listener_orientation( hBinRendererTd, Opt_Headrotation, ( Quaternions != NULL ) ? &Quaternions[subframe_idx] : NULL, ( Pos != NULL ) ? &Pos[subframe_idx] : NULL ); + + if ( hReverb != NULL && hReverb->pConfig.roomAcoustics.late_reverb_on ) + { + if ( ( error = ivas_reverb_process( hReverb, transport_config, 0, output, reverb_signal, subframe_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Render subframe */ + if ( ( error = TDREND_GetMix( hBinRendererTd, output, subframe_length, subframe_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + + if ( hReverb != NULL && hReverb->pConfig.roomAcoustics.late_reverb_on ) + { + /* add reverb to rendered signals */ + v_add( reverb_signal[0], output[0], output[0], output_frame ); + v_add( reverb_signal[1], output[1], output[1], output_frame ); + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * TDREND_GetMix() + * + * Render one 5 ms subframe from the mixer + *---------------------------------------------------------------------*/ + +ivas_error TDREND_GetMix( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + float output[][L_FRAME48k], /* i/o: ISM object synth / rendered output in 0,1 */ + const int16_t subframe_length, /* i/o: subframe length */ + const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */ +) +{ + int16_t i; + TDREND_SRC_t *Src_p; + TDREND_SRC_SPATIAL_t *SrcSpatial_p; + TDREND_SRC_REND_t *SrcRend_p; + ivas_error error; + float output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */ + float hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + float hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + int16_t intp_count; + error = IVAS_ERR_OK; + + /* Clear the output buffer to accumulate rendered sources */ + set_f( output_buf[0], 0.0f, subframe_length ); + set_f( output_buf[1], 0.0f, subframe_length ); + + /* Clear interpolation buffers and counter */ + set_f( hrf_left_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + set_f( hrf_right_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + intp_count = 0; + + /* Create the mix */ + /* Loop through the source list and render each source */ + for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) + { + Src_p = hBinRendererTd->Sources[i]; + SrcSpatial_p = Src_p->SrcSpatial_p; + SrcRend_p = Src_p->SrcRend_p; + + /* Update rendering params if needed */ + if ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) + { + TDREND_SRC_REND_UpdateFiltersFromSpatialParams( hBinRendererTd, SrcRend_p, SrcSpatial_p, Src_p->hrf_left_prev, + Src_p->hrf_right_prev, hrf_left_delta, hrf_right_delta, &intp_count, &Src_p->filterlength, &Src_p->itd, &Src_p->Gain, Src_p, subframe_idx ); + } + + /* Render source if needed */ + if ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) ) + { + error = TDREND_REND_RenderSourceHRFilt( Src_p, hrf_left_delta, hrf_right_delta, intp_count, output_buf, subframe_length ); + } + } + + /* Populate output variable */ + mvr2r( output_buf[0], output[0] + subframe_idx * subframe_length, subframe_length ); /* Left */ + mvr2r( output_buf[1], output[1] + subframe_idx * subframe_length, subframe_length ); /* Right */ + + /* Clear the PoseUpdated and Source position update flags */ + TDREND_Clear_Update_flags( hBinRendererTd ); + + return error; +} + + +/*---------------------------------------------------------------------* + * TDREND_Clear_Update_flags() + * + * Initializes the audio mixer module + *---------------------------------------------------------------------*/ + +static void TDREND_Clear_Update_flags( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */ +) +{ + int16_t i; + + hBinRendererTd->Listener_p->PoseUpdated = FALSE; + + for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) + { + hBinRendererTd->Sources[i]->SrcSpatial_p->Updated = FALSE; + } + + return; +} + + +/*---------------------------------------------------------------------* + * TDREND_Update_object_positions() + * + * Update object position(s) + *---------------------------------------------------------------------*/ + +void TDREND_Update_object_positions( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o : TD Renderer handle */ + const int16_t num_src, /* i : number of sources to render */ + const int16_t lfe_idx, /* i : Input LFE index */ + const IVAS_FORMAT in_format, /* i : Format of input sources */ + const ISM_METADATA_HANDLE *hIsmMetaData, /* i : Input metadata for ISM objects */ + float output[][L_FRAME48k] /* i/o: SCE/MC channels */ +) +{ + TDREND_DirAtten_t *DirAtten_p; + int16_t nS; + float Pos[3]; + float Dir[3]; + int16_t c_indx; + + DirAtten_p = hBinRendererTd->DirAtten_p; + + /* For each source, write the frame data to the source object*/ + c_indx = 0; + for ( nS = 0; nS < num_src; nS++ ) + { + if ( !( in_format == MC_FORMAT && nS == lfe_idx ) ) /* Skip LFE for MC */ + { + hBinRendererTd->Sources[c_indx]->InputFrame_p = output[nS]; + hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE; + c_indx++; + } + + if ( in_format == ISM_FORMAT ) + { + + /* Update the source positions */ + /* Source position and direction */ + angles_to_vec( hIsmMetaData[nS]->radius, hIsmMetaData[nS]->azimuth, hIsmMetaData[nS]->elevation, Pos ); + angles_to_vec( 1.0f, hIsmMetaData[nS]->yaw, hIsmMetaData[nS]->pitch, Dir ); + /* Source directivity info */ + DirAtten_p->ConeInnerAngle = 360.0f; + DirAtten_p->ConeOuterAngle = 360.0f; + DirAtten_p->ConeOuterGain = 1.0f; + + TDREND_MIX_SRC_SetPos( hBinRendererTd, nS, Pos ); + TDREND_MIX_SRC_SetDirAtten( hBinRendererTd, nS, DirAtten_p ); + TDREND_MIX_SRC_SetPlayState( hBinRendererTd, nS, TDREND_PLAYSTATUS_PLAYING ); + + TDREND_MIX_SRC_SetDir( hBinRendererTd, nS, Dir ); + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * TDREND_Update_listener_orientation() + * + * Update listener orientation (s) + *---------------------------------------------------------------------*/ + +void TDREND_Update_listener_orientation( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */ + const int16_t headRotEnabled, /* i : Headrotation flag */ + const IVAS_QUATERNION *headPosition, /* i : Listener orientation */ + const IVAS_POSITION *Pos /* i : Listener Position */ +) +{ + float FrontVec[3]; + float UpVec[3]; + float Rmat[3][3]; + float Pos_p[3]; + + if ( headRotEnabled ) + { + /* Obtain head rotation matrix */ + QuatToRotMat( *headPosition, Rmat ); + /* Apply rotation matrix to looking vector [1;0;0] */ + FrontVec[0] = Rmat[0][0]; + FrontVec[1] = Rmat[0][1]; + FrontVec[2] = Rmat[0][2]; + /* Apply rotation matrix to up vector [0;0;1] */ + UpVec[0] = Rmat[2][0]; + UpVec[1] = Rmat[2][1]; + UpVec[2] = Rmat[2][2]; + /* Input position */ + Pos_p[0] = ( *Pos ).x; + Pos_p[1] = ( *Pos ).y; + Pos_p[2] = ( *Pos ).z; + } + else + { + /* Oriented with looking vector along the x axis */ + FrontVec[0] = 1.0f; + FrontVec[1] = 0.0f; + FrontVec[2] = 0.0f; + /* Oriented with up vector along the z axis */ + UpVec[0] = 0.0f; + UpVec[1] = 0.0f; + UpVec[2] = 1.0f; + /* Listener at the origin */ + Pos_p[0] = 0.0f; + Pos_p[1] = 0.0f; + Pos_p[2] = 0.0f; + } + + /* Set the listener position and orientation:*/ + TDREND_MIX_LIST_SetPos( hBinRendererTd, Pos_p ); + TDREND_MIX_LIST_SetOrient( hBinRendererTd, FrontVec, UpVec ); + + return; +} + + +/*---------------------------------------------------------------------* + * ivas_td_binaural_open_ext() + * + * + *---------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_open_ext( + TDREND_WRAPPER *pTDRend, + IVAS_REND_AudioConfig inConfig, + RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */ + LSSETUP_CUSTOM_STRUCT *customLsInput, + const int32_t outFs ) +{ + int16_t nchan_transport; + AUDIO_CONFIG transport_config; + IVAS_FORMAT ivas_format; + IVAS_OUTPUT_SETUP hTransSetup; + ivas_error error; + float *directivity = NULL; + + if ( inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_transport ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + nchan_transport = customLsInput->num_spk; + } + + transport_config = getIvasAudioConfigFromRendAudioConfig( inConfig ); + ivas_format = ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ? MC_FORMAT : ISM_FORMAT; + hTransSetup.ls_azimuth = customLsInput->ls_azimuth; + hTransSetup.ls_elevation = customLsInput->ls_elevation; + + if ( NULL != hRendCfg ) + { + directivity = hRendCfg->directivity; + } + + return ivas_td_binaural_open_unwrap( &pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); +} + + +/*---------------------------------------------------------------------* + * ivas_td_binaural_renderer_ext() + * + * Receives the current frames for the object streams, updates metadata + * and renders the current frame. + *---------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_renderer_ext( + const TDREND_WRAPPER *pTDRend, /* i : TD Renderer wrapper structure */ + const IVAS_REND_AudioConfig inConfig, /* i : Input audio configuration */ + const LSSETUP_CUSTOM_STRUCT *customLsInput, /* i : Input custom loudspeaker layout */ + const IVAS_REND_HeadRotData *headRotData, /* i : Input head positions */ + const IVAS_REND_AudioObjectPosition *currentPos, /* i : Object position */ + const REVERB_HANDLE hReverb, /* i : Reverberator handle */ + const int16_t output_frame, /* i : output frame length */ + float output[][L_FRAME48k] /* i/o: SCE channels / Binaural synthesis */ +) +{ + ISM_METADATA_FRAME hIsmMetaDataFrame; + ISM_METADATA_HANDLE hIsmMetaData[1]; + int16_t lfe_idx; + int16_t num_src; + IVAS_FORMAT ivas_format; + IVAS_REND_AudioConfigType inConfigType; + AUDIO_CONFIG transport_config; + ivas_error error; + + push_wmops( "ivas_td_binaural_renderer_ext" ); + + inConfigType = getAudioConfigType( inConfig ); + lfe_idx = LFE_CHANNEL; + hIsmMetaData[0] = NULL; + + if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + ivas_format = MC_FORMAT; + transport_config = getIvasAudioConfigFromRendAudioConfig( inConfig ); + if ( inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = getAudioConfigNumChannels( inConfig, &num_src ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + lfe_idx = ( customLsInput->num_lfe > 0 ) ? customLsInput->lfe_idx[0] : -1; + num_src = customLsInput->num_spk + customLsInput->num_lfe; + } + } + else + { + ivas_format = ISM_FORMAT; + num_src = 1; + transport_config = AUDIO_CONFIG_ISM1; + hIsmMetaData[0] = &hIsmMetaDataFrame; + hIsmMetaData[0]->azimuth = currentPos->azimuth; + hIsmMetaData[0]->elevation = currentPos->elevation; + hIsmMetaData[0]->yaw = currentPos->yaw; + hIsmMetaData[0]->pitch = currentPos->pitch; + hIsmMetaData[0]->radius = currentPos->radius; + } + + if ( ( error = ivas_td_binaural_renderer_unwrap( hReverb, transport_config, pTDRend->hBinRendererTd, num_src, lfe_idx, ivas_format, hIsmMetaData, headRotData->headRotEnabled, + ( headRotData != NULL ) ? headRotData->headPositions : NULL, + ( headRotData != NULL ) ? headRotData->Pos : NULL, output, output_frame ) ) != IVAS_ERR_OK ) + { + return error; + } + + pop_wmops(); + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * angles_to_vec() + * + * Convert azimuth and elevation angles to position/orientation vector + *---------------------------------------------------------------------*/ + +static void angles_to_vec( + const float radius, /* i : radius */ + const float azimuth, /* i : Azimuth angle */ + const float elevation, /* i : Elevation angle */ + float *vec /* o : Pos/Dir vector */ +) +{ + vec[0] = radius * cosf( elevation * PI_OVER_180 ) * cosf( azimuth * PI_OVER_180 ); + vec[1] = radius * cosf( elevation * PI_OVER_180 ) * sinf( azimuth * PI_OVER_180 ); + vec[2] = radius * sinf( elevation * PI_OVER_180 ); + + return; +} diff --git a/lib_rend/ivas_objectRenderer_hrFilt.c b/lib_rend/ivas_objectRenderer_hrFilt.c new file mode 100644 index 0000000000000000000000000000000000000000..91b018b1486f9f3538c9d30d6f890fef0a06c732 --- /dev/null +++ b/lib_rend/ivas_objectRenderer_hrFilt.c @@ -0,0 +1,615 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include "options.h" +#include "prot.h" +#include +#include "ivas_prot_rend.h" +#include "ivas_rom_rend.h" +#include "ivas_cnst.h" +#include "wmc_auto.h" + + +/*---------------------------------------------------------------------* + * Local function prototypes + *---------------------------------------------------------------------*/ + +static void getPeriodicBSplineSampVec( float *BfVec, int16_t *AzIdx, const int16_t NumBFs, const float t, int16_t *num_az_idx, const float knot_interval, const float azimKSeq_0, const int16_t azimSegSamples, const float *azimBsShape, const int16_t subSampFactor ); +static void getStandardBSplineSampVec( float *BfVec, int16_t *NzIdx, int16_t *num_idx, const int16_t NumBFs, const float t, const float *KSeq, const int16_t SegSamples, const int16_t *BsLen, const int16_t *BsStart, const float *BsShape ); +static void GenerateFilter( const float elev, float azim, ModelParams_t *model, ModelEval_t *modelEval ); +static void GenerateITD( const float elev, float azim, ModelParamsITD_t *model, ModelEval_t *modelEval ); +static void SkipSmallest_ValueIndex( int16_t *use_inds, const ValueIndex_t *VI, const int16_t N, const int16_t n_smallest ); + + +/*-------------------------------------------------------------------* + * TDREND_REND_RenderSourceHRFilt() + * + * Renders each object using the HR filters + --------------------------------------------------------------------*/ + +ivas_error TDREND_REND_RenderSourceHRFilt( + TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ + const float *hrf_left_delta, /* i : Left filter interpolation delta */ + const float *hrf_right_delta, /* i : Right filter interpolation delta */ + const int16_t intp_count, /* i : Interpolation count */ + float output_buf[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ + const int16_t subframe_length /* i : Subframe length in use */ +) +{ + float LeftOutputFrame[L_SPATIAL_SUBFR_48k]; + float RightOutputFrame[L_SPATIAL_SUBFR_48k]; + float Gain; + + Gain = ( *Src_p->SrcRend_p->DirGain_p ) * ( *Src_p->SrcRend_p->DistGain_p ); + + TDREND_Apply_ITD( Src_p->InputFrame_p, LeftOutputFrame, RightOutputFrame, &Src_p->previtd, Src_p->itd, Src_p->mem_itd, subframe_length ); + TDREND_firfilt( LeftOutputFrame, Src_p->hrf_left_prev, hrf_left_delta, intp_count, Src_p->mem_hrf_left, subframe_length, Src_p->filterlength, Gain ); + TDREND_firfilt( RightOutputFrame, Src_p->hrf_right_prev, hrf_right_delta, intp_count, Src_p->mem_hrf_right, subframe_length, Src_p->filterlength, Gain ); + + /* Copy to accumulative output frame */ + v_add( LeftOutputFrame, output_buf[0], output_buf[0], subframe_length ); + v_add( RightOutputFrame, output_buf[1], output_buf[1], subframe_length ); + + Src_p->InputFrame_p += subframe_length; /* Increment input pointer -- todo: should we remove this and input the current subframe instead? */ + + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * GetFilterFromAngle() + * + * Obtain an HR filter corresponding to the input angle pair. + * This version uses the HR filter model. + --------------------------------------------------------------------*/ + +void GetFilterFromAngle( + TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ + const float Elev, /* i : Elevation, degrees */ + float Azim, /* i : Azimuth, degrees */ + float *hrf_left, /* o : Left HR filter */ + float *hrf_right, /* o : Right HR filter */ + int16_t *itd /* o : ITD value */ +) +{ + + GenerateFilter( Elev, Azim, &HrFiltSet_p->ModelParams, &HrFiltSet_p->ModelEval ); + + mvr2r( HrFiltSet_p->ModelEval.hrfModL, hrf_left, HrFiltSet_p->ModelParams.K ); + mvr2r( HrFiltSet_p->ModelEval.hrfModR, hrf_right, HrFiltSet_p->ModelParams.K ); + /* 4. Evaluate the ITD */ + if ( HrFiltSet_p->ModelParams.UseItdModel ) + { + GenerateITD( Elev, Azim, &HrFiltSet_p->ModelParamsITD, &HrFiltSet_p->ModelEval ); + *itd = (int16_t) HrFiltSet_p->ModelEval.itdMod; + } + else + { + *itd = 0; + } + + return; +} + + +/*-------------------------------------------------------------------* + * GenerateFilter() + * + * Generate an HR filter using the B Spline model. + --------------------------------------------------------------------*/ + +static void GenerateFilter( + const float elev, /* i : Elevation angle, degrees */ + float azim, /* i : Azimuth angle, degrees */ + ModelParams_t *model, /* i : Model parameters structure */ + ModelEval_t *modelEval /* i/o: Model evaluation structure */ +) +{ + int16_t qp, p, k, i; + int32_t index; + int16_t AzIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS][HRTF_MODEL_BSPLINE_NUM_COEFFS], EvIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; /* non-zero basis functions */ + int16_t num_az_idx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + int16_t num_ev_idx; + int16_t BM_idx[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + float knot_interval; + float ETotL, ETotR, ESynL, ESynR; + float ScaleL, ScaleR; + int16_t iSec; + + getStandardBSplineSampVec( modelEval->elevBfVec, EvIdx, &num_ev_idx, model->elevDim3, elev, model->elevKSeq, + model->elevSegSamples, model->elevBsLen, model->elevBsStart, model->elevBsShape ); + + for ( p = 0; p < num_ev_idx; p++ ) + { + /* Wrap the requested azimuth to the range of the BSplines */ + azim = fmodf( azim + model->azimKSeq[p][0], 360 ); + if ( azim < 0 ) + { + azim += 360.0f; + } + azim = azim - model->azimKSeq[p][0]; + + if ( model->azimDim3[EvIdx[p]] == 1 ) /* Constant basis function */ + { + num_az_idx[p] = 1; + AzIdx[p][0] = 0; + modelEval->azimBfVec[p][0] = 1.0f; + } + else + { + k = EvIdx[p]; + knot_interval = ( model->azimKSeq[k][model->azimDim3[k]] - model->azimKSeq[k][0] ) / model->azimDim3[k]; + + getPeriodicBSplineSampVec( modelEval->azimBfVec[p], AzIdx[p], model->azimDim3[k], azim, &num_az_idx[p], + knot_interval, model->azimKSeq[k][0], model->azimSegSamples[model->azimShapeIdx[k]], + model->azimBsShape[model->azimShapeIdx[k]], model->azimShapeSampFactor[k] ); + } + } + + /* Compute BM */ + qp = 0; + for ( p = 0; p < num_ev_idx; p++ ) + { + for ( i = 0; i < num_az_idx[p]; i++ ) + { + modelEval->BM[qp + i] = modelEval->elevBfVec[p] * modelEval->azimBfVec[p][i]; + BM_idx[qp + i] = model->azim_start_idx[EvIdx[p]] + AzIdx[p][i]; + } + qp = qp + num_az_idx[p]; + } + + /* Compute HR filters, approximate optimized model evaluation */ + for ( iSec = 0; iSec < HRTF_MODEL_N_SECTIONS; iSec++ ) + { + ETotL = 0.0f; + ETotR = 0.0f; + ESynL = 0.0f; + ESynR = 0.0f; + + /* Energy is precalculated part updated with square of BM value. Store index for sorting */ + for ( i = 0; i < qp; i++ ) + { + modelEval->BMEnergiesL[i].val = modelEval->BM[i] * modelEval->BM[i] * model->EL[iSec * model->AlphaN + BM_idx[i]]; + modelEval->BMEnergiesR[i].val = modelEval->BM[i] * modelEval->BM[i] * model->ER[iSec * model->AlphaN + BM_idx[i]]; + modelEval->BMEnergiesL[i].i = i; + modelEval->BMEnergiesR[i].i = i; + ETotL += modelEval->BMEnergiesL[i].val; + ETotR += modelEval->BMEnergiesR[i].val; + } + + /* Number of basis components actually used. */ + p = min( HRTF_MODEL_N_CPTS_VAR[iSec], qp ); + SkipSmallest_ValueIndex( modelEval->UseIndsL, modelEval->BMEnergiesL, qp, qp - p ); + SkipSmallest_ValueIndex( modelEval->UseIndsR, modelEval->BMEnergiesR, qp, qp - p ); + + /* Account for lost energy */ + for ( i = 0; i < p; i++ ) + { + ESynL += modelEval->BMEnergiesL[modelEval->UseIndsL[i]].val; + ESynR += modelEval->BMEnergiesR[modelEval->UseIndsR[i]].val; + } + ScaleL = sqrtf( ETotL / ESynL ); + ScaleR = sqrtf( ETotR / ESynR ); + + /* Build using only the most energetic components. */ + for ( k = model->iSecFirst[iSec]; k <= model->iSecLast[iSec]; k++ ) + { + modelEval->hrfModL[k] = 0.0; + modelEval->hrfModR[k] = 0.0; + for ( i = 0; i < p; i++ ) + { + index = BM_idx[modelEval->BMEnergiesL[modelEval->UseIndsL[i]].i] + k * model->AlphaN; + modelEval->hrfModL[k] += modelEval->BM[modelEval->BMEnergiesL[modelEval->UseIndsL[i]].i] * model->AlphaL[index]; + index = BM_idx[modelEval->BMEnergiesR[modelEval->UseIndsR[i]].i] + k * model->AlphaN; + modelEval->hrfModR[k] += modelEval->BM[modelEval->BMEnergiesR[modelEval->UseIndsR[i]].i] * model->AlphaR[index]; + } + /* Account for lost energy */ + modelEval->hrfModL[k] *= ScaleL; + modelEval->hrfModR[k] *= ScaleR; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * GenerateITD() + * + * Generates an ITD value from the B Spline model. + --------------------------------------------------------------------*/ + +static void GenerateITD( + const float elev, /* i : Elevation angle, degrees */ + float azim, /* i : Azimuth angle, degrees */ + ModelParamsITD_t *model, /* i : ITD Model parameters structure */ + ModelEval_t *modelEval /* i/o: Model evaluation structure */ +) +{ + int16_t qp, p, i; + int32_t index; + int16_t AlphaN; + int16_t elev_offset; + float azim_itd; + int16_t AzIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS], EvIdx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; /* non-zero basis functions */ + int16_t num_az_idx, num_ev_idx; + int16_t BM_idx[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + + /* Wrap the requested azimuth to the range of the BSplines */ + azim = fmodf( azim + model->azimKSeq[0], 360 ); + if ( azim < 0 ) + { + azim += 360.0f; + } + azim = azim - model->azimKSeq[0]; + + if ( (int16_t) abs( (int16_t) elev ) != 90 ) + { + getStandardBSplineSampVec( modelEval->elevBfVecITD, EvIdx, &num_ev_idx, model->elevDim3, elev, model->elevKSeq, + model->elevSegSamples, model->elevBsLen, model->elevBsStart, model->elevBsShape ); + azim_itd = azim; + if ( azim > 180 ) + { + /* Flip spline functions around 180 deg */ + azim_itd = 360 - azim; + } + getStandardBSplineSampVec( modelEval->azimBfVecITD, AzIdx, &num_az_idx, ( model->azimDim3 + 1 ) / 2, azim_itd, model->azimKSeq, + model->azimSegSamples, model->azimBsLen, model->azimBsStart, model->azimBsShape ); + if ( azim > 180 ) + { + /* Flip spline functions around 180 deg */ + for ( i = 0; i < HRTF_MODEL_BSPLINE_NUM_COEFFS; i++ ) + { + AzIdx[i] = model->azimDim3 - 1 - AzIdx[i]; + } + } + } + else + { + num_az_idx = 1; + num_ev_idx = 1; + modelEval->elevBfVecITD[0] = 1.0f; + if ( elev < 0 ) + { + EvIdx[0] = 0; + } + else + { + EvIdx[0] = model->elevDim3 - 1; + } + } + + /* Compute BM_ITD */ + elev_offset = 0; + if ( model->elevKSeq[0] == -90 ) + { + elev_offset = -( model->azimDim3 - 1 ); + } + qp = 0; + for ( p = 0; p < num_ev_idx; p++ ) + { + if ( EvIdx[p] == 0 && (int16_t) ( model->elevKSeq[EvIdx[p]] ) == -90 ) + { + modelEval->BM_ITD[qp] = modelEval->elevBfVecITD[p]; + BM_idx[qp] = EvIdx[p] * model->azimDim3; + qp = qp + 1; + } + else if ( EvIdx[p] == ( model->elevDim3 - 1 ) && (int16_t) ( model->elevKSeq[EvIdx[p] - 2] ) == 90 ) + { + /* NB: -2 in if() condition above as number of knot points is numBF-2 */ + modelEval->BM_ITD[qp] = modelEval->elevBfVecITD[p]; + BM_idx[qp] = EvIdx[p] * model->azimDim3 + elev_offset; + qp = qp + 1; + } + else + { + for ( i = 0; i < num_az_idx; i++ ) + { + modelEval->BM_ITD[qp + i] = modelEval->elevBfVecITD[p] * modelEval->azimBfVecITD[i]; + BM_idx[qp + i] = EvIdx[p] * model->azimDim3 + elev_offset + AzIdx[i]; + } + qp = qp + num_az_idx; + } + } + + /* Compute ITD */ + AlphaN = model->elevDim3 * model->azimDim3 + elev_offset; + if ( model->elevKSeq[model->elevDim3 - 3] == 90 ) /* Constant azimuth basis function */ + { + AlphaN = AlphaN - ( model->azimDim3 - 1 ); + } + + /* Matrix multiplcation (row x column) */ + modelEval->itdMod = 0.0f; + for ( i = 0; i < qp; i++ ) + { + index = BM_idx[i]; + modelEval->itdMod += modelEval->BM_ITD[i] * model->W[index]; + } + + modelEval->itdMod = -(float) round_f( modelEval->itdMod * model->resamp_factor ); /* Resample and reverse sign of ITD as convention in model and renderer are opposite */ + + return; +} + + +/*-------------------------------------------------------------------* + * getStandardBSplineSampVec() + * + * Obtain a periodic sampled B Spline basis vector. + --------------------------------------------------------------------*/ + +static void getPeriodicBSplineSampVec( + float *BfVec, /* i/o: values for non-zero basis functions */ + int16_t *AzIdx, /* i/o: indices of non-zero basis functions */ + const int16_t NumBFs, /* i : the number of basis functions = third index of Bf. */ + const float t, /* i : azimuth */ + int16_t *num_az_idx, /* i : Number of azimuth indices */ + const float knot_interval, /* i : The knot interval */ + const float azimKSeq_0, /* i : Knot sequence */ + const int16_t azimSegSamples, /* i : Samples per segment */ + const float *azimBsShape, /* i : Basis shape */ + const int16_t subSampFactor /* i : Subsampling factor */ +) +{ + int16_t i, nI, d0, d; + + int16_t SegSamples = azimSegSamples / subSampFactor; + + /* index of closest sample point */ + d0 = (int16_t) round_f( ( t - azimKSeq_0 ) / ( knot_interval / SegSamples ) ); + + /* find segment */ + nI = d0 / SegSamples; + + *num_az_idx = HRTF_MODEL_BSPLINE_NUM_COEFFS; + + if ( d0 % SegSamples == 0 ) + { + ( *num_az_idx )--; /* on the knot points, the last basis function is zero */ + } + + for ( i = 0; i < *num_az_idx; i++ ) + { + d = d0 - ( i + nI - 1 ) * SegSamples; /* offset of knot_interval */ + BfVec[i] = azimBsShape[(int16_t) abs( d ) * subSampFactor]; + AzIdx[i] = ( nI + i ) % NumBFs; + } + + return; +} + + +/*-------------------------------------------------------------------* + * getStandardBSplineSampVec() + * + * Obtain a sampled B Spline basis vector. + --------------------------------------------------------------------*/ + +static void getStandardBSplineSampVec( + float *BfVec, /* i/o: values for non-zero basis functions */ + int16_t *NzIdx, /* i/o: indices of non-zero basis functions */ + int16_t *num_idx, /* i/o: number of non-zero indices */ + const int16_t NumBFs, /* i : the number of basis functions = third index of Bf */ + const float t, /* i : estimation point */ + const float *KSeq, /* i : knot sequence including multiplicities */ + const int16_t SegSamples, /* i : samples per segment */ + const int16_t *BsLen, /* i : lengths of basis shapes */ + const int16_t *BsStart, /* i : start of basis shapes */ + const float *BsShape /* i : basis shapes */ +) +{ + int16_t i, nI; + float knot_interval; + int16_t d0, d, shape_idx, start_idx; + + knot_interval = ( KSeq[NumBFs - 3] - KSeq[0] ) / ( NumBFs - 3 ); /* assuming triple knot at the first knot */ + /* index of closest sample point */ + d0 = (int16_t) round_f( ( t - KSeq[0] ) / ( knot_interval / SegSamples ) ); + /* find segment */ + nI = d0 / SegSamples; + + *num_idx = HRTF_MODEL_BSPLINE_NUM_COEFFS; + + if ( d0 % SegSamples == 0 ) + { + ( *num_idx )--; /* on the knot points, the last basis function is zero */ + } + + + for ( i = 0; i < *num_idx; i++ ) + { + start_idx = max( 0, i + nI - 3 ); + shape_idx = min( i + nI, min( 3, NumBFs - 1 - ( i + nI ) ) ); + d = d0 - start_idx * SegSamples; + + if ( i + nI > NumBFs - 4 ) /* reverse full shape */ + { + d = BsLen[shape_idx] - 1 - d; + } + else if ( d > BsLen[shape_idx] - 1 ) /* reverse half shape */ + { + d = 2 * ( BsLen[shape_idx] - 1 ) - d; + } + BfVec[i] = BsShape[BsStart[shape_idx] + (int16_t) abs( d )]; /*TT, verify if abs is needed */ + NzIdx[i] = nI + i; + } + + return; +} + + +/*-------------------------------------------------------------------* + * HRTF_model_precalc() + * + * Set precalculated parameters for HRTF model + --------------------------------------------------------------------*/ + +void HRTF_model_precalc( + ModelParams_t *model /* i/o: HRTF model parameters */ +) +{ + int16_t sec_length; + int16_t i; + + sec_length = model->K / HRTF_MODEL_N_SECTIONS; + + for ( i = 0; i < HRTF_MODEL_N_SECTIONS; i++ ) + { + model->iSecFirst[i] = i * sec_length; + } + for ( i = 0; i < HRTF_MODEL_N_SECTIONS - 1; i++ ) + { + model->iSecLast[i] = ( i + 1 ) * sec_length - 1; + } + model->iSecLast[HRTF_MODEL_N_SECTIONS - 1] = model->K - 1; /* Final section is longer if (K % nSec) > 0 */ + + maximum_s( model->azimDim3, model->elevDim3, &model->azimDim3Max ); + + return; +} + + +/*-------------------------------------------------------------------* + * BSplineModelEvalDealloc() + * + * Deallocate BSpline HR Filter model + --------------------------------------------------------------------*/ + +void BSplineModelEvalDealloc( + ModelParams_t *model, /* i : Model parameters */ + ModelEval_t *modelEval /* i : Model evaluation structure */ +) +{ + /* Allocated in LoadBSplineBinary() */ + int16_t i; + + if ( model->modelROM ) + { + free( (void *) model->azimBsShape ); /* void* cast needed to please both gcc and Visual studio compilers. Deallocating const float** should be fine and gcc agrees, but Visual studio complains. */ + for ( i = 0; i < model->elevDim3; i++ ) + { + free( model->azimKSeq[i] ); + } + free( model->azimKSeq ); + if ( modelEval != NULL ) + { + free( modelEval->hrfModL ); + free( modelEval->hrfModR ); + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * SkipSmallest_ValueIndex() + * + * Returns indices to the largest values in a ValueIndex list, + * unordered (i.e. skip the n_smallest values, return the remainder). + --------------------------------------------------------------------*/ + +static void SkipSmallest_ValueIndex( + int16_t *use_inds, /* i/o: List of indices to use */ + const ValueIndex_t *VI, /* i : List of value-index items */ + const int16_t N, /* i : Length of list */ + const int16_t n_smallest /* i : Number of items to skip */ +) +{ + int16_t i, j, k, flag; + int16_t skip_inds[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + float candidate_max; /* Stores the max value in the shortlist (next to be kicked off) and its index */ + int16_t candidate_max_i; + + /* Initialise with first entries of VI */ + candidate_max = 0.0; + candidate_max_i = 0; + for ( j = 0; j < n_smallest; j++ ) + { + skip_inds[j] = j; + if ( candidate_max < VI[j].val ) + { + candidate_max = VI[j].val; + candidate_max_i = j; + } + } + + /* Look in the remainder of the list for smaller values */ + for ( i = n_smallest; i < N; i++ ) + { + for ( j = 0; j < n_smallest; j++ ) + { + if ( VI[i].val < VI[skip_inds[j]].val ) + { + /* Found a smaller value, so it goes into the list, replacing candidate_max. */ + skip_inds[candidate_max_i] = i; + candidate_max = VI[i].val; + /* Update candidate_max */ + for ( k = 0; k < n_smallest; k++ ) + { + if ( VI[skip_inds[k]].val > candidate_max ) + { + candidate_max = VI[skip_inds[k]].val; + candidate_max_i = k; + } + } + break; + } + } + } + + /* Build the list of indices that will not be skipped */ + k = 0; + for ( j = 0; j < N; j++ ) + { + flag = 1; + for ( i = 0; i < n_smallest; i++ ) + { + if ( skip_inds[i] == j ) + { + flag = 0; + break; + } + } + if ( flag ) + { + use_inds[k] = j; + k++; + } + } + + return; +} diff --git a/lib_dec/ivas_objectRenderer_mix.c b/lib_rend/ivas_objectRenderer_mix.c similarity index 57% rename from lib_dec/ivas_objectRenderer_mix.c rename to lib_rend/ivas_objectRenderer_mix.c index 61553ca4fc85a82c0274c13ca44e511084858f6f..509d22d320f98ef6d1fcc17dc55b3ec8cc5ae14b 100644 --- a/lib_dec/ivas_objectRenderer_mix.c +++ b/lib_rend/ivas_objectRenderer_mix.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,21 +33,37 @@ #include #include "options.h" #include "prot.h" -#include "ivas_prot.h" -#include "wmops.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_TdBinauralRenderer.h" +#include "ivas_error.h" +#include "wmc_auto.h" #ifdef DEBUGGING #include "debug.h" #endif +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define RESAMPLE_FACTOR_16_48 ( 16.0f / 48.0f ) +#define RESAMPLE_FACTOR_32_48 ( 32.0f / 48.0f ) + + +/*------------------------------------------------------------------------- + * Local functions + *-------------------------------------------------------------------------*/ + +static ivas_error DefaultBSplineModel( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, const int32_t output_Fs ); + + /*-------------------------------------------------------------------* * TDREND_MIX_LIST_SetPos() * * Sets the listener's position in the specified mixer unit. --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ -ivas_error TDREND_MIX_LIST_SetPos( +void TDREND_MIX_LIST_SetPos( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const float *Pos_p /* i : Listener's position */ ) @@ -65,7 +81,7 @@ ivas_error TDREND_MIX_LIST_SetPos( Listener_p->PoseUpdated = TRUE; } - return IVAS_ERR_OK; + return; } @@ -75,7 +91,6 @@ ivas_error TDREND_MIX_LIST_SetPos( * Sets the listener's orientation vectors in the specified mixer unit. --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_LIST_SetOrient( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const float *FrontVec_p, /* i : Listener's orientation front vector */ @@ -124,7 +139,7 @@ void TDREND_MIX_Dealloc( /* Deallocate Listener and RendListener */ if ( hBinRendererTd->Listener_p != NULL ) { - count_free( hBinRendererTd->Listener_p ); + free( hBinRendererTd->Listener_p ); hBinRendererTd->Listener_p = NULL; } /* Dealloc HR filter set */ @@ -132,54 +147,33 @@ void TDREND_MIX_Dealloc( { if ( hBinRendererTd->HrFiltSet_p->FilterMethod == TDREND_HRFILT_Method_BSplineModel ) { - if ( hBinRendererTd->HrFiltSet_p->ModelParams.UseItdModel && !hBinRendererTd->HrFiltSet_p->ModelParams.modelROM ) - { - BSplineModelEvalITDDealloc( &hBinRendererTd->HrFiltSet_p->ModelParamsITD ); - } BSplineModelEvalDealloc( &hBinRendererTd->HrFiltSet_p->ModelParams, &hBinRendererTd->HrFiltSet_p->ModelEval ); } else { if ( hBinRendererTd->HrFiltSet_p->Elev_p != NULL ) { - count_free( hBinRendererTd->HrFiltSet_p->Elev_p ); + free( hBinRendererTd->HrFiltSet_p->Elev_p ); hBinRendererTd->HrFiltSet_p->Elev_p = NULL; } if ( hBinRendererTd->HrFiltSet_p->Azim_p != NULL ) { - count_free( hBinRendererTd->HrFiltSet_p->Azim_p ); + free( hBinRendererTd->HrFiltSet_p->Azim_p ); hBinRendererTd->HrFiltSet_p->Azim_p = NULL; } if ( hBinRendererTd->HrFiltSet_p->LeftFiltSet_p != NULL ) { - count_free( hBinRendererTd->HrFiltSet_p->LeftFiltSet_p ); + free( hBinRendererTd->HrFiltSet_p->LeftFiltSet_p ); hBinRendererTd->HrFiltSet_p->LeftFiltSet_p = NULL; } if ( hBinRendererTd->HrFiltSet_p->RightFiltSet_p != NULL ) { - count_free( hBinRendererTd->HrFiltSet_p->RightFiltSet_p ); + free( hBinRendererTd->HrFiltSet_p->RightFiltSet_p ); hBinRendererTd->HrFiltSet_p->RightFiltSet_p = NULL; } -#ifdef TDREND_HRTF_TABLE_METHODS - if ( hBinRendererTd->HrFiltSet_p->NumAzim_p != NULL ) - { - count_free( hBinRendererTd->HrFiltSet_p->NumAzim_p ); - hBinRendererTd->HrFiltSet_p->NumAzim_p = NULL; - } - if ( hBinRendererTd->HrFiltSet_p->AzimStartIdx_p != NULL ) - { - count_free( hBinRendererTd->HrFiltSet_p->AzimStartIdx_p ); - hBinRendererTd->HrFiltSet_p->AzimStartIdx_p = NULL; - } - if ( hBinRendererTd->HrFiltSet_p->ElevFull_p != NULL ) - { - count_free( hBinRendererTd->HrFiltSet_p->ElevFull_p ); - hBinRendererTd->HrFiltSet_p->ElevFull_p = NULL; - } -#endif } - count_free( hBinRendererTd->HrFiltSet_p ); + free( hBinRendererTd->HrFiltSet_p ); hBinRendererTd->HrFiltSet_p = NULL; } @@ -193,7 +187,6 @@ void TDREND_MIX_Dealloc( * Initializes the mixer and sets HRTF --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_Init( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HRTF data (initialized in case of NULL) */ @@ -201,6 +194,7 @@ ivas_error TDREND_MIX_Init( const int32_t output_Fs /* i : Output sampling rate */ ) { + ivas_error error; hBinRendererTd->Gain = 1.0f; @@ -228,12 +222,15 @@ ivas_error TDREND_MIX_Init( /* Init HR filter set */ if ( *hHrtfTD == NULL ) { - if ( ( hBinRendererTd->HrFiltSet_p = (TDREND_HRFILT_FiltSet_t *) count_malloc( sizeof( TDREND_HRFILT_FiltSet_t ) ) ) == NULL ) + if ( ( hBinRendererTd->HrFiltSet_p = (TDREND_HRFILT_FiltSet_t *) malloc( sizeof( TDREND_HRFILT_FiltSet_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } - DefaultBSplineModel( hBinRendererTd->HrFiltSet_p, output_Fs ); + if ( ( error = DefaultBSplineModel( hBinRendererTd->HrFiltSet_p, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } *hHrtfTD = hBinRendererTd->HrFiltSet_p; } else @@ -256,7 +253,6 @@ ivas_error TDREND_MIX_Init( * Set the distance attenuation model of the mixer --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_SetDistAttenModel( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const TDREND_DistAttenModel_t DistAttenModel /* i : Distance attenuation model */ @@ -291,12 +287,10 @@ ivas_error TDREND_MIX_SetDistAttenModel( * Adds the specified input source unit to the specified mixer unit. --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_AddSrc( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ int16_t *SrcInd, /* o : Source index */ - const TDREND_PosType_t PosType, /* i : Position type (absolute/relative) */ - const int32_t output_Fs /* i : Output sampling rate */ + const TDREND_PosType_t PosType /* i : Position type (absolute/relative) */ ) { TDREND_SRC_t *Src_p; @@ -328,7 +322,7 @@ ivas_error TDREND_MIX_AddSrc( return error; } - TDREND_SRC_Init( Src_p, PosType, output_Fs ); + TDREND_SRC_Init( Src_p, PosType ); /* Special OpenAL initialization due to a common distance attenuation model */ if ( hBinRendererTd->DistAttenModel != 0 ) @@ -343,3 +337,201 @@ ivas_error TDREND_MIX_AddSrc( return error; } + + +/*-------------------------------------------------------------------* + * BSplineModelEvalAlloc() + * + * Allocate the B Spline HR Filter model. + --------------------------------------------------------------------*/ + +static ivas_error BSplineModelEvalAlloc( + ModelParams_t *model, /* i : Model parameters */ + ModelEval_t *modelEval /* i/o: Model evaluation structure */ +) +{ + if ( ( modelEval->hrfModL = (float *) malloc( model->K * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); + } + + if ( ( modelEval->hrfModR = (float *) malloc( model->K * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * DefaultBSplineModel() + * + * Init default HRTF model + --------------------------------------------------------------------*/ + +static ivas_error DefaultBSplineModel( + TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* o : Loaded HR filter set */ + const int32_t output_Fs /* i : Output sampling rate */ +) +{ + ModelParams_t *model; + ModelParamsITD_t *modelITD; + int16_t i, j; + ivas_error error; + + HrFiltSet_p->FilterMethod = TDREND_HRFILT_Method_BSplineModel; + model = &( HrFiltSet_p->ModelParams ); + modelITD = &( HrFiltSet_p->ModelParamsITD ); + + /* Set ROM flag for correct deallocation */ + model->modelROM = TRUE; + + /* int16_t parameters */ + model->UseItdModel = 1; + model->SplineDegree = 4; + model->elevDim2 = 20; + model->elevDim3 = 18; + model->AlphaN = 578; + model->num_unique_azim_splines = 1; + model->elevSegSamples = 3; + model->elevBsLen[0] = 4; + model->elevBsLen[1] = 7; + model->elevBsLen[2] = 10; + model->elevBsLen[3] = 7; + model->elevBsStart[0] = 0; + model->elevBsStart[1] = 4; + model->elevBsStart[2] = 11; + model->elevBsStart[3] = 21; + + model->azimDim2 = orange53_rom_azimDim2; + model->azimDim3 = orange53_rom_azimDim3; + model->azim_start_idx = orange53_rom_azim_start_idx; + model->azimSegSamples = orange53_rom_azimSegSamples; + model->azimShapeIdx = orange53_rom_azimShapeIdx; + model->azimShapeSampFactor = orange53_rom_azimShapeSampFactor; + + /* float parameters */ + model->elevKSeq = (const float *) orange53_rom_elevKSeq; + model->elevBsShape = (const float *) orange53_rom_elevBsShape; + + if ( ( model->azimBsShape = (const float **) malloc( model->num_unique_azim_splines * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); + } + + model->azimBsShape[0] = (const float *) orange53_rom_azimBsShape; + if ( ( model->azimKSeq = (float **) malloc( 18 * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); + } + if ( ( model->azimKSeq[0] = (float *) malloc( 2 * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); + } + if ( ( model->azimKSeq[17] = (float *) malloc( 2 * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); + } + model->azimKSeq[0][0] = 0.0f; + model->azimKSeq[17][0] = 0.0f; + model->azimKSeq[0][1] = 360.0f; + model->azimKSeq[17][1] = 360.0f; + + for ( i = 1; i < 17; i++ ) + { + if ( ( model->azimKSeq[i] = (float *) malloc( model->azimDim2[i] * sizeof( float * ) ) ) == NULL ) /* azimDim2[i] = 91, i=2..15 */ + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); + } + for ( j = 0; j < model->azimDim2[i]; j++ ) + { + model->azimKSeq[i][j] = (float) orange53_rom_azimSegSamples[0] * j; + } + } + + switch ( output_Fs ) + { + case 48000: + model->AlphaL = (const float *) orange53_rom_AlphaL48; + model->AlphaR = (const float *) orange53_rom_AlphaR48; + model->EL = (const float *) orange53_rom_EL48; + model->ER = (const float *) orange53_rom_ER48; + model->K = 128; + if ( HrFiltSet_p->ModelParams.UseItdModel ) + { + modelITD->resamp_factor = 1.0f; + } + break; + case 32000: + model->AlphaL = (const float *) orange53_rom_AlphaL32; + model->AlphaR = (const float *) orange53_rom_AlphaR32; + model->EL = (const float *) orange53_rom_EL32; + model->ER = (const float *) orange53_rom_ER32; + model->K = 86; + if ( HrFiltSet_p->ModelParams.UseItdModel ) + { + modelITD->resamp_factor = RESAMPLE_FACTOR_32_48; + } + break; + case 16000: + model->AlphaL = (const float *) orange53_rom_AlphaL16; + model->AlphaR = (const float *) orange53_rom_AlphaR16; + model->EL = (const float *) orange53_rom_EL16; + model->ER = (const float *) orange53_rom_ER16; + model->K = 43; + if ( HrFiltSet_p->ModelParams.UseItdModel ) + { + modelITD->resamp_factor = RESAMPLE_FACTOR_16_48; + } + break; + default: + break; + } + + modelITD->N = 4; + modelITD->elevDim2 = 20; + modelITD->elevDim3 = 18; + modelITD->azimDim2 = 41; + modelITD->azimDim3 = 41; + modelITD->elevSegSamples = 3; + modelITD->elevBsLen[0] = 4; + modelITD->elevBsLen[1] = 7; + modelITD->elevBsLen[2] = 10; + modelITD->elevBsLen[3] = 7; + modelITD->elevBsStart[0] = 0; + modelITD->elevBsStart[1] = 4; + modelITD->elevBsStart[2] = 11; + modelITD->elevBsStart[3] = 21; + + modelITD->elevKSeq = model->elevKSeq; + + modelITD->azimBsLen[0] = 11; + modelITD->azimBsLen[1] = 21; + modelITD->azimBsLen[2] = 31; + modelITD->azimBsLen[3] = 21; + modelITD->azimBsStart[0] = 0; + modelITD->azimBsStart[1] = 11; + modelITD->azimBsStart[2] = 32; + modelITD->azimBsStart[3] = 63; + + modelITD->azimSegSamples = 10; + + modelITD->azimKSeq = orange53_rom_ITD_azimKSeq; + modelITD->W = (const float *) orange53_rom_ITD_W; + modelITD->azimBsShape = (const float *) orange53_rom_ITD_azimBsShape; + modelITD->elevBsShape = (const float *) orange53_rom_ITD_elevBsShape; + + HRTF_model_precalc( model ); + + HrFiltSet_p->latency_s = orange53_rom_latency_s; + HrFiltSet_p->SampleRate = output_Fs; + HrFiltSet_p->FiltLength = HrFiltSet_p->ModelParams.K; + + if ( ( error = BSplineModelEvalAlloc( &HrFiltSet_p->ModelParams, &HrFiltSet_p->ModelEval ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} diff --git a/lib_rend/ivas_objectRenderer_sfx.c b/lib_rend/ivas_objectRenderer_sfx.c new file mode 100644 index 0000000000000000000000000000000000000000..98f45a5dd94b7d6542e679fda3d122d3a13faaa1 --- /dev/null +++ b/lib_rend/ivas_objectRenderer_sfx.c @@ -0,0 +1,274 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include +#include "ivas_prot_rend.h" +#include "ivas_rom_rend.h" +#include "prot.h" +#include "wmc_auto.h" + + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------* + * Local function prototypes + *---------------------------------------------------------------------*/ + +static void sincResample( const float *input, float *output, const int16_t length_in, const int16_t length_out ); + + +/*---------------------------------------------------------------------* + * TDREND_Apply_ITD() + * + * Apply ITD by delaying late channel + *---------------------------------------------------------------------*/ +void TDREND_Apply_ITD( + float *input, /* i: Input subframe to be time adjusted */ + float *out_left, /* o: Output left channel with ITD applied */ + float *out_right, /* o: Output right channel with ITD applied */ + int16_t *previtd, /*i/o: Previous ITD value */ + const int16_t itd, /* i: Current subframe ITD value */ + float *mem_itd, /*i/o: ITD buffer memory */ + const int16_t length /* i: Subframe length */ +) +{ + int16_t transition_len; + int16_t tlen1, tlen2, tlen3; + int16_t length_in1; + int16_t length_in2; + int16_t currShift; + int16_t prevShift; + float *pstart1; + float *pstart2; + float *pstart3; + float buffer[ITD_MEM_LEN + L_SUBFRAME5MS_48k]; + float *p_input; + float *out_buf_A, *out_buf_B; + + push_wmops( "TDREND_Apply_ITD" ); + + /* Prepare resampling buffer */ + mvr2r( mem_itd, buffer, ITD_MEM_LEN ); /* Retrieve memory */ + p_input = buffer + ITD_MEM_LEN; /* pointer to the current subframe */ + mvr2r( input, p_input, length ); /* input current subframe */ + mvr2r( buffer + length, mem_itd, ITD_MEM_LEN ); /* update memory for next frame */ + + currShift = (int16_t) abs( itd ); + prevShift = (int16_t) abs( *previtd ); + tlen3 = max( 0, SFX_SPAT_BIN_SINC_M - currShift ); /* Make sure there is enough look-ahead for the sinc resampling */ + transition_len = length - tlen3; + + if ( ( ( *previtd ) * itd ) < 0 ) + { + /* ITD sign change - apply shift on both channels */ + tlen1 = (int16_t) ( ( (float) ( transition_len * prevShift ) / ( (float) ( prevShift + currShift ) ) ) + 0.5f ); + tlen2 = transition_len - tlen1; + pstart1 = p_input - prevShift; + length_in1 = tlen1 + prevShift; + pstart2 = pstart1 + length_in1; + length_in2 = tlen2 - currShift; + pstart3 = pstart2 + length_in2; + } + else + { + /* ITD sign stays the same, or one of them is zero */ + tlen1 = transition_len; + tlen2 = 0; + pstart1 = p_input - prevShift; + length_in1 = transition_len + prevShift - currShift; + pstart2 = pstart1 + length_in1; + length_in2 = 0; + pstart3 = pstart2 + length_in2 + currShift; + } + + if ( *previtd == 0 ) + { + if ( itd > 0 ) + { + out_buf_A = out_right; + out_buf_B = out_left; + } + else + { + out_buf_A = out_left; + out_buf_B = out_right; + } + } + else + { + if ( *previtd > 0 ) + { + out_buf_A = out_right; + out_buf_B = out_left; + } + else + { + out_buf_A = out_left; + out_buf_B = out_right; + } + } + + /* Output buffer A */ + sincResample( pstart1, out_buf_A, length_in1, tlen1 ); + mvr2r( pstart2, out_buf_A + tlen1, length - tlen1 ); + + /* Output buffer B */ + mvr2r( p_input, out_buf_B, tlen1 ); + sincResample( pstart2, out_buf_B + tlen1, length_in2, tlen2 ); + mvr2r( pstart3, out_buf_B + transition_len, tlen3 ); + + *previtd = itd; + pop_wmops(); + return; +} + +/*---------------------------------------------------------------------* + * sincResample() + * + * Resample signal (stretch/compress) to new ITD + * The sinc resampling reads SFX_SPAT_BIN_SINC_M (5) samples outside of + * the target frame. + *---------------------------------------------------------------------*/ +static void sincResample( + const float *input, /*i : Input signal */ + float *output, /*o : Output signal */ + const int16_t length_in, /*i : Input length */ + const int16_t length_out /*i : Output length */ +) +{ + int16_t snc0; + int16_t i, j; + int16_t t; + float t_frac; + float t_step; + float tmp; + const float *p_mid; + const float *p_forward; + const float *p_backward; + const float *p_sinc_forward; + const float *p_sinc_backward; + + + /* Compute fractional time step */ + t_step = (float) ( length_in ) / (float) ( length_out ); + t_frac = 0; + + for ( i = 0; i < length_out; i++ ) + { + t = (int16_t) ( t_frac + EPSILON ); + + /* Calculate the sinc-index for the center value of the sinc */ + snc0 = (int16_t) ( ( t_frac - t + EPSILON ) * SFX_SPAT_BIN_NUM_SUBSAMPLES + 0.5f ); + + /* Run convolution forward and backward from mid point */ + p_mid = input + t; + p_forward = p_mid + 1; + p_backward = p_mid - 1; + p_sinc_forward = SincTable + SFX_SPAT_BIN_NUM_SUBSAMPLES - snc0; + p_sinc_backward = SincTable + SFX_SPAT_BIN_NUM_SUBSAMPLES + snc0; + + tmp = *p_mid * SincTable[snc0]; /* Middle point */ + for ( j = 0; j < SFX_SPAT_BIN_SINC_M - 1; j++ ) + { + tmp += ( *p_forward ) * ( *p_sinc_forward ) + ( *p_backward ) * ( *p_sinc_backward ); + p_sinc_forward += SFX_SPAT_BIN_NUM_SUBSAMPLES; + p_sinc_backward += SFX_SPAT_BIN_NUM_SUBSAMPLES; + p_forward++; + p_backward--; + } + tmp += ( *p_forward ) * ( *p_sinc_forward ); /* Integer index always rounded down --> 4 steps backward, 5 steps forward */ + + output[i] = tmp; + + /* Advance fractional time */ + t_frac += t_step; + } + + return; +} + +/*-------------------------------------------------------------------* + * TDREND_firfilt() + * + * FIR filtering function + * + --------------------------------------------------------------------*/ + +void TDREND_firfilt( + float *signal, /* i/o: Input signal / Filtered signal */ + float *filter, /* i/o: FIR filter */ + const float *filter_delta, /* i : FIR filter delta */ + const int16_t intp_count, /* i : interpolation count */ + float *mem, /* i/o: filter memory */ + const int16_t subframe_length, /* i : Length of signal */ + const int16_t filterlength, /* i : Filter length */ + const float Gain /* i : Gain */ +) +{ + float buffer[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 + L_SUBFRAME5MS_48k]; + float *p_signal; + float *p_tmp; + float *p_filter; + float tmp; + int16_t i, j; + + /* Handle memory */ + p_signal = buffer + filterlength - 1; + mvr2r( mem, buffer, filterlength - 1 ); /* Insert memory */ + mvr2r( signal, buffer + filterlength - 1, subframe_length ); /* Insert current frame */ + mvr2r( signal + subframe_length - filterlength + 1, mem, filterlength - 1 ); /* Update memory for next frame */ + + /* Convolution */ + for ( i = 0; i < subframe_length; i++ ) + { + tmp = 0.0f; + p_tmp = p_signal + i; + p_filter = filter; + for ( j = 0; j < filterlength; j++ ) + { + tmp += ( *p_filter++ ) * ( *p_tmp-- ); + } + signal[i] = tmp * Gain; + + if ( i < intp_count ) + { + v_add( filter, filter_delta, filter, filterlength ); + } + } + + return; +} diff --git a/lib_dec/ivas_objectRenderer_sources.c b/lib_rend/ivas_objectRenderer_sources.c similarity index 79% rename from lib_dec/ivas_objectRenderer_sources.c rename to lib_rend/ivas_objectRenderer_sources.c index b24708a1955db2c8bb3f273696ea302d9800f5ca..b14db0b7c2f69c0d784f3f528c4dfa4bc7e8cabe 100644 --- a/lib_dec/ivas_objectRenderer_sources.c +++ b/lib_rend/ivas_objectRenderer_sources.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,36 +33,41 @@ #include #include "options.h" #include -#include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "ivas_prot_rend.h" +#include "wmc_auto.h" #ifdef DEBUGGING #include "debug.h" #endif + /*---------------------------------------------------------------------* * Local function prototypes *---------------------------------------------------------------------*/ static void TDREND_SRC_SPATIAL_Dealloc( TDREND_SRC_SPATIAL_t *SrcSpatial_p ); + static void TDREND_SRC_SPATIAL_Init( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_PosType_t PosType ); + static void TDREND_SRC_SPATIAL_SetDirAtten( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DirAtten_t *DirAtten_p ); + static float TDREND_SRC_SPATIAL_GetDirGain( const TDREND_DirAtten_t *DirAtten_p, const float *Front_p, const float *RelPos_p ); + static float TDREND_SRC_SPATIAL_GetDistGain( const TDREND_DistAtten_t *DistAtten_p, const float Dist ); + static ivas_error TDREND_SRC_REND_Alloc( TDREND_SRC_REND_t **SrcRend_pp ); -static void TDREND_SRC_REND_Dealloc( TDREND_SRC_REND_t *SrcRend_p ); -static void TDREND_SRC_REND_Init( TDREND_SRC_REND_t *SrcRend_p, const int32_t output_Fs ); + +static void TDREND_SRC_REND_Init( TDREND_SRC_REND_t *SrcRend_p ); /*-------------------------------------------------------------------* - * TDREND_MIX_SetSrcPos() + * TDREND_MIX_SRC_SetPos() * * Set source position --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_SRC_SetPos( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const int16_t SrcInd, /* i : Source index */ const float *Vec_p /* i : Position vector */ ) @@ -91,10 +96,9 @@ ivas_error TDREND_MIX_SRC_SetPos( /*-------------------------------------------------------------------* * TDREND_MIX_SRC_SetDir() * - * Set source direciton + * Set source direction --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_SRC_SetDir( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const int16_t SrcInd, /* i : Source index */ @@ -129,7 +133,6 @@ ivas_error TDREND_MIX_SRC_SetDir( * Set directional attenuation for the mixer. --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_SRC_SetDirAtten( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const int16_t SrcInd, /* i : Source index */ @@ -146,6 +149,7 @@ ivas_error TDREND_MIX_SRC_SetDirAtten( SrcSpatial_p = hBinRendererTd->Sources[SrcInd]->SrcSpatial_p; TDREND_SRC_SPATIAL_SetDirAtten( SrcSpatial_p, DirAtten_p ); } + return IVAS_ERR_OK; } @@ -156,7 +160,6 @@ ivas_error TDREND_MIX_SRC_SetDirAtten( * Set play state for the source. --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_MIX_SRC_SetPlayState( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const int16_t SrcInd, /* i : Source index */ @@ -181,7 +184,6 @@ ivas_error TDREND_MIX_SRC_SetPlayState( * Renderer allocation --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ static ivas_error TDREND_SRC_REND_Alloc( TDREND_SRC_REND_t **SrcRend_pp /* i/o: Source object */ ) @@ -191,76 +193,17 @@ static ivas_error TDREND_SRC_REND_Alloc( *SrcRend_pp = NULL; /* Allocate the TDREND_SRC_REND_t variable */ - SrcRend_p = (TDREND_SRC_REND_t *) count_malloc( sizeof( TDREND_SRC_REND_t ) ); - if ( SrcRend_p == NULL ) + if ( ( SrcRend_p = (TDREND_SRC_REND_t *) malloc( sizeof( TDREND_SRC_REND_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "SrcRend_p allocation error\n" ) ); } - /* Allocate the HR filtering structures */ - SrcRend_p->SfxSpatBin_p = (SFX_SpatBin_t *) count_malloc( SPAT_BIN_MAX_INPUT_CHANNELS * sizeof( SFX_SpatBin_t ) ); - if ( SrcRend_p->SfxSpatBin_p == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "SrcRend_p->SfxSpatBin_p allocation error\n" ) ); - } - *SrcRend_pp = SrcRend_p; return IVAS_ERR_OK; } -/*-------------------------------------------------------------------* - * TDREND_SRC_REND_Dealloc() - * - * Deallocate rendering aspects of source. - --------------------------------------------------------------------*/ - -static void TDREND_SRC_REND_Dealloc( - TDREND_SRC_REND_t *SrcRend_p /* i/o: Source object */ -) -{ - if ( SrcRend_p == NULL ) - { - return; - } - if ( SrcRend_p->SfxSpatBin_p->LeftOldBuffer != NULL ) - { - count_free( SrcRend_p->SfxSpatBin_p->LeftOldBuffer ); - } - if ( SrcRend_p->SfxSpatBin_p->RightOldBuffer != NULL ) - { - count_free( SrcRend_p->SfxSpatBin_p->RightOldBuffer ); - } - if ( SrcRend_p->SfxSpatBin_p->LeftFilter_p != NULL ) - { - count_free( SrcRend_p->SfxSpatBin_p->LeftFilter_p ); - } - if ( SrcRend_p->SfxSpatBin_p->LeftFilterIncr_p != NULL ) - { - count_free( SrcRend_p->SfxSpatBin_p->LeftFilterIncr_p ); - } - if ( SrcRend_p->SfxSpatBin_p->RightFilter_p != NULL ) - { - count_free( SrcRend_p->SfxSpatBin_p->RightFilter_p ); - } - if ( SrcRend_p->SfxSpatBin_p->RightFilterIncr_p != NULL ) - { - count_free( SrcRend_p->SfxSpatBin_p->RightFilterIncr_p ); - } - if ( SrcRend_p->SfxSpatBin_p != NULL ) - { - count_free( SrcRend_p->SfxSpatBin_p ); - } - - /* Free the SrcRend_p variable */ - count_free( SrcRend_p ); - SrcRend_p = NULL; - - return; -} - - /*-------------------------------------------------------------------* * TDREND_SRC_REND_Init() * @@ -268,8 +211,7 @@ static void TDREND_SRC_REND_Dealloc( --------------------------------------------------------------------*/ static void TDREND_SRC_REND_Init( - TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ - const int32_t output_Fs /* i : Output sampling rate */ + TDREND_SRC_REND_t *SrcRend_p /* i/o: Source object */ ) { int16_t nC; @@ -278,9 +220,6 @@ static void TDREND_SRC_REND_Init( SrcRend_p->InputAvailable = FALSE; SrcRend_p->PlayStatus = TDREND_PLAYSTATUS_INITIAL; -#ifdef TDREND_HRTF_TABLE_METHODS - SrcRend_p->SfxSpatBin_p->HrFilterInterpOn = 0; /* Disabled for first frame */ -#endif /* SrcGain */ for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ ) { @@ -297,11 +236,6 @@ static void TDREND_SRC_REND_Init( SrcRend_p->DistGain_p[nC] = 1.0f; } - /* Init the SfxSpatBin structs. One per channel. Default is effect turned off. */ - for ( nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ ) - { - TDREND_SFX_SpatBin_Initialize( SrcRend_p->SfxSpatBin_p + nC, output_Fs ); - } return; } @@ -317,35 +251,33 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i : Spatial aspects of source */ - const int32_t output_Fs /* i : Output sampling rate */ + float *hrf_left_prev, /* o: Left filter */ + float *hrf_right_prev, /* o: Right filter */ + float *hrf_left_delta, /* o: Left filter interpolation delta */ + float *hrf_right_delta, /* o: Right filter interpolation delta */ + int16_t *intp_count, /* o: Interpolation count */ + int16_t *filterlength, /* o: Length of filters */ + int16_t *itd, /* o: ITD value */ + float *Gain, /* o: Gain value */ + TDREND_SRC_t *Src_p, /* i/o: Source pointer */ + const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */ ) { TDREND_MIX_Listener_t *Listener_p; TDREND_HRFILT_FiltSet_t *HrFiltSet_p; - SFX_SpatBin_t *SfxSpatBin_p; - SFX_SpatBin_Params_t SfxSpatBinParams; - float ListRelPos[3], ListRelDist; - float Gain; + float ListRelPosAbs[3]; /* Relative position, ignoring orientation of listener */ float Azim, Elev; - int16_t mem_size; + float hrf_left[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + float hrf_right[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + float azim_delta; + float elev_delta; /* Evaluate the HR filters from the source and listener positions and orientations */ Listener_p = hBinRendererTd->Listener_p; HrFiltSet_p = hBinRendererTd->HrFiltSet_p; - SfxSpatBinParams.LeftFilter_p = NULL; - SfxSpatBinParams.RightFilter_p = NULL; - - mem_size = (int16_t) ( HrFiltSet_p->FiltLength * sizeof( float ) ); - - SfxSpatBin_p = SrcRend_p->SfxSpatBin_p; - SfxSpatBinParams.TurnOn = TRUE; - SfxSpatBinParams.Reset = FALSE; - - SfxSpatBinParams.FilterLength = HrFiltSet_p->FiltLength; - SfxSpatBinParams.LeftFilter_p = (float *) count_malloc( mem_size ); - SfxSpatBinParams.RightFilter_p = (float *) count_malloc( mem_size ); + *filterlength = HrFiltSet_p->FiltLength; /* 1. Map source pos to the coordinate system of the listener */ switch ( SrcSpatial_p->PosType ) @@ -356,14 +288,14 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( break; case TDREND_POSTYPE_ABSOLUTE: /* Absolute position */ - TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos ); + TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos, ListRelPosAbs ); break; default: /* Illegal position type */ #ifdef DEBUGGING printf( "Warning! TDREND_SRC_REND_UpdateFiltersFromSpatialParams: Invalid position type. Assuming absolute position!\n" ); #endif /* Assume absolute position */ - TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos ); + TDREND_SPATIAL_VecMapToNewCoordSystem( SrcSpatial_p->Pos_p, Listener_p->Pos, Listener_p->Front, Listener_p->Up, Listener_p->Right, ListRelPos, ListRelPosAbs ); break; } @@ -382,14 +314,14 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( Azim = -1.0f * _180_OVER_PI * (float) atan2f( ListRelPos[1], ListRelPos[0] ); } - GetFilterFromAngle( HrFiltSet_p, Elev, Azim, &SfxSpatBinParams ); + GetFilterFromAngle( HrFiltSet_p, Elev, Azim, hrf_left, hrf_right, itd ); /* 6. Evaluate the directional and distance gains */ /* Directional gain */ *SrcRend_p->DirGain_p = 1.0f; if ( SrcSpatial_p->DirAttenEnabled ) { - *SrcRend_p->DirGain_p = TDREND_SRC_SPATIAL_GetDirGain( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p, ListRelPos ); + *SrcRend_p->DirGain_p = TDREND_SRC_SPATIAL_GetDirGain( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p, ListRelPosAbs ); } /* Distance gain */ @@ -411,24 +343,32 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( } /* Update total gains */ - Gain = ( *SrcRend_p->SrcGain_p ) * ( *SrcRend_p->DirGain_p ) * ( *SrcRend_p->DistGain_p ) * hBinRendererTd->Gain; - SfxSpatBinParams.LeftVolume = Gain; - SfxSpatBinParams.RightVolume = Gain; + *Gain = ( *SrcRend_p->SrcGain_p ) * ( *SrcRend_p->DirGain_p ) * ( *SrcRend_p->DistGain_p ) * hBinRendererTd->Gain; - /* Reset source gain update flag (That update is now included in the total gain update) */ - SrcRend_p->SrcGainUpdated = FALSE; + /* Delta for interpolation, in case the angular step exceeds MAX_ANGULAR_STEP */ + elev_delta = Elev - Src_p->elev_prev; + azim_delta = Azim - Src_p->azim_prev; + Src_p->elev_prev = Elev; + Src_p->azim_prev = Azim; - /* Update the rendering parameters of the SFX effect */ - TDREND_SFX_SpatBin_SetParams( SfxSpatBin_p, &SfxSpatBinParams, output_Fs ); + azim_delta = ( azim_delta > 180.0f ) ? ( azim_delta - 360 ) : ( ( azim_delta < -180.0f ) ? ( azim_delta + 360 ) : ( azim_delta ) ); /* map to -180:180 range */ + *intp_count = min( MAX_INTERPOLATION_STEPS, max( (int16_t) ( fabsf( azim_delta ) * MAX_ANGULAR_STEP_INV ), (int16_t) ( fabsf( elev_delta ) * MAX_ANGULAR_STEP_INV ) ) ); - if ( SfxSpatBinParams.LeftFilter_p != NULL ) + if ( ( *intp_count > 0 ) && subframe_idx == 0 ) { - count_free( SfxSpatBinParams.LeftFilter_p ); + /* Set deltas for interpolation */ + v_sub( hrf_left, hrf_left_prev, hrf_left_delta, *filterlength ); + v_multc( hrf_left_delta, 1.0f / *intp_count, hrf_left_delta, *filterlength ); + v_sub( hrf_right, hrf_right_prev, hrf_right_delta, *filterlength ); + v_multc( hrf_right_delta, 1.0f / *intp_count, hrf_right_delta, *filterlength ); } - - if ( SfxSpatBinParams.RightFilter_p != NULL ) + else { - count_free( SfxSpatBinParams.RightFilter_p ); + /* No interpolation, just set the new filters and reset deltas */ + mvr2r( hrf_left, hrf_left_prev, *filterlength ); + mvr2r( hrf_right, hrf_right_prev, *filterlength ); + set_f( hrf_left_delta, 0.0f, *filterlength ); + set_f( hrf_right_delta, 0.0f, *filterlength ); } return; @@ -441,7 +381,6 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( * Allocatie spatial properties of a source. --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ static ivas_error TDREND_SRC_SPATIAL_Alloc( TDREND_SRC_SPATIAL_t **SrcSpatial_pp /* i/o: Source spatial parameters */ ) @@ -451,8 +390,7 @@ static ivas_error TDREND_SRC_SPATIAL_Alloc( *SrcSpatial_pp = NULL; /* Allocate the TDREND_SRC_t variable */ - SrcSpatial_p = (TDREND_SRC_SPATIAL_t *) count_malloc( sizeof( TDREND_SRC_SPATIAL_t ) ); - if ( SrcSpatial_p == NULL ) + if ( ( SrcSpatial_p = (TDREND_SRC_SPATIAL_t *) malloc( sizeof( TDREND_SRC_SPATIAL_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "TDREND_SRC_SPATIAL_t allocation error\n" ) ); } @@ -478,7 +416,7 @@ static void TDREND_SRC_SPATIAL_Dealloc( return; } /* Free the SrcSpatial_p variable */ - count_free( SrcSpatial_p ); + free( SrcSpatial_p ); SrcSpatial_p = NULL; return; @@ -522,7 +460,11 @@ static void TDREND_SRC_SPATIAL_Init( SrcSpatial_p->DistAttenEnabled = FALSE; SrcSpatial_p->DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; SrcSpatial_p->DistAtten.RefDist = 1.0f; +#ifdef FIX_379_EXT_METADATA + SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ +#else SrcSpatial_p->DistAtten.MaxDist = 10.0f; +#endif SrcSpatial_p->DistAtten.RollOffFactor = 1.0f; return; @@ -651,7 +593,6 @@ static float TDREND_SRC_SPATIAL_GetDistGain( * Allocate a source. --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ ivas_error TDREND_SRC_Alloc( TDREND_SRC_t **Src_pp /* i/o: Source */ ) @@ -664,8 +605,7 @@ ivas_error TDREND_SRC_Alloc( *Src_pp = NULL; /* Allocate the TDREND_SRC_t variable */ - Src_p = (TDREND_SRC_t *) count_malloc( sizeof( TDREND_SRC_t ) ); - if ( Src_p == NULL ) + if ( ( Src_p = (TDREND_SRC_t *) malloc( sizeof( TDREND_SRC_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, " TDREND_SRC_Alloc: Allocation error\n" ) ); } @@ -706,10 +646,11 @@ void TDREND_SRC_Dealloc( TDREND_SRC_SPATIAL_Dealloc( Src_p->SrcSpatial_p ); /* Delloc the TDREND_SRC_REND__t variable */ - TDREND_SRC_REND_Dealloc( Src_p->SrcRend_p ); + free( Src_p->SrcRend_p ); + Src_p->SrcRend_p = NULL; /* Free the Src_p variable */ - count_free( Src_p ); + free( Src_p ); Src_p = NULL; return; @@ -723,9 +664,8 @@ void TDREND_SRC_Dealloc( --------------------------------------------------------------------*/ void TDREND_SRC_Init( - TDREND_SRC_t *Src_p, /* i/o: Source to initialize */ - const TDREND_PosType_t PosType, /* i : Position type specifier */ - const int32_t output_Fs /* i : Output sampling rate */ + TDREND_SRC_t *Src_p, /* i/o: Source to initialize */ + const TDREND_PosType_t PosType /* i : Position type specifier */ ) { /* Init the TDREND_SRC_Spatial_t variable */ @@ -735,7 +675,23 @@ void TDREND_SRC_Init( } /* Init the TDREND_SRC_REND_t variable */ - TDREND_SRC_REND_Init( Src_p->SrcRend_p, output_Fs ); + TDREND_SRC_REND_Init( Src_p->SrcRend_p ); + + /* Reset memory buffers */ + Src_p->itd = 0; + Src_p->previtd = 0; + Src_p->filterlength = -1; + set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN ); + set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); + set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); + + set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + Src_p->hrf_left_prev[0] = 1; + Src_p->hrf_right_prev[0] = 1; + Src_p->azim_prev = 0.0f; + Src_p->elev_prev = 0.0f; + return; } diff --git a/lib_dec/ivas_objectRenderer_vec.c b/lib_rend/ivas_objectRenderer_vec.c similarity index 91% rename from lib_dec/ivas_objectRenderer_vec.c rename to lib_rend/ivas_objectRenderer_vec.c index a3bd94683b4b2b0afc881a7481e8f59792bf8a3d..061b790e1b46e9010d14a0b0162b528bbd3768fb 100644 --- a/lib_dec/ivas_objectRenderer_vec.c +++ b/lib_rend/ivas_objectRenderer_vec.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,13 +33,14 @@ #include #include "options.h" #include -#include "ivas_prot.h" #include "prot.h" -#include "wmops.h" +#include "ivas_prot_rend.h" +#include "wmc_auto.h" #ifdef DEBUGGING #include "debug.h" #endif + /*-------------------------------------------------------------------* * TDREND_SPATIAL_VecInit() * @@ -89,7 +90,7 @@ void TDREND_SPATIAL_VecNormalize( { float scaler; - scaler = 1.0f / sqrtf( Vec_p[0] * Vec_p[0] + Vec_p[1] * Vec_p[1] + Vec_p[2] * Vec_p[2] ); + scaler = inv_sqrt( Vec_p[0] * Vec_p[0] + Vec_p[1] * Vec_p[1] + Vec_p[2] * Vec_p[2] ); VecNorm_p[0] = scaler * Vec_p[0]; VecNorm_p[1] = scaler * Vec_p[1]; VecNorm_p[2] = scaler * Vec_p[2]; @@ -110,20 +111,16 @@ void TDREND_SPATIAL_VecMapToNewCoordSystem( const float *DirVec_p, /* i : Direction vector */ const float *UpVec_p, /* i : Up vector */ const float *RightVec_p, /* i : Right vector */ - float *MappedVec_p /* o : Transformed vector */ + float *MappedVec_p, /* o : Transformed vector */ + float *LisRelPosAbs /* o : Transformed vector ignoring orientation */ ) { - float RelVec[3]; - - /* Evaluate Vec relative to the new origin given by TranslVec */ - v_sub( Vec_p, TranslVec_p, RelVec, 3 ); - + v_sub( Vec_p, TranslVec_p, LisRelPosAbs, 3 ); /* Evalute the relative Vec in the coordinates of the Orientation vectors, */ /* which form an orthonormal basis */ - MappedVec_p[0] = dotp( RelVec, DirVec_p, 3 ); - MappedVec_p[1] = dotp( RelVec, RightVec_p, 3 ); - MappedVec_p[2] = dotp( RelVec, UpVec_p, 3 ); - + MappedVec_p[0] = dotp( LisRelPosAbs, DirVec_p, 3 ); + MappedVec_p[1] = dotp( LisRelPosAbs, RightVec_p, 3 ); + MappedVec_p[2] = dotp( LisRelPosAbs, UpVec_p, 3 ); return; } diff --git a/lib_rend/ivas_orient_trk.c b/lib_rend/ivas_orient_trk.c new file mode 100644 index 0000000000000000000000000000000000000000..63d863c4b635dcdfc832f9c0027d165a7c902238 --- /dev/null +++ b/lib_rend/ivas_orient_trk.c @@ -0,0 +1,674 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "common_api_types.h" +#include +#include "options.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_cnst.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include +#include +#include "wmc_auto.h" + + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + +#define MAX_TRACKED_ANGLE_AVG_ORIENT PI_OVER_2 +#define MAX_TRACKED_ANGLE_REF_ORIENT EVS_PI +#define OTR_UPDATE_RATE (float) FRAMES_PER_SEC /* rate of the Process() calls [Hz]; 1x per IVAS frame */ + + +/*------------------------------------------------------------------------------------------* + * Local functions + *------------------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------------------* + * IdentityQuaternion() + * + * + *------------------------------------------------------------------------------------------*/ + +static IVAS_QUATERNION IdentityQuaternion( + void ) +{ + IVAS_QUATERNION q; + + q.w = 1.0f; + q.x = q.y = q.z = 0.0f; + + return q; +} + + +/*------------------------------------------------------------------------------------------* + * QuaternionProduct() + * + * Quaternion product + *------------------------------------------------------------------------------------------*/ + +static void QuaternionProduct( + const IVAS_QUATERNION q1, + const IVAS_QUATERNION q2, + IVAS_QUATERNION *const r ) +{ + IVAS_QUATERNION tmp; + tmp.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; + tmp.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; + tmp.y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x; + tmp.z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w; + + *r = tmp; + + return; +} + +/*------------------------------------------------------------------------------------------* + * QuaternionDotProduct() + * + * Quaternion dot product + *------------------------------------------------------------------------------------------*/ + +static float QuaternionDotProduct( + const IVAS_QUATERNION q1, + const IVAS_QUATERNION q2 ) +{ + return q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w; +} + + +/*------------------------------------------------------------------------------------------* + * QuaternionDivision() + * + * Divides a quaternion by a scalar + *------------------------------------------------------------------------------------------*/ + +static void QuaternionDivision( + const IVAS_QUATERNION q, + const float d, + IVAS_QUATERNION *const r ) +{ + r->w = q.w / d; + r->x = q.x / d; + r->y = q.y / d; + r->z = q.z / d; + + return; +} + + +/*------------------------------------------------------------------------------------------* + * QuaternionNormalize() + * + * Normalizes a quaternion + *------------------------------------------------------------------------------------------*/ + +static void QuaternionNormalize( + const IVAS_QUATERNION q, + IVAS_QUATERNION *const r ) +{ + QuaternionDivision( q, sqrtf( QuaternionDotProduct( q, q ) ), r ); + + return; +} + + +/*------------------------------------------------------------------------------------------* + * QuaternionSlerp() + * + * Computes a spherical linear interpolation between two quaternions + *------------------------------------------------------------------------------------------*/ + +static void QuaternionSlerp( + const IVAS_QUATERNION q1, + const IVAS_QUATERNION q2, + const float t, + IVAS_QUATERNION *const r ) +{ + float angle, denom, s, s2; + + s = QuaternionDotProduct( q1, q2 ); + + if ( fabsf( s ) >= 1.0f ) + { + *r = q2; + return; + } + + angle = acosf( s ); + denom = sinf( angle ); + + s = sinf( ( 1 - t ) * angle ); + s2 = sinf( t * angle ); + r->x = ( q1.x * s + q2.x * s2 ) / denom; + r->y = ( q1.y * s + q2.y * s2 ) / denom; + r->z = ( q1.z * s + q2.z * s2 ) / denom; + r->w = ( q1.w * s + q2.w * s2 ) / denom; + + QuaternionNormalize( *r, r ); + + return; +} + + +/*------------------------------------------------------------------------------------------* + * QuaternionConjugate() + * + * Computes a quaternion conjugate + *------------------------------------------------------------------------------------------*/ + +static void QuaternionConjugate( + const IVAS_QUATERNION q, + IVAS_QUATERNION *const r ) +{ + r->w = q.w; + r->x = -q.x; + r->y = -q.y; + r->z = -q.z; + + return; +} + + +/*------------------------------------------------------------------------------------------* + * QuaternionAngle() + * + * Computes an angle between two quaternions + *------------------------------------------------------------------------------------------*/ + +static float QuaternionAngle( + const IVAS_QUATERNION q1, + const IVAS_QUATERNION q2 ) +{ + IVAS_QUATERNION q12; + float angle; + + QuaternionConjugate( q1, &q12 ); + QuaternionProduct( q12, q2, &q12 ); + angle = 2.0f * atan2f( sqrtf( q12.x * q12.x + q12.y * q12.y + q12.z * q12.z ), q12.w ); + + return angle; +} + + +/*------------------------------------------------------------------------------------------* + * QuaternionInverse() + * + * Computes an inverse quaternion + *------------------------------------------------------------------------------------------*/ + +static void QuaternionInverse( + const IVAS_QUATERNION q, + IVAS_QUATERNION *const r ) +{ + float dot_product; + + dot_product = QuaternionDotProduct( q, q ); + QuaternionConjugate( q, r ); + QuaternionDivision( *r, dot_product, r ); + + return; +} + + +/*------------------------------------------------------------------------------------------* + * VectorSubtract() + * + * Computes the difference of two vectors + *------------------------------------------------------------------------------------------*/ + +static IVAS_VECTOR3 VectorSubtract( + const IVAS_VECTOR3 p1, + const IVAS_VECTOR3 p2 ) +{ + IVAS_VECTOR3 result; + + result.x = p1.x - p2.x; + result.y = p1.y - p2.y; + result.z = p1.z - p2.z; + + return result; +} + + +/*------------------------------------------------------------------------------------------* + * VectorCrossProduct() + * + * Computes the cross product of two vectors + *------------------------------------------------------------------------------------------*/ + +static IVAS_VECTOR3 VectorCrossProduct( + const IVAS_VECTOR3 p1, + const IVAS_VECTOR3 p2 ) +{ + IVAS_VECTOR3 result; + result.x = p1.y * p2.z - p1.z * p2.y; + result.y = p1.z * p2.x - p1.x * p2.z; + result.z = p1.x * p2.y - p1.y * p2.x; + + return result; +} + + +/*------------------------------------------------------------------------------------------* + * VectorDotProduct( + * + * Computes the dot product of two vectors + *------------------------------------------------------------------------------------------*/ + +static float VectorDotProduct( + const IVAS_VECTOR3 p1, + const IVAS_VECTOR3 p2 ) +{ + return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z; +} + + +/*------------------------------------------------------------------------------------------* + * VectorLength() + * + * Computes the length of a vector + *------------------------------------------------------------------------------------------*/ + +static float VectorLength( + const IVAS_VECTOR3 p ) +{ + return sqrtf( p.x * p.x + p.y * p.y + p.z * p.z ); +} + + +/*------------------------------------------------------------------------------------------* + * VectorNormalize() + * + * Normalizes a vector + *------------------------------------------------------------------------------------------*/ + +static IVAS_VECTOR3 VectorNormalize( + const IVAS_VECTOR3 p ) +{ + IVAS_VECTOR3 result; + + const float length = VectorLength( p ); + + result.x = p.x / length; + result.y = p.y / length; + result.z = p.z / length; + + return result; +} + + +/*------------------------------------------------------------------------------------------* + * VectorRotationToQuaternion() + * + * Computes a quaternion representing the rotation from vector p1 to vector p2 + *------------------------------------------------------------------------------------------*/ + +static void VectorRotationToQuaternion( + const IVAS_VECTOR3 p1, + const IVAS_VECTOR3 p2, + IVAS_QUATERNION *const r ) +{ + float dot_product; + IVAS_VECTOR3 cross_product, p1_normalized, p2_normalized; + + p1_normalized = VectorNormalize( p1 ); + p2_normalized = VectorNormalize( p2 ); + cross_product = VectorCrossProduct( p1_normalized, p2_normalized ); + dot_product = VectorDotProduct( p1_normalized, p2_normalized ); + + if ( dot_product < -0.999999 ) + { + /* happens when the p1 vector is parallel to p2, but direction is flipped */ + r->w = 0.0f; + r->x = 0.0f; + r->y = 0.0f; + r->z = 1.0f; + } + else + { + /* all regular cases */ + r->x = cross_product.x; + r->y = cross_product.y; + r->z = cross_product.z; + r->w = 1.0f + dot_product; + } + + QuaternionNormalize( *r, r ); + + return; +} + +/*-------------------------------------------------------------------* + * ivas_orient_trk_Init() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_Init( + ivas_orient_trk_state_t *pOTR ) /* i/o : orientation tracker handle */ +{ + IVAS_QUATERNION identity; + + if ( pOTR == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + identity.w = 1.0f; + identity.x = identity.y = identity.z = 0.0f; + + /* configuration parameters */ + pOTR->centerAdaptationRate = 1.0f / 30.0f; + pOTR->offCenterAdaptationRate = 1.0f / 8.0f; + pOTR->adaptationAngle = PI_OVER_2; /* Excursion angle relative to center at which maximum adaptation rate shall be applied */ + + /* initial adaptivity filter coefficient, will be auto-adapted */ + pOTR->alpha = sinf( PI2 * pOTR->offCenterAdaptationRate / OTR_UPDATE_RATE ); /* start adaptation at off-center rate = fastest rate */ + + pOTR->trkRot = identity; + pOTR->absAvgRot = identity; + /* Use frontal and horiontal orientation as reference orientation, unless/until overridden */ + pOTR->refRot = identity; + + /* set safe default tracking mode */ + pOTR->trackingType = OTR_TRACKING_NONE; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_orient_trk_SetTrackingType() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_SetTrackingType( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + const OTR_TRACKING_T trackingType /* i/o: orientation tracking type */ +) +{ + if ( pOTR == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + pOTR->trackingType = trackingType; + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ivas_orient_trk_SetReferenceRotation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_SetReferenceRotation( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + const IVAS_QUATERNION refRot /* i : reference rotation */ +) +{ + if ( pOTR == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + /* check for Euler angle signaling */ + if ( refRot.w == -3.0f ) + { + Euler2Quat( deg2rad( refRot.x ), deg2rad( refRot.y ), deg2rad( refRot.z ), &pOTR->refRot ); + } + else + { + pOTR->refRot = refRot; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_orient_trk_GetMainOrientation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_GetMainOrientation( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + IVAS_QUATERNION *pOrientation /* i/o: average/reference orientation */ +) +{ + if ( pOTR == NULL || pOrientation == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + switch ( pOTR->trackingType ) + { + case OTR_TRACKING_NONE: + *pOrientation = IdentityQuaternion(); + break; + case OTR_TRACKING_REF_VEC: + case OTR_TRACKING_REF_VEC_LEV: + case OTR_TRACKING_REF_ORIENT: + *pOrientation = pOTR->refRot; + break; + case OTR_TRACKING_AVG_ORIENT: + *pOrientation = pOTR->absAvgRot; + break; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_orient_trk_GetTrackedRotation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_GetTrackedRotation( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + IVAS_QUATERNION *pRotation /* i/o: processed rotation */ +) +{ + if ( pOTR == NULL || pRotation == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *pRotation = pOTR->trkRot; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_orient_trk_SetReferenceVector() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_SetReferenceVector( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + const IVAS_VECTOR3 listenerPos, /* i : Listener position */ + const IVAS_VECTOR3 refPos /* i : Reference position */ +) +{ + IVAS_VECTOR3 acousticFrontVector, ivasForwardVector; + IVAS_VECTOR3 listenerPosLevel, refPosLevel; + float acousticFrontVectorLength; + + if ( pOTR == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + switch ( pOTR->trackingType ) + { + case OTR_TRACKING_NONE: + case OTR_TRACKING_REF_ORIENT: + case OTR_TRACKING_AVG_ORIENT: + case OTR_TRACKING_REF_VEC: + acousticFrontVector = VectorSubtract( listenerPos, refPos ); + break; + case OTR_TRACKING_REF_VEC_LEV: + /* ignore the height difference between listener position and reference position */ + listenerPosLevel.z = refPosLevel.z = listenerPos.z; + listenerPosLevel.x = listenerPos.x; + listenerPosLevel.y = listenerPos.y; + refPosLevel.x = refPos.x; + refPosLevel.y = refPos.y; + acousticFrontVector = VectorSubtract( listenerPosLevel, refPosLevel ); + break; + default: + return IVAS_ERR_WRONG_PARAMS; + } + + acousticFrontVectorLength = VectorLength( acousticFrontVector ); + + /* if the length is zero, the user has entered insensible listener and reference positions */ + if ( acousticFrontVectorLength < 0.0001f ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + ivasForwardVector.x = -1.0f; + ivasForwardVector.y = 0.0f; + ivasForwardVector.z = 0.0f; + VectorRotationToQuaternion( ivasForwardVector, acousticFrontVector, &pOTR->refRot ); + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_orient_trk_Process() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_Process( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + IVAS_QUATERNION absRot, /* i : absolute head rotation */ + float updateRate, /* i : rotation update rate [Hz] */ + IVAS_QUATERNION *pTrkRot /* o : tracked rotation */ +) +{ + float normalizedOrientation; + float relativeOrientationRate; + float rateRange; + float cutoffFrequency; + float alpha = pOTR->alpha; + float ang; + ivas_error result; + + if ( pOTR == NULL || pTrkRot == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + result = IVAS_ERR_OK; + + switch ( pOTR->trackingType ) + { + case OTR_TRACKING_NONE: + pOTR->trkRot = absRot; + break; + case OTR_TRACKING_REF_VEC: + case OTR_TRACKING_REF_VEC_LEV: + case OTR_TRACKING_REF_ORIENT: + /* Reset average orientation */ + pOTR->absAvgRot = absRot; + + /* Reset adaptation filter - start adaptation at center rate */ + pOTR->alpha = sinf( 2.0f * EVS_PI * pOTR->centerAdaptationRate / updateRate ); + + /* Compute relative orientation = (absolute orientation) - (reference orientation) */ + QuaternionInverse( pOTR->refRot, &pOTR->trkRot ); + QuaternionProduct( pOTR->trkRot, absRot, &pOTR->trkRot ); + break; + + case OTR_TRACKING_AVG_ORIENT: + /* Compute average (low-pass filtered) absolute orientation */ + QuaternionSlerp( pOTR->absAvgRot, absRot, alpha, &pOTR->absAvgRot ); + + /* Compute relative orientation = (absolute orientation) - (average absolute orientation) */ + QuaternionInverse( pOTR->absAvgRot, &pOTR->trkRot ); + QuaternionProduct( pOTR->trkRot, absRot, &pOTR->trkRot ); + + /* Adapt LPF constant based on orientation excursion relative to current mean: + - low cutoff (slow adaptation) for small excursions (around center) + - high cutoff (fast adaptation) for large excursions (off-center) + */ + ang = QuaternionAngle( absRot, pOTR->trkRot ); + normalizedOrientation = ang * ang; + + relativeOrientationRate = sqrtf( normalizedOrientation ) / pOTR->adaptationAngle; + /* 'if' assumed to perform comparison to 0 */ + if ( relativeOrientationRate > 1.0f ) + { + relativeOrientationRate = 1.0f; + } + + /* Compute range of the adaptation rate between center = lower rate and off-center = higher rate */ + rateRange = pOTR->offCenterAdaptationRate - pOTR->centerAdaptationRate; + /* 'if' assumed to perform comparison to 0 */ + if ( rateRange < 0.0f ) + { + rateRange = 0.0f; + } + + /* Compute adaptivity cutoff frequency: interpolate between minimum (center) and maximum (off-center) values */ + cutoffFrequency = pOTR->centerAdaptationRate + ( relativeOrientationRate * rateRange ); + + /* Compute filter coefficient corresponding to desired cutoff frequency */ + pOTR->alpha = sinf( 2.0f * EVS_PI * cutoffFrequency / updateRate ); + break; + default: + result = IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Non-supported orientation tracking adaptation type" ); + break; + } + + if ( result == IVAS_ERR_OK ) + { + *pTrkRot = pOTR->trkRot; + } + + return result; +} diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c new file mode 100644 index 0000000000000000000000000000000000000000..193e775f22f2c44dddf64e6e4ca73520c76f3220 --- /dev/null +++ b/lib_rend/ivas_output_init.c @@ -0,0 +1,245 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "ivas_cnst.h" +#include "prot.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_com.h" +#ifdef DEBUGGING +#include "debug.h" +#include +#endif +#include "wmc_auto.h" + +/*-------------------------------------------------------------------------* + * audioCfg2channels() + * + * Map Audio configuration to number of channels + *-------------------------------------------------------------------------*/ + +/*! r: number of audio channels */ +int16_t audioCfg2channels( + AUDIO_CONFIG output_config /* i : output audio configuration */ +) +{ + int16_t nchan_out; + + switch ( output_config ) + { + case AUDIO_CONFIG_MONO: + nchan_out = 1; + break; + case AUDIO_CONFIG_STEREO: + nchan_out = 2; + break; + case AUDIO_CONFIG_5_1: + nchan_out = 6; + break; + case AUDIO_CONFIG_7_1: + nchan_out = 8; + break; + case AUDIO_CONFIG_5_1_2: + nchan_out = 8; + break; + case AUDIO_CONFIG_5_1_4: + nchan_out = 10; + break; + case AUDIO_CONFIG_7_1_4: + nchan_out = 12; + break; + case AUDIO_CONFIG_FOA: + nchan_out = 4; + break; + case AUDIO_CONFIG_HOA2: + nchan_out = 9; + break; + case AUDIO_CONFIG_HOA3: + nchan_out = 16; + break; + case AUDIO_CONFIG_OBA: + nchan_out = 8; + break; + case AUDIO_CONFIG_BINAURAL: + case AUDIO_CONFIG_BINAURAL_ROOM: + nchan_out = 2; + break; + case AUDIO_CONFIG_ISM1: + nchan_out = 1; + break; + case AUDIO_CONFIG_ISM2: + nchan_out = 2; + break; + case AUDIO_CONFIG_ISM3: + nchan_out = 3; + break; + case AUDIO_CONFIG_ISM4: + nchan_out = 4; + break; + default: + IVAS_ERROR( IVAS_ERR_INTERNAL, "Error: illegal output configuration\n" ); + nchan_out = -1; + break; + } + + return ( nchan_out ); +} + + +/*-------------------------------------------------------------------------* + * ivas_output_init() + * + * Initialize and configure IVAS output parameters + *-------------------------------------------------------------------------*/ + +void ivas_output_init( + IVAS_OUTPUT_SETUP *hOutSetup, /* o : IVAS output setup structure */ + const AUDIO_CONFIG output_config /* i : output audio configuration */ +) +{ + int16_t nchan_out; + + /* set general default values */ + hOutSetup->output_config = output_config; + hOutSetup->is_loudspeaker_setup = 0; + hOutSetup->is_binaural_setup = 0; + hOutSetup->ambisonics_order = -1; + hOutSetup->separateChannelEnabled = 0; + hOutSetup->separateChannelIndex = 0; + + if ( output_config == AUDIO_CONFIG_LS_CUSTOM ) + { + hOutSetup->is_loudspeaker_setup = 1; + /* set in ivas_init_decoder: */ + /* hOutSetup->ls_azimuth */ + /* hOutSetup->ls_elevation */ + /* hOutSetup->num_lfe */ + /* hOutSetup->index_lfe[0] */ + /* hOutSetup->is_planar_setup */ + } + else + { + /* Set default values for all other than custom LS setup */ + hOutSetup->ls_azimuth = NULL; + hOutSetup->ls_elevation = NULL; + hOutSetup->num_lfe = 0; + hOutSetup->index_lfe[0] = -1; + hOutSetup->is_planar_setup = 0; + + /* set output setup specific values */ + switch ( output_config ) + { + case AUDIO_CONFIG_MONO: + hOutSetup->is_loudspeaker_setup = 1; + break; + case AUDIO_CONFIG_STEREO: + hOutSetup->is_loudspeaker_setup = 1; + hOutSetup->ls_azimuth = ls_azimuth_CICP2; + hOutSetup->ls_elevation = ls_elevation_CICP2; + break; + case AUDIO_CONFIG_FOA: + hOutSetup->ambisonics_order = SBA_FOA_ORDER; + break; + case AUDIO_CONFIG_HOA2: + hOutSetup->ambisonics_order = SBA_HOA2_ORDER; + break; + case AUDIO_CONFIG_HOA3: + hOutSetup->ambisonics_order = SBA_HOA3_ORDER; + break; + case AUDIO_CONFIG_5_1: + hOutSetup->num_lfe = 1; + hOutSetup->index_lfe[0] = 3; + hOutSetup->is_loudspeaker_setup = 1; + hOutSetup->ls_azimuth = ls_azimuth_CICP6; + hOutSetup->ls_elevation = ls_elevation_CICP6; + hOutSetup->is_planar_setup = 1; + break; + case AUDIO_CONFIG_7_1: + hOutSetup->num_lfe = 1; + hOutSetup->index_lfe[0] = 3; + hOutSetup->is_loudspeaker_setup = 1; + hOutSetup->ls_azimuth = ls_azimuth_CICP12; + hOutSetup->ls_elevation = ls_elevation_CICP12; + hOutSetup->is_planar_setup = 1; + break; + case AUDIO_CONFIG_5_1_2: + hOutSetup->num_lfe = 1; + hOutSetup->index_lfe[0] = 3; + hOutSetup->is_loudspeaker_setup = 1; + hOutSetup->ls_azimuth = ls_azimuth_CICP14; + hOutSetup->ls_elevation = ls_elevation_CICP14; + hOutSetup->is_planar_setup = 0; + break; + case AUDIO_CONFIG_5_1_4: + hOutSetup->num_lfe = 1; + hOutSetup->index_lfe[0] = 3; + hOutSetup->is_loudspeaker_setup = 1; + hOutSetup->ls_azimuth = ls_azimuth_CICP16; + hOutSetup->ls_elevation = ls_elevation_CICP16; + hOutSetup->is_planar_setup = 0; + break; + case AUDIO_CONFIG_7_1_4: + hOutSetup->num_lfe = 1; + hOutSetup->index_lfe[0] = 3; + hOutSetup->is_loudspeaker_setup = 1; + hOutSetup->ls_azimuth = ls_azimuth_CICP19; + hOutSetup->ls_elevation = ls_elevation_CICP19; + hOutSetup->is_planar_setup = 0; + break; + case AUDIO_CONFIG_BINAURAL: + case AUDIO_CONFIG_BINAURAL_ROOM: + case AUDIO_CONFIG_ISM1: + case AUDIO_CONFIG_ISM2: + case AUDIO_CONFIG_ISM3: + case AUDIO_CONFIG_ISM4: + hOutSetup->is_binaural_setup = 1; + case AUDIO_CONFIG_EXTERNAL: + /* Default values are used */ + break; + default: +#ifdef DEBUGGING + /* error */ + assert( !"Error: Unknown output setup!\n" ); +#endif + return; + } + } + + if ( output_config != AUDIO_CONFIG_EXTERNAL && output_config != AUDIO_CONFIG_LS_CUSTOM ) + { + nchan_out = audioCfg2channels( output_config ); + hOutSetup->nchan_out_woLFE = nchan_out - hOutSetup->num_lfe; + } + + return; +} diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h new file mode 100644 index 0000000000000000000000000000000000000000..938e8de02c909c85236052bb6055cbd1f97b8143 --- /dev/null +++ b/lib_rend/ivas_prot_rend.h @@ -0,0 +1,884 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#ifndef IVAS_PROT_REND_H +#define IVAS_PROT_REND_H + +#include +#include "options.h" +#include "ivas_error.h" +#include "lib_rend.h" +#include "ivas_stat_dec.h" // Note: needed until #156 is resolved + +/* clang-format off */ + +/*----------------------------------------------------------------------------------* + * General renderer declarations + *----------------------------------------------------------------------------------*/ + +IVAS_REND_AudioConfigType getAudioConfigType( + const IVAS_REND_AudioConfig config +); + +ivas_error getAudioConfigNumChannels( + const IVAS_REND_AudioConfig config, + int16_t *numChannels +); + +AUDIO_CONFIG getIvasAudioConfigFromRendAudioConfig( + IVAS_REND_AudioConfig rendConfig ); + +IVAS_REND_AudioConfig getRendAudioConfigFromIvasAudioConfig( + AUDIO_CONFIG config ); + + +/*----------------------------------------------------------------------------------* + * output setup prototypes + *----------------------------------------------------------------------------------*/ + +/*! r: number of output channels */ +int16_t audioCfg2channels( + const AUDIO_CONFIG output_config /* i : output audio configuration */ +); + +void ivas_output_init( + IVAS_OUTPUT_SETUP *hOutSetup, /* o : output setup structure */ + const AUDIO_CONFIG output_config /* i : output audio configuration */ +); + +/*----------------------------------------------------------------------------------* + * Limiter prototypes + *----------------------------------------------------------------------------------*/ + +/*! r: limiter struct handle */ +IVAS_LIMITER_HANDLE ivas_limiter_open( + const int16_t num_channels, /* i : number of I/O channels */ + const int32_t sampling_rate /* i : sampling rate for processing */ +); + +void ivas_limiter_close( + IVAS_LIMITER_HANDLE* phLimiter /* i/o: pointer to limiter handle, can be NULL */ +); + +void ivas_limiter_dec +( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + float output[MAX_OUTPUT_CHANNELS][L_FRAME48k], /* i/o: input/output buffer */ + const int16_t num_channels, /* i : number of channels to be processed */ + const int16_t output_frame, /* i : number of samples per channel in the buffer */ + const int16_t BER_detect /* i : BER detect flag */ +); + +void limiter_process( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + const int16_t output_frame, /* i : number of samples to be processed per channel in the I/O buffer */ + const float threshold, /* i : signal amplitude above which limiting starts to be applied */ + const int16_t BER_detect, /* i : BER detect flag */ + int16_t *strong_saturation_cnt /* i/o: counter of strong saturations (can be NULL) */ +); + + +/*----------------------------------------------------------------------------------* + * Amplitude Panning EFAP prototypes + *----------------------------------------------------------------------------------*/ + +ivas_error efap_init_data( + EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ + const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ + const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ + const int16_t num_speaker_nodes, /* i : number of speaker nodes in the set */ + const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ +); + +void efap_free_data( + EFAP_HANDLE *hEFAPdata /* i/o: EFAP handle to be freed */ +); + +void efap_determine_gains( + EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + float *gains, /* o : gain vector for speaker nodes for given direction */ + const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ + const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */ + const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ +); + + +/*----------------------------------------------------------------------------------* + * SBA rendering + *----------------------------------------------------------------------------------*/ + +void ivas_sba_prototype_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ + float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ + float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, imag */ + const int16_t firstSubframe, /* i : First subframe to map */ + const int16_t nSubframes /* i : Number of subframes to map */ +); + +ivas_error ivas_sba_get_hoa_dec_matrix( + const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ + float **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ + const int16_t ambisonics_order /* i : Ambisonics order */ +); + +void ivas_dirac_dec_binaural( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ + const int16_t nchan_transport /* i : number of transport channels */ +); + +ivas_error ivas_dirac_dec_init_binaural_data( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ +); + +void ivas_dirac_dec_close_binaural_data( + DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle */ +); + +ivas_error ivas_dirac_dec_binaural_copy_hrtfs( + HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ +); + + +/*----------------------------------------------------------------------------------* + * HRTF + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_binary_open( + TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ +); + +void ivas_HRTF_binary_close( + TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ +); + +ivas_error ivas_HRTF_fastconv_binary_open( + HRTFS_FASTCONV **hHrtfFastConv /* i/o: FASTCONV HRTF structure */ +); + +void ivas_HRTF_fastconv_binary_close( + HRTFS_FASTCONV **hHrtfFastConv /* i/o: FASTCONV HRTF structure */ +); + +ivas_error ivas_HRTF_parambin_binary_open( + HRTFS_PARAMBIN **hHrtfParambin /* i/o: Parametric binauralizer HRTF structure */ +); + +void ivas_HRTF_parambin_binary_close( + HRTFS_PARAMBIN **hHrtfParambin /* i/o: Parametric binauralizer HRTF structure */ +); + +ivas_error ivas_HRTF_CRend_binary_open( + HRTFS_CREND **hSetOfHRTF /* i/o: Set of HRTF handle */ +); + +void ivas_HRTF_CRend_binary_close( + HRTFS_CREND **hSetOfHRTF /* i/o: Set of HRTF handle */ +); + + +/*----------------------------------------------------------------------------------* + * TD object renderer + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_renderer_unwrap( + const REVERB_HANDLE hReverb, /* i : Reverberator handle */ + const AUDIO_CONFIG transport_config, /* i : Transport configuration */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD binaural object renderer handle */ + const int16_t num_src, /* i : number of sources to render */ + const int16_t lfe_idx, /* i : LFE channel index */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */ + const int16_t Opt_Headrotation, /* i : Head rotation flag */ + const IVAS_QUATERNION *Quaternions, /* i : Head tracking data per subframe */ + const IVAS_POSITION *Pos, /* i : Listener position data per subframe */ + float output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ + const int16_t output_frame /* i : output frame length */ +); + +ivas_error ivas_td_binaural_renderer_ext( + const TDREND_WRAPPER *pTDRend, /* i : TD Renderer wrapper structure */ + const IVAS_REND_AudioConfig inConfig, /* i : Input audio configuration */ + const LSSETUP_CUSTOM_STRUCT *customLsInput, /* i : Input custom loudspeaker layout */ + const IVAS_REND_HeadRotData *headRotData, /* i : Input head positions */ + const IVAS_REND_AudioObjectPosition *currentPos, /* i : Object position */ + const REVERB_HANDLE hReverb, /* i : Reverberator handle */ + const int16_t output_frame, /* i : output frame length */ + float output[][L_FRAME48k] /* i/o: SCE channels / Binaural synthesis */ +); + +ivas_error ivas_td_binaural_open_unwrap( + TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HR filter model (from file or NULL) */ + const int32_t output_Fs, /* i : Output sampling rate */ + const int16_t nchan_transport, /* i : Number of channels */ + const IVAS_FORMAT ivas_format, /* i : IVAS format (ISM/MC) */ + const AUDIO_CONFIG transport_config, /* i : Transport configuration */ + const float *directivity, /* i : Directivity pattern (used for ISM) */ + const IVAS_OUTPUT_SETUP hTransSetup, /* i : Loudspeaker layout */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd, /* o : TD renderer handle */ + int32_t *binaural_latency_ns /* i : Binauralization delay */ +); + +ivas_error ivas_td_binaural_open_ext( + TDREND_WRAPPER *pTDRend, + const IVAS_REND_AudioConfig inConfig, + RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */ + LSSETUP_CUSTOM_STRUCT *customLsInput, + const int32_t output_Fs +); + +void ivas_td_binaural_close( + BINAURAL_TD_OBJECT_RENDERER_HANDLE *hBinRendererTd /* i/o: TD binaural object renderer handle */ +); + + +ivas_error TDREND_GetMix( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + float output[][L_FRAME48k], /* i/o: ISM object synth / rendered output in 0,1 */ + const int16_t subframe_length, /* i/o: subframe length */ + const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */ +); + +void TDREND_Update_listener_orientation( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD Renderer handle */ + const int16_t headRotEnabled, /* i : Headrotation flag */ + const IVAS_QUATERNION *headPosition, /* i : Listener orientation */ + const IVAS_POSITION *Pos /* i : Listener Position */ +); + +void TDREND_Update_object_positions( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o : TD Renderer handle */ + const int16_t num_src, /* i : number of sources to render */ + const int16_t lfe_idx, /* i : Input LFE index */ + const IVAS_FORMAT in_format, /* i : Format of input sources */ + const ISM_METADATA_HANDLE *hIsmMetaData, /* i : Input metadata for ISM objects */ + float output[][L_FRAME48k] /* i/o: SCE/MC channels */ +); + +void BSplineModelEvalDealloc( + ModelParams_t *model, /* i : Model parameters */ + ModelEval_t *modelEval /* i : Model evaluation structure */ +); + +/* ----- Object renderer - hrfilt ----- */ + +void GetFilterFromAngle( + TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ + const float Elev, /* i : Elevation, degrees */ + float Azim, /* i : Azimuth, degrees */ + float *LeftFilter, /* o : Left HR filter */ + float *RightFilter, /* o : Right HR filter */ + int16_t *itd /* o : ITD value */ +); + +void HRTF_model_precalc( + ModelParams_t *model /* i/o: HRTF Model parameters */ +); + +ivas_error TDREND_REND_RenderSourceHRFilt( + TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ + const float *hrf_left_delta, /* i: Left filter interpolation delta */ + const float *hrf_right_delta, /* i: Right filter interpolation delta */ + const int16_t intp_count, /* i: Interpolation count */ + float output_buf[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ + const int16_t subframe_length /* i : Subframe length in use */ +); + +/* ----- Object renderer - sources ----- */ + +ivas_error TDREND_MIX_SRC_SetPos( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const int16_t SrcInd, /* i : Source index */ + const float *Vec_p /* i : Position vector */ +); + +ivas_error TDREND_MIX_SRC_SetDir( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const int16_t SrcInd, /* i : Source index */ + const float *Vec_p /* i : Direction vector */ +); + +ivas_error TDREND_MIX_SRC_SetDirAtten( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const int16_t SrcInd, /* i : Source index */ + const TDREND_DirAtten_t *DirAtten_p /* i : Directional attenuation specifier */ +); + +ivas_error TDREND_MIX_SRC_SetPlayState( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const int16_t SrcInd, /* i : Source index */ + const TDREND_PlayStatus_t PlayStatus /* i : Play state */ +); + +void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ + TDREND_SRC_SPATIAL_t *SrcSpatial_p, /* i : Spatial aspects of source */ + float *hrf_left_prev, /* o: Left filter */ + float *hrf_right_prev, /* o: Right filter */ + float *hrf_left_delta, /* o: Left filter interpolation delta */ + float *hrf_right_delta, /* o: Right filter interpolation delta */ + int16_t *intp_count, /* o: Interpolation count */ + int16_t *filterlength, /* o: Length of filters */ + int16_t *itd, /* o: ITD value */ + float *Gain, /* o: Gain value */ + TDREND_SRC_t *Src_p, + const int16_t subframe_idx /* i : Subframe index to 5 ms subframe */ +); + +ivas_error TDREND_SRC_Alloc( + TDREND_SRC_t **Src_pp /* i/o: Source */ +); + +void TDREND_SRC_Dealloc( + TDREND_SRC_t *Src_p /* i/o: Source to deallocate */ +); + +void TDREND_SRC_Init( + TDREND_SRC_t *Src_p, /* i/o: Source to initialize */ + const TDREND_PosType_t PosType /* i : Position type specifier */ +); + +/* ----- Object renderer - vec ----- */ + +void TDREND_SPATIAL_VecInit( + float *Pos_p, /* o : Output vector */ + const float PosX, /* i : X value */ + const float PosY, /* i : Y value */ + const float PosZ /* i : Z value */ +); + +/*! r: Euclidian norm value */ +float TDREND_SPATIAL_VecNorm( + const float *Vec_p /* i : Vector for norm calculation */ +); + +void TDREND_SPATIAL_VecNormalize( + const float *Vec_p, /* i : Input vector */ + float *VecNorm_p /* o : Output vector */ +); + +void TDREND_SPATIAL_VecMapToNewCoordSystem( + const float *Vec_p, /* i : Input vector */ + const float *TranslVec_p, /* i : Translation vector */ + const float *DirVec_p, /* i : Direction vector */ + const float *UpVec_p, /* i : Up vector */ + const float *RightVec_p, /* i : Right vector */ + float *MappedVec_p, /* o : Transformed vector */ + float *LisRelPosAbs /* o : Transformed vector ignoring orientation */ +); + +/*! r: Flag if the orientation has been updated */ +int16_t TDREND_SPATIAL_EvalOrthonormOrient( + float *FrontVecON_p, /* o : Normalized front vector */ + float *UpVecON_p, /* o : Normalized up vector */ + float *RightVecON_p, /* o : Normalized right vector */ + const float *FrontVec_p, /* i : Input front vector */ + const float *UpVec_p /* i : Input up vector */ +); + +/* ----- Object renderer - mix ----- */ + +ivas_error TDREND_MIX_AddSrc( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + int16_t *SrcInd, /* o : Source index */ + const TDREND_PosType_t PosType /* i : Position type (absolute/relative) */ +); + +ivas_error TDREND_MIX_SetDistAttenModel( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const TDREND_DistAttenModel_t DistAttenModel /* i : Distance attenuation model */ +); + +void TDREND_MIX_LIST_SetPos( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const float *Pos_p /* i : Listener's position */ +); + +ivas_error TDREND_MIX_LIST_SetOrient( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const float *FrontVec_p, /* i : Listener's orientation front vector */ + const float *UpVec_p /* i : Listener's orientation up vector */ +); + +void TDREND_MIX_Dealloc( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd /* i/o: TD renderer handle */ +); + +ivas_error TDREND_MIX_Init( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + TDREND_HRFILT_FiltSet_t **hHrtfTD, /* i/o: HRTF data (initialized in case of NULL) */ + const TDREND_MixSpatSpec_t *MixSpatSpec_p, /* i : Mixer spatial specification */ + const int32_t output_Fs /* i : Output sampling rate */ +); + + /* ----- Object renderer - sfx ----- */ + +void TDREND_Apply_ITD( + float *input, /* i: Input SCE subframe to be time adjusted */ + float *out_left, /* o: Output left channels with ITD applied */ + float *out_right, /* o: Output right channels with ITD applied */ + int16_t *previtd, /*i/o: Previous ITD value */ + const int16_t itd, /* i: Current subframe ITD value */ + float *mem_itd, /*i/o: ITD buffer memory */ + const int16_t length /* i: Subframe length */ +); + +void TDREND_firfilt( + float *signal, /* i/o: Input signal / Filtered signal */ + float *filter, /* i/o: FIR filter */ + const float *filter_delta, /* i : FIR filter delta */ + const int16_t intp_count, /* i : interpolation count */ + float *mem, /* i/o: filter memory */ + const int16_t subframe_length, /* i : Length of signal */ + const int16_t filterlength, /* i : Filter length */ + const float Gain /* i : Gain */ +); + + +/*----------------------------------------------------------------------------------* + * Crend renderer + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_rend_openCrend( + CREND_WRAPPER_HANDLE *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + RENDER_CONFIG_DATA *hRendCfg, + HRTFS_CREND_HANDLE hSetOfHRTF, + const int32_t output_Fs +); + +void ivas_rend_closeCrend( + CREND_WRAPPER_HANDLE *pCrend ); + +ivas_error ivas_rend_initCrendWrapper( + CREND_WRAPPER_HANDLE *pCrend ); + +ivas_error ivas_rend_crendProcess( + const CREND_WRAPPER *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + DECODER_CONFIG_HANDLE hDecoderConfig, + HEAD_TRACK_DATA_HANDLE hHeadTrackData, + IVAS_OUTPUT_SETUP_HANDLE hIntSetup, + EFAP_HANDLE hEFAPdata, + float output[][L_FRAME48k], /* i/o: input/output audio channels */ + const int32_t output_Fs +); + + + + +ivas_error ivas_crend_init_from_rom( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +ivas_error ivas_crend_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +ivas_error ivas_crend_close( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +ivas_error ivas_crend_process( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float output[][L_FRAME48k] /* i/o: input/output audio channels */ +); + +/*----------------------------------------------------------------------------------* + * Reverberator + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_binaural_reverb_open( + REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ + const int16_t numBins, /* i : number of CLDFB bins */ + const int16_t numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */ + ivas_roomAcoustics_t *roomAcoustics, /* i/o: room acoustics parameters */ + const AUDIO_CONFIG output_config, /* i : output audio configuration */ + const int32_t sampling_rate, /* i : sampling rate */ + const RENDERER_TYPE renderer_type, /* i : renderer type */ + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, /* i : FastConv HRTF handle */ + const HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : Parametric binauralizer HRTF handle */ +); + +void ivas_binaural_reverb_close( + REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */ +); + +void ivas_binaural_reverb_processFrame( + REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ + const int16_t numInChannels, /* i : num input channels to be processed */ + float inReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real */ + float inImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ + float outReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ + float outImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data imag */ + const uint8_t offsetSamplesIO /* i : number of offset samples */ +); + +ivas_error ivas_reverb_open( + REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ + const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ + const HRTFS_HANDLE hHrtf, /* i : HRTF handle */ + RENDER_CONFIG_DATA *pConfig, /* i : Reverb configuration */ + const int32_t output_Fs /* i : output sampling rate */ +); + +void ivas_reverb_close( + REVERB_HANDLE *hReverb /* i/o: Reverberator handle */ +); + +ivas_error ivas_reverb_process( + const REVERB_HANDLE hReverb, /* i : Reverberator handle */ + const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ + const int16_t mix_signals, /* i : add reverb to output signal */ + float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ + float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ + const int16_t i_ts /* i : subframe index */ +); + +void ivas_rev_delay_line_init( + ivas_rev_delay_line_t *pDelay, /* o : the delay line to initialize */ + float *memory_buffer, /* i : the memory buffer to use for the delay line */ + const uint16_t delay, /* i : the delay */ + const uint16_t maxdelay /* i : maximum delay to be supported */ +); + +/* !r: sample gotten out of delay line, and amplified by set gain */ +float ivas_rev_delay_line_get_sample( + ivas_rev_delay_line_t *pDelay /* i/o: the delay line */ +); + +void ivas_rev_delay_line_feed_sample( + ivas_rev_delay_line_t *pDelay, /* i : the delay line */ + float input /* i : the sample to feed */ +); + +void ivas_rev_delay_line_get_sample_blk( + ivas_rev_delay_line_t *pDelay, /* i : the delay line */ + const uint16_t blk_size, /* i : number of samples in the data block */ + float *output /* i/o: amples gotten out of delay line, and amplified by set gainin */ +); + +void ivas_rev_delay_line_feed_sample_blk( + ivas_rev_delay_line_t *pDelay, /* i/o: the delay line */ + const uint16_t blk_size, /* i : number of samples in the input data block */ + float *input /* i : the samples to feed */ +); + +void ivas_reverb_iir_filt_init( + ivas_rev_iir_filter_t *iirFilter, /* o : IIR filter */ + const uint16_t maxTaps /* i : maximum number of filter taps */ +); + +void ivas_reverb_iir_filt_set( + ivas_rev_iir_filter_t *iirFilter, /* i/o: IIR filter */ + uint16_t nr_taps, /* i : number of IIR filter taps */ + const float *coefA, /* i : A filter coefficients to set */ + const float *coefB /* i : the B filter coefficients to set */ +); + +void ivas_reverb_iir_filt_2taps_feed_blk( + ivas_rev_iir_filter_t *iirFilter, /* i/o: IIR filter */ + const uint16_t blk_size, /* i : size */ + const float *input, /* i : input buffer */ + float *output /* i : output buffer */ +); + +uint16_t int_log2( + uint32_t powerOf2 +); + +int16_t ivas_reverb_t2f_f2t_init( + ivas_reverb_t2f_f2t_t *t2f_f2t, + const int16_t fft_size, + const int16_t block_size +); + +void ivas_reverb_t2f_f2t_ClearHistory( + ivas_reverb_t2f_f2t_t *t2f_f2t +); + +void ivas_reverb_t2f_f2t_in( + ivas_reverb_t2f_f2t_t *t2f_f2t, + float *input_L, + float *input_R, float *buffer_L, + float *buffer_R +); + +void ivas_reverb_t2f_f2t_out( + ivas_reverb_t2f_f2t_t *t2f_f2t, + float *buffer_L, + float *buffer_R, + float *output_L, + float *output_R +); + +int16_t ivas_reverb_fft_filter_init( + ivas_reverb_fft_filter_t *fft_filter, + const int16_t fft_size +); + +void ivas_reverb_fft_filter_ComplexMul( + ivas_reverb_fft_filter_t *fft_filter, + float *buffer +); + +void ivas_reverb_fft_filter_CrossMix( + float *buffer0, + float *buffer1, + const int16_t fft_size +); + +void ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( + rv_fftwf_type_complex *spectrum, + float *fft_real, + const int16_t fft_size +); + +void ivas_reverb_define_window_fft( + float *pWindow, + const int16_t transitionStart, + const int16_t transitionLength, + const int16_t spectrumLength +); + +int16_t ivas_reverb_calc_color_filters( + const float *pTargetL, + const float *pTargetR, + const float *pWindow, + const int16_t fft_size, + const float delay, + rv_fftwf_type_complex *pBeqL, + rv_fftwf_type_complex *pBeqR +); + +int16_t ivas_reverb_calc_correl_filters( + const float *pTargetICC, + const float *pWindow, + const int16_t fft_size, + const float delay, + rv_fftwf_type_complex *pU, + rv_fftwf_type_complex *pV +); + +void ivas_reverb_calc_color_levels( + const int32_t output_Fs, + const int16_t freq_count, + const int16_t loop_count, + const float *pFc, + const float *pAcoustic_dsr, + const float *pHrtf_avg_pwr_L, + const float *pHrtf_avg_pwr_R, + const int16_t *pLoop_delays, + const float *pT60_filter_coeff, + float *pTarget_color_L, + float *pTarget_color_R +); + +void ivas_reverb_prepare_cldfb_params( + ivas_roomAcoustics_t *pInput_params, + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, + const AUDIO_CONFIG input_audio_config, + const int16_t use_brir, + const int32_t output_Fs, + float *pOutput_t60, + float *pOutput_ene ); + +void ivas_reverb_interpolate_acoustic_data( + const int16_t input_table_size, + const float *pInput_fc, + const float *pInput_t60, + const float *pInput_dsrR, + const int16_t output_table_size, + const float *pOutput_fc, + float *pOutput_t60, + float *pOutput_dsr +); + +void ivas_reverb_get_hrtf_set_properties( + float **ppHrtf_set_L_re, + float **ppHrtf_set_L_im, + float **ppHrtf_set_R_re, + float **ppHrtf_set_R_im, + const AUDIO_CONFIG input_audio_config, + const int16_t hrtf_count, + const int16_t in_freq_count, + const int16_t out_freq_count, + float *pOut_avg_pwr_L, + float *pOut_avg_pwr_R, + float *pOut_i_a_coherence +); + + +/*---------------------------------------------------------------------------------* + * Rotation Prototypes + *-----------------------------------------------------------------------------------*/ + +ivas_error ivas_headTrack_open( + HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* o : head track handle */ +); + +void ivas_headTrack_close( + HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* i/o: head track handle */ +); + +void Euler2Quat( + const float yaw, /* i : yaw (x) */ + const float pitch, /* i : pitch (y) */ + const float roll, /* i : roll (z) */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ +); + +float deg2rad( float degrees ); + + + +void QuatToRotMat( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ +); + +void rotateAziEle( + float azi_in, /* i : output elevation */ + float ele_in, /* i : input elevation */ + int16_t *azi, /* o : rotated azimuth */ + int16_t *ele, /* o : rotated elevation */ + float Rmat[3][3], /* i : real-space rotation matrix */ + const int16_t isPlanar /* i : is roation planar and elevation meaningless? */ +); + +void SHrotmatgen( + float SHrotmat[SBA_NHARM_HOA3][SBA_NHARM_HOA3], /* o : SHD rotation matrix */ + float Rmat[3][3], /* i : real-space rotation matrix */ + const int16_t order /* i : ambisonics order */ +); + +void rotateFrame_shd( + HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ + float output[][L_FRAME48k], /* i/o: unrotated HOA3 signal buffer in TD */ + const int16_t subframe_len, /* i : subframe length per channel */ + const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ + const int16_t subframe_idx /* i : subframe index */ +); + +void rotateFrame_sd( + HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ + float output[][L_FRAME48k], /* i/o: unrotated SD signal buffer in TD */ + const int16_t subframe_len, /* i : subframe length per channel */ + const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ + const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + const int16_t subframe_idx /* i : subframe index */ +); + +void rotateFrame_shd_cldfb( + float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */ + float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ + float Rmat[3][3], /* i : real-space rotation matrix */ + const int16_t nInChannels, /* i : number of channels */ + const int16_t shd_rot_max_order /* i : split-order rotation method */ +); + +void rotateFrame_sd_cldfb( + HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ + float Cldfb_RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain real part */ + float Cldfb_ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o: unrotated HOA3 signal buffer in cldfb domain imag part */ + const IVAS_OUTPUT_SETUP_HANDLE hOutputSetup, /* i : output format setup number of channels */ + const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + const int16_t nb_band /* i : number of CLDFB bands to process */ +); + + +/*----------------------------------------------------------------------------------* + * Renderer configuration + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_render_config_open( + RENDER_CONFIG_HANDLE *hRenderConfig /* i/o: Renderer config handle */ +); + +void ivas_render_config_close( + RENDER_CONFIG_HANDLE *hRenderConfig /* i/o: Renderer config handle */ +); + +ivas_error ivas_render_config_init_from_rom( + RENDER_CONFIG_HANDLE *hRenderConfig, /* i/o: Renderer config handle */ + const int16_t room_flag_on /* i : room effect on/off flag */ +); + + +/*----------------------------------------------------------------------------------* + * Orientation tracking + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_orient_trk_Init( + ivas_orient_trk_state_t *pOTR /* i/o: orientation tracker handle */ +); + +ivas_error ivas_orient_trk_SetTrackingType( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + const OTR_TRACKING_T trackingType /* i : orientation tracking type */ +); + +ivas_error ivas_orient_trk_SetReferenceRotation( + ivas_orient_trk_state_t *pOTR, /* i/o: orientatoin trakcer handle */ + const IVAS_QUATERNION refRot /* i : reference rotation */ +); + +ivas_error ivas_orient_trk_SetReferenceVector( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + const IVAS_VECTOR3 listenerPos, /* i : Listener position */ + const IVAS_VECTOR3 refPos /* i : Reference position */ +); + +ivas_error ivas_orient_trk_GetMainOrientation( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + IVAS_QUATERNION *pOrientation /* i/o: average/reference orientation */ +); + +ivas_error ivas_orient_trk_GetTrackedRotation( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + IVAS_QUATERNION *pRotation /* i/o: processed rotation */ +); + +ivas_error ivas_orient_trk_Process( + ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ + IVAS_QUATERNION absRot, /* i : absolute head rotation */ + float updateRate, /* i : rotation update rate [Hz] */ + IVAS_QUATERNION *pTrkRot /* o : tracked rotation */ +); + +/* clang-format on */ + +#endif /* IVAS_PROT_REND_H */ diff --git a/lib_dec/ivas_render_config.c b/lib_rend/ivas_render_config.c similarity index 86% rename from lib_dec/ivas_render_config.c rename to lib_rend/ivas_render_config.c index d03ce0fa75c0af967be2e73477b83303032a20ba..efd866ccec4139bb01801f6141e6b4451776bc51 100644 --- a/lib_dec/ivas_render_config.c +++ b/lib_rend/ivas_render_config.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,13 +33,21 @@ #include #include "options.h" #include "prot.h" -#include "ivas_prot.h" -#include "ivas_rom_dec.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_rend.h" #include "ivas_rom_TdBinauralRenderer.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" + + +/*-----------------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------------*/ + +#define IVAS_REVERB_DEFAULT_PRE_DELAY 0.016f +#define IVAS_REVERB_DEFAULT_INPUT_DELAY 0.1f /*-----------------------------------------------------------------------* @@ -53,8 +61,7 @@ ivas_error ivas_render_config_open( ) { /* Allocate HR filter set for headphones configuration */ - *hRenderConfig = (RENDER_CONFIG_HANDLE) count_malloc( sizeof( RENDER_CONFIG_DATA ) ); - if ( *hRenderConfig == NULL ) + if ( ( *hRenderConfig = (RENDER_CONFIG_HANDLE) malloc( sizeof( RENDER_CONFIG_DATA ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for renderer configuration!" ); } @@ -78,7 +85,7 @@ void ivas_render_config_close( return; } - count_free( *hRenderConfig ); + free( *hRenderConfig ); *hRenderConfig = NULL; return; @@ -96,6 +103,7 @@ ivas_error ivas_render_config_init_from_rom( const int16_t room_flag_on /* i : room effect on/off flag */ ) { + if ( hRenderConfig == NULL || *hRenderConfig == NULL ) { return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "Unexpected null pointer while attempting to fill renderer configuration from ROM" ); @@ -104,7 +112,7 @@ ivas_error ivas_render_config_init_from_rom( #ifdef DEBUGGING ( *hRenderConfig )->renderer_type_override = RENDER_TYPE_OVERRIDE_NONE; #endif - ( *hRenderConfig )->roomAcoustics.override = false; + ( *hRenderConfig )->roomAcoustics.override = FALSE; ( *hRenderConfig )->roomAcoustics.use_brir = room_flag_on; ( *hRenderConfig )->roomAcoustics.late_reverb_on = room_flag_on; ( *hRenderConfig )->roomAcoustics.nBands = IVAS_REVERB_DEFAULT_N_BANDS; @@ -118,5 +126,9 @@ ivas_error ivas_render_config_init_from_rom( mvr2r( ivas_reverb_default_RT60, ( *hRenderConfig )->roomAcoustics.pAcoustic_rt60, IVAS_REVERB_DEFAULT_N_BANDS ); mvr2r( ivas_reverb_default_DSR, ( *hRenderConfig )->roomAcoustics.pAcoustic_dsr, IVAS_REVERB_DEFAULT_N_BANDS ); + ( *hRenderConfig )->directivity[0] = 360.0f; /* Front cone */ + ( *hRenderConfig )->directivity[1] = 360.0f; /* Back cone */ + ( *hRenderConfig )->directivity[2] = 1.0f; /* Back attenuation */ + return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c new file mode 100644 index 0000000000000000000000000000000000000000..d31d1bd1a6b6359158ea54483cd388d4222aa5c5 --- /dev/null +++ b/lib_rend/ivas_reverb.c @@ -0,0 +1,1979 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot_rend.h" +#include "ivas_cnst.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "math.h" +#include "ivas_rom_rend.h" +#include +#include "wmc_auto.h" + + +/* The reverberator structure implemented here is described in detail in: + * Vilkamo, J., Neugebauer, B., & Plogsties, J. (2012). Sparse frequency-domain reverberator. + * Journal of the Audio Engineering Society, 59(12), 936-943. */ + +/*------------------------------------------------------------------------- + * Local constants + *------------------------------------------------------------------------*/ + +#define BIN_REND_RANDOM_SEED 1 /* random seed for generating reverb decorrelators */ + +#define CLDFB_SLOTS_PER_SECOND 800 /* Used for initializing reverb */ + + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + +#define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */ +/* should be a divisor of the frame length at any sampling rate and an even number*/ +#define FFT_FILTER_WND_FLAT_REGION ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */ +#define FFT_FILTER_WND_TRANS_REGION ( 0.15f ) /* transition (1->0) length of FFT filter window, in proportion to overlap */ +#define REF_LF_MIN ( 100.0f ) +#define REF_LF_MAX ( 250.0f ) +#define REF_HF_MIN ( 5000.0f ) +#define REF_HF_MAX ( 7950.0f ) +#define LF_BIAS ( 0.5f ) + +#define DEFAULT_SRC_DIST ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */ + +#define IVAS_REVERB_FFT_SIZE_48K ( 512 ) +#define IVAS_REVERB_FFT_SIZE_32K ( 512 ) +#define IVAS_REVERB_FFT_SIZE_16K ( 256 ) +#define IVAS_REVERB_FFT_N_SUBBLOCKS_48K ( 1 ) +#define IVAS_REVERB_FFT_N_SUBBLOCKS_32K ( 1 ) +#define IVAS_REVERB_FFT_N_SUBBLOCKS_16K ( 1 ) + +#define MAX_NR_OUTPUTS ( 2 ) + +const int16_t init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 }; +const int16_t default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 }; +const int16_t default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 }; +const int16_t default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 }; + +/*------------------------------------------------------------------------------------------* + * Local Struct definition + *------------------------------------------------------------------------------------------*/ + +typedef struct ivas_reverb_params_t +{ + int16_t pre_delay; /* Delay of the FDC reverb, first peak after pre_delay samples. Note that */ + /* there may be non-zero samples earlier due to the filters being */ + /* linear-phase. */ + int16_t nr_loops; /* Number of feedback loops (= L) */ + int16_t pLoop_delays[IVAS_REV_MAX_NR_BRANCHES]; /* Delay for each feedback loop in samples. */ + float pLoop_feedback_matrix[IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_NR_BRANCHES]; /* Feedback [L][L] matrix that mixes the signals of the loops. */ + int16_t nr_outputs; /* Nr of signals extracted from the loops (= S). */ + /* Currently this is fixed to 2. */ + float pLoop_extract_matrix[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES]; /* Mix [S][L] matrix from feedback loops to outputs. */ + /* In Matlab: [S x L] - Currently S=2, later may be more than 2 for speaker playback. */ + int16_t t60_filter_order; /* Filter order (length of vector) */ + float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH]; /* Filters [][] in feedback loops, controlling T60. */ + /* In Matlab: IIR: [(2 * L) x ( + 1)] (odd: b-vector, even: a-vector) */ + /* In Matlab: FIR: [L x ] */ + float *pFc; /* Center frequencies for FFT filter design */ + float *pRt60; /* RT60 values at these frequencies */ + float *pDsr; /* DSR values at these frequencies */ + float *pHrtf_avg_pwr_response_l; /* The HRTF set's average left ear power response */ + float *pHrtf_avg_pwr_response_r; /* The HRTF set's average right ear power response */ + float *pHrtf_inter_aural_coherence; /* The HRTF set's inter-aural coherence for diffuse sound */ + const float *pHrtf_avg_pwr_response_l_const; /* The HRTF set's average left ear power response */ + const float *pHrtf_avg_pwr_response_r_const; /* The HRTF set's average right ear power response */ + const float *pHrtf_inter_aural_coherence_const; /* The HRTF set's inter-aural coherence for diffuse sound */ + + int16_t do_corr_filter; /* Flag indicating whether correlation filters should be used. */ + /* Correlation only supported and needed for binaural playback (i.e. */ + /* when nr_outputs != 2 correlation filtering is never supported). */ +} ivas_reverb_params_t; + + +/*------------------------------------------------------------------------------------------* + * Static functions declarations + *------------------------------------------------------------------------------------------*/ + +static ivas_error calc_jot_t60_coeffs( float *pH_dB, const uint16_t nrFrequencies, float *pFrequencies, float *pCoeffA, float *pCoeffB, const float fNyquist ); + + +/*------------------------------------------------------------------------- + * binRend_rand() + * + * + *------------------------------------------------------------------------*/ + +static uint16_t binRend_rand( + REVERB_STRUCT_HANDLE hReverb /* i/o: binaural reverb handle */ +) +{ + hReverb->binRend_RandNext = hReverb->binRend_RandNext * 1103515245 + 12345; + + return (uint16_t) ( hReverb->binRend_RandNext / 65536 ) % 32768; +} + + +/*------------------------------------------------------------------------- + * ivas_binaural_reverb_setPreDelay() + * + * + *------------------------------------------------------------------------*/ + +static void ivas_binaural_reverb_setPreDelay( + REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ + const int16_t delaySamples /* i : reverb pre-delay in CLDFB slots */ +) +{ + if ( delaySamples < 1 ) + { + hReverb->preDelayBufferLength = 1; + + return; + } + + if ( delaySamples > REVERB_PREDELAY_MAX ) + { + hReverb->preDelayBufferLength = REVERB_PREDELAY_MAX; + + return; + } + + hReverb->preDelayBufferLength = delaySamples; + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_binaural_reverb_setReverbTimes() + * + * + *------------------------------------------------------------------------*/ + +static void ivas_binaural_reverb_setReverbTimes( + REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ + const int32_t output_Fs, /* i : sampling_rate */ + const float *revTimes, /* i : reverberation times T60 for each CLDFB bin in seconds */ + const float *revEnes /* i : spectrum for reverberated sound at each CLDFB bin */ +) +{ + int16_t bin, ch, tap, sample; + float binCenterFreq, diffuseFieldICC, tmpVal, attenuationFactorPerSample; + float intendedEnergy, actualizedEnergy, energyBuildup, currentEnergy, attenuationFactorPerSampleSq; + + hReverb->binRend_RandNext = (uint16_t) BIN_REND_RANDOM_SEED; + hReverb->highestBinauralCoherenceBin = 0; + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + /* Determine the diffuse field binaural coherence */ + binCenterFreq = ( (float) bin + 0.5f ) / ( (float) hReverb->numBins ) * ( (float) output_Fs ) / 2.0f; + if ( bin == 0 ) + { + diffuseFieldICC = 1.0f; + } + else if ( binCenterFreq < 2700.0f ) + { + diffuseFieldICC = sinf( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) / ( EVS_PI * binCenterFreq / 550.0f + 1e-20f ) * ( 1.0f - binCenterFreq / 2700.0f ); + hReverb->highestBinauralCoherenceBin = bin; + } + else + { + diffuseFieldICC = 0.0f; + } + + /* Mixing gains to generate a diffuse-binaural sound based on incoherent sound */ + tmpVal = ( 1.0f - sqrtf( 1.0f - powf( diffuseFieldICC, 2.0 ) ) ) / 2.0f; + if ( diffuseFieldICC > 0 ) + { + hReverb->binauralCoherenceCrossmixGains[bin] = sqrtf( fabsf( tmpVal ) ); + } + else + { + hReverb->binauralCoherenceCrossmixGains[bin] = -sqrtf( fabsf( tmpVal ) ); + } + hReverb->binauralCoherenceDirectGains[bin] = sqrtf( 1.0f - fabsf( tmpVal ) ); + + /* Determine attenuation factor that generates the appropriate energy decay according to reverberation time */ + attenuationFactorPerSample = powf( 10.0f, -3.0f * ( 1.0f / ( (float) CLDFB_SLOTS_PER_SECOND * revTimes[bin] ) ) ); + hReverb->loopAttenuationFactor[bin] = powf( attenuationFactorPerSample, hReverb->loopBufLength[bin] ); + attenuationFactorPerSampleSq = attenuationFactorPerSample * attenuationFactorPerSample; + + /* Design sparse decorrelation filters. The decorrelation filters, due to random procedures involved, + * may affect the spectrum of the output. The spectral effect is therefore monitored and compensated for. */ + intendedEnergy = 0.0f; + actualizedEnergy = 0.0f; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + energyBuildup = 0.0f; + currentEnergy = 1.0f; + tap = 0; + + for ( sample = 0; sample < hReverb->loopBufLength[bin]; sample++ ) + { + intendedEnergy += currentEnergy; + + /* The randomization at the energy build up affects where the sparse taps are located */ + energyBuildup += currentEnergy + 0.1f * ( (float) binRend_rand( hReverb ) / PCM16_TO_FLT_FAC - 0.5f ); + + if ( energyBuildup >= 1.0f ) /* A new filter tap is added at this condition */ + { + /* Four efficient phase operations: n*pi/2, n=0,1,2,3 */ + hReverb->tapPhaseShiftType[bin][ch][tap] = (int16_t) ( binRend_rand( hReverb ) % 4 ); + /* Set the tapPointer to point to the determined sample at the loop buffer */ + hReverb->tapPointersReal[bin][ch][tap] = &( hReverb->loopBufReal[bin][sample] ); + hReverb->tapPointersImag[bin][ch][tap] = &( hReverb->loopBufImag[bin][sample] ); + energyBuildup -= 1.0f; /* A tap is added, thus remove its energy from the buildup */ + tap++; + actualizedEnergy += 1.0f; + } + currentEnergy *= attenuationFactorPerSampleSq; + } + hReverb->taps[bin][ch] = tap; /* Number of taps determined at the above random procedure */ + } + + /* The decorrelator design and IIR attenuation rate affects the energy of reverb, which is compensated here */ + hReverb->reverbEqGains[bin] = sqrtf( revEnes[bin] ); /* Determined reverb spectrum */ + hReverb->reverbEqGains[bin] *= sqrtf( intendedEnergy / actualizedEnergy ); /* Correction of random effects at the decorrelator design */ + hReverb->reverbEqGains[bin] *= sqrtf( 0.5f * ( 1.0f - attenuationFactorPerSampleSq ) ); /* Correction of IIR decay rate */ + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function compute_feedback_matrix() + * + * Compute the N x N matrix for the mixing the N feedback loop outputs into the N inputs again + *-----------------------------------------------------------------------------------------*/ + +static ivas_error compute_feedback_matrix( + float *pFeedbackMatrix, + const int16_t n ) +{ + float u, v; + int16_t i, j, x; + + if ( n == 6 ) + { + /* special case (there is no 6 x 6 Hadamard matrix in set R) */ + u = -1.0f / 3; + v = 1.0f + u; + for ( i = 0; i < n; i++ ) + { + for ( j = 0; j < n; j++ ) + { + if ( i == j ) + { + pFeedbackMatrix[i * n + j] = v; + } + else + { + pFeedbackMatrix[i * n + j] = u; + } + } + } + } + else + { + if ( !( n == 4 || n == 8 || n == 16 ) ) + { + return IVAS_ERR_INTERNAL; /* n must be 4, 6, 8 or 16, else ERROR */ + } + + u = inv_sqrt( n ); + + if ( n == 4 ) + { + u = -u; + } + + pFeedbackMatrix[0] = u; + for ( x = 1; x < n; x += x ) + { + for ( i = 0; i < x; i++ ) + { + for ( j = 0; j < x; j++ ) + { + pFeedbackMatrix[( i + x ) * n + j] = pFeedbackMatrix[i * n + j]; + pFeedbackMatrix[i * n + j + x] = pFeedbackMatrix[i * n + j]; + pFeedbackMatrix[( i + x ) * n + j + x] = -pFeedbackMatrix[i * n + j]; + } + } + } + + if ( n == 4 ) + { + /* special case */ + for ( j = 12; j < 16; j++ ) + { + pFeedbackMatrix[j] = -pFeedbackMatrix[j]; + } + } + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function compute_2_out_extract_matrix() + * + * Compute the N x 2 matrix for mixing the N Jot feedback loops to 2 outputs + *-----------------------------------------------------------------------------------------*/ + +static void compute_2_out_extract_matrix( + float *pExtractMatrix, + const int16_t n ) +{ + float ff; + int16_t i; + + ff = 1.0; + for ( i = 0; i < n; i++ ) + { + pExtractMatrix[i] = 1.0; + pExtractMatrix[i + n] = ff; + ff = -ff; + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_base_config() + * + * Set all jot reverb parameters that are independent of the input reverb configuration + *-----------------------------------------------------------------------------------------*/ + +static ivas_error set_base_config( + ivas_reverb_params_t *pParams, + const int32_t output_Fs ) +{ + ivas_error error; + int16_t loop_idx; + const int16_t *selected_loop_delay = NULL; + + if ( pParams == NULL ) + { + return IVAS_ERR_INTERNAL; + } + + /* TODO: values below could be reconsidered, and/or be made variable */ + pParams->pre_delay = 0; + pParams->nr_outputs = BINAURAL_CHANNELS; + pParams->nr_loops = IVAS_REV_MAX_NR_BRANCHES; + + /* set loop delays to default */ + if ( output_Fs == 48000 ) + { + selected_loop_delay = default_loop_delay_48k; + } + else if ( output_Fs == 32000 ) + { + selected_loop_delay = default_loop_delay_32k; + } + else if ( output_Fs == 16000 ) + { + selected_loop_delay = default_loop_delay_16k; + } + + for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ ) + { + pParams->pLoop_delays[loop_idx] = selected_loop_delay[loop_idx]; + } + + /* set feedback and output matrices */ + if ( ( error = compute_feedback_matrix( pParams->pLoop_feedback_matrix, pParams->nr_loops ) ) != IVAS_ERR_OK ) + { + return error; + } + + compute_2_out_extract_matrix( pParams->pLoop_extract_matrix, pParams->nr_loops ); + + /* pre-set the various filters; they will be set later based on reverb configuration */ + pParams->t60_filter_order = 1; /* set to 1 in base config. */ + + if ( pParams->nr_outputs == 2 ) + { + pParams->do_corr_filter = 1; + } + else + { + pParams->do_corr_filter = 0; + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function calc_dmx_gain() + * + * Computes the downmix gain + *-----------------------------------------------------------------------------------------*/ + +static float calc_dmx_gain( void ) +{ + const float dist = DEFAULT_SRC_DIST; + return sqrtf( 4.0f * EVS_PI * dist * dist / 0.001f ); +} + + +/*-----------------------------------------------------------------------------------------* + * Function calc_predelay() + * + * Calculate the predelay, taking shortest jot loop delay into account + *-----------------------------------------------------------------------------------------*/ + +static void calc_predelay( + ivas_reverb_params_t *pParams, + float acoustic_predelay_sec, + const int32_t output_Fs ) +{ + int16_t predelay, fbdelay, output_frame; + + predelay = (int16_t) roundf( acoustic_predelay_sec * (float) output_Fs ); + output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + fbdelay = pParams->pLoop_delays[pParams->nr_loops - 1]; + predelay -= fbdelay; + + if ( predelay < 0 ) + { + predelay = 0; + } + + if ( output_frame < predelay ) + { + predelay = output_frame; + } + + pParams->pre_delay = predelay; + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function compute_t60_coeffs() + * + * Calculate Jot reverb's T60 filter coefficients + *-----------------------------------------------------------------------------------------*/ + +static ivas_error compute_t60_coeffs( + ivas_reverb_params_t *pParams, + const int16_t nr_fc_fft_filter, + const int32_t output_Fs ) +{ + int16_t bin_idx, loop_idx, tf_T60_len, len; + float loop_delay_sec, freq_Nyquist, inv_hfs; + float target_gains_db[RV_LENGTH_NR_FC]; + float norm_f[RV_LENGTH_NR_FC]; + float *pCoeffs_a, *pCoeffs_b; + float *targetT60, *freqT60; + ivas_error error; + + targetT60 = pParams->pRt60; + freqT60 = pParams->pFc; + + error = IVAS_ERR_OK; + tf_T60_len = nr_fc_fft_filter; + len = pParams->t60_filter_order + 1; + freq_Nyquist = 0.5f * (float) output_Fs; + + /* normalize pFrequencies: 0 .. 1/2 output_Fs --> 0.0 .. 1.0 */ + inv_hfs = 1.0f / freq_Nyquist; + for ( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ ) + { + norm_f[bin_idx] = freqT60[bin_idx] * inv_hfs; + } + + for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ ) + { + loop_delay_sec = (float) pParams->pLoop_delays[loop_idx] / (float) output_Fs; + for ( bin_idx = 0; bin_idx < tf_T60_len; bin_idx++ ) + { + target_gains_db[bin_idx] = -60.0f * loop_delay_sec / targetT60[bin_idx]; + target_gains_db[bin_idx] = max( target_gains_db[bin_idx], -120.0f ); + } + + pCoeffs_a = &pParams->pT60_filter_coeff[2 * len * loop_idx + len]; + pCoeffs_b = &pParams->pT60_filter_coeff[2 * len * loop_idx]; + if ( ( error = calc_jot_t60_coeffs( target_gains_db, tf_T60_len, norm_f, pCoeffs_a, pCoeffs_b, freq_Nyquist ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + // TODO: Compute proper (group) Delay from IIR filter + len = ( pParams->t60_filter_order + 1 ) >> 1; /* == floor( (order+1) / 2) */ + for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ ) + { + pParams->pLoop_delays[loop_idx] -= len; + } + + return error; +} + + +/*-----------------------------------------------------------------------------------------* + * Function calc_low_shelf_first_order_filter() + * + * Calculate 1st order low shelf filter + *-----------------------------------------------------------------------------------------*/ + +static void calc_low_shelf_first_order_filter( + float *pNum, + float *pDen, + const float f0, + const float lin_gain_lf, + const float lin_gain_hf ) +{ + float w0, gain; + + w0 = tanf( EVS_PI * f0 / 2.0f ); + gain = lin_gain_lf / lin_gain_hf; + + if ( gain < 1.0f ) + { + pNum[0] = 1 + w0 * gain; + pNum[1] = w0 * gain - 1; + pDen[0] = 1 + w0; + pDen[1] = w0 - 1; + } + else + { + pNum[0] = 1 + w0; + pNum[1] = w0 - 1; + pDen[0] = 1 + w0 / gain; + pDen[1] = w0 / gain - 1; + } + + /* Normalize and adjust gain to match target amplitudes */ + pNum[0] = ( pNum[0] / pDen[0] ) * lin_gain_hf; + pNum[1] = ( pNum[1] / pDen[0] ) * lin_gain_hf; + pDen[1] = pDen[1] / pDen[0]; + pDen[0] = 1.0f; + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function calc_jot_t60_coeffs() + * + * Calculate Jot reverb's T60 filters + *-----------------------------------------------------------------------------------------*/ + +static ivas_error calc_jot_t60_coeffs( + float *pH_dB, + const uint16_t nrFrequencies, + float *pFrequencies, + float *pCoeffA, + float *pCoeffB, + const float fNyquist ) +{ + const float ref_lf_min_norm = REF_LF_MIN / fNyquist; + const float ref_lf_max_norm = REF_LF_MAX / fNyquist; + const float ref_hf_min_norm = REF_HF_MIN / fNyquist; + const float ref_hf_max_norm = REF_HF_MAX / fNyquist; + int16_t f_idx, minidx; + float f0, tmp, minval, lf_target_gain_dB, hf_target_gain_dB, mid_crossing_gain_dB; + uint16_t n_points_lf, n_points_hf; + float lin_gain_lf, lin_gain_hf; + + minidx = nrFrequencies - 1; + minval = 1e+20f; + lf_target_gain_dB = 0.0f; + hf_target_gain_dB = 0.0f; + n_points_lf = 0; + n_points_hf = 0; + + for ( f_idx = 0; f_idx < nrFrequencies; f_idx++ ) + { + if ( ( pFrequencies[f_idx] >= ref_lf_min_norm ) && ( pFrequencies[f_idx] <= ref_lf_max_norm ) ) + { + lf_target_gain_dB += pH_dB[f_idx]; + n_points_lf++; + } + if ( ( pFrequencies[f_idx] >= ref_hf_min_norm ) && ( pFrequencies[f_idx] <= ref_hf_max_norm ) ) + { + hf_target_gain_dB += pH_dB[f_idx]; + n_points_hf++; + } + } + + if ( ( n_points_lf == 0 ) || ( n_points_hf == 0 ) ) + { + return IVAS_ERR_INTERNAL; + } + + lf_target_gain_dB = lf_target_gain_dB / (float) n_points_lf; + hf_target_gain_dB = hf_target_gain_dB / (float) n_points_hf; + mid_crossing_gain_dB = hf_target_gain_dB + LF_BIAS * ( lf_target_gain_dB - hf_target_gain_dB ); + + for ( f_idx = 1; f_idx < nrFrequencies - 1; f_idx++ ) + { + tmp = fabsf( pH_dB[f_idx] - mid_crossing_gain_dB ); + if ( tmp < minval ) + { + minval = tmp; + minidx = f_idx; + } + } + + f0 = pFrequencies[minidx]; + lin_gain_lf = powf( 10.0f, lf_target_gain_dB * 0.05f ); + lin_gain_hf = powf( 10.0f, hf_target_gain_dB * 0.05f ); + + /* call low-pass iir shelf */ + calc_low_shelf_first_order_filter( pCoeffB, pCoeffA, f0, lin_gain_lf, lin_gain_hf ); + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function initialize_reverb_filters() + * + * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data) + *-----------------------------------------------------------------------------------------*/ + +static ivas_error initialize_reverb_filters( + REVERB_HANDLE hReverb ) +{ + ivas_error error; + + error = IVAS_ERR_OK; + + /* init correlation and coloration filters */ + if ( ( error = ivas_reverb_t2f_f2t_init( &hReverb->fft_filter_ols, hReverb->fft_size, hReverb->fft_subblock_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_0, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_1, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_0, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_1, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + return error; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_t60_filter() + * + * Sets t60 number of taps and coefficients A and B + *-----------------------------------------------------------------------------------------*/ + +static ivas_error set_t60_filter( + REVERB_HANDLE hReverb, + const uint16_t branch, + const uint16_t nr_taps, + const float coefA[], + const float coefB[] ) +{ + if ( branch >= hReverb->nr_of_branches ) + { + return IVAS_ERR_INTERNAL; + } + + if ( nr_taps > IVAS_REV_MAX_IIR_FILTER_LENGTH ) + { + return IVAS_ERR_INTERNAL; + } + + ivas_reverb_iir_filt_set( &( hReverb->t60[branch] ), nr_taps, coefA, coefB ); + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_feedback_delay() + * + * Sets Delay of feedback branch in number of samples + *-----------------------------------------------------------------------------------------*/ + +static ivas_error set_feedback_delay( + REVERB_HANDLE hReverb, + const uint16_t branch, + const int16_t fb_delay ) +{ + if ( branch >= hReverb->nr_of_branches ) + { + return IVAS_ERR_INTERNAL; + } + + hReverb->delay_line[branch].Delay = fb_delay; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_feedback_gain() + * + * Sets nr_of_branches feedback gain values in feedback matrix + *-----------------------------------------------------------------------------------------*/ + +static ivas_error set_feedback_gain( + REVERB_HANDLE hReverb, + const uint16_t branch, + const float *pGain ) +{ + uint16_t gain_idx; + if ( branch >= hReverb->nr_of_branches ) + { + return IVAS_ERR_INTERNAL; + } + + for ( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ ) + { + hReverb->gain_matrix[branch][gain_idx] = pGain[gain_idx]; + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_correl_fft_filter() + * + * Sets correlation filter complex gains + *-----------------------------------------------------------------------------------------*/ + +static ivas_error set_correl_fft_filter( + REVERB_HANDLE hReverb, + const uint16_t channel, + rv_fftwf_type_complex *pSpectrum ) +{ + if ( channel > 1 ) + { + return IVAS_ERR_INTERNAL; + } + + if ( channel == 0 ) + { + ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_correl_0.fft_spectrum, hReverb->fft_filter_correl_0.fft_size ); + } + else + { + ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_correl_1.fft_spectrum, hReverb->fft_filter_correl_1.fft_size ); + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_color_fft_filter() + * + * Sets coloration filter complex gains + *-----------------------------------------------------------------------------------------*/ + +static ivas_error set_color_fft_filter( + REVERB_HANDLE hReverb, + const uint16_t channel, + rv_fftwf_type_complex *pSpectrum ) +{ + if ( channel > 1 ) + { + return IVAS_ERR_INTERNAL; + } + + if ( channel == 0 ) + { + ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_color_0.fft_spectrum, hReverb->fft_filter_color_0.fft_size ); + } + else + { + ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, hReverb->fft_filter_color_1.fft_spectrum, hReverb->fft_filter_color_1.fft_size ); + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_mixer_level() + * + * Sets Mixer level: to mix 2 output channels from 8 feedback branches + *-----------------------------------------------------------------------------------------*/ + +static ivas_error set_mixer_level( + REVERB_HANDLE hReverb, + const uint16_t channel, + const float level[] ) +{ + uint16_t branch_idx; + if ( channel >= BINAURAL_CHANNELS ) + { + return IVAS_ERR_INTERNAL; + } + + for ( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ ) + { + hReverb->mixer[channel][branch_idx] = level[branch_idx]; + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function clear_buffers() + * + * Clears buffers of delay lines and filters + *-----------------------------------------------------------------------------------------*/ + +static void clear_buffers( + REVERB_HANDLE hReverb ) +{ + int16_t branch_idx; + ivas_rev_iir_filter_t *iirFilter; + ivas_rev_delay_line_t *delay_line; + + for ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ ) + { + delay_line = &( hReverb->delay_line[branch_idx] ); + set_f( delay_line->pBuffer, 0, delay_line->MaxDelay ); + delay_line->BufferPos = 0; + + iirFilter = &( hReverb->t60[branch_idx] ); + set_f( iirFilter->pBuffer, 0, iirFilter->MaxTaps ); + } + + ivas_reverb_t2f_f2t_ClearHistory( &hReverb->fft_filter_ols ); + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_fft_and_datablock_sizes() + * + * Sets frame size and fft-filter related sizes + *-----------------------------------------------------------------------------------------*/ + +static void set_fft_and_datablock_sizes( + REVERB_HANDLE hReverb, + const int16_t subframe_len ) +{ + hReverb->full_block_size = subframe_len; + if ( subframe_len == L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES ) + { + hReverb->fft_size = IVAS_REVERB_FFT_SIZE_48K; + hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K; + } + else if ( subframe_len == L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES ) + { + hReverb->fft_size = IVAS_REVERB_FFT_SIZE_32K; + hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K; + } + else if ( subframe_len == L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES ) + { + hReverb->fft_size = IVAS_REVERB_FFT_SIZE_16K; + hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K; + } + else + { + assert( 0 ); /* unsupported block size */ + } + + hReverb->fft_subblock_size = subframe_len / hReverb->num_fft_subblocks; + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function set_reverb_acoustic_data() + * + * Sets reverb acoustic data (room acoustics and HRTF), interpolating it to the filter grid + *-----------------------------------------------------------------------------------------*/ + +static void set_reverb_acoustic_data( + ivas_reverb_params_t *pParams, + const AUDIO_CONFIG input_audio_config, + const HRTFS_HANDLE hHrtf, + ivas_roomAcoustics_t *pRoomAcoustics, + const int16_t subframe_len, + const int16_t nr_fc_input, + const int16_t nr_fc_fft_filter ) +{ + int16_t nr_out_ch, hrtf_idx, offset, iter_idx, bin_idx; + float ln_1e6_inverted, delay_diff, exp_argument; + float *pHrtf_set_l_re[MAX_INTERN_CHANNELS]; + float *pHrtf_set_l_im[MAX_INTERN_CHANNELS]; + float *pHrtf_set_r_re[MAX_INTERN_CHANNELS]; + float *pHrtf_set_r_im[MAX_INTERN_CHANNELS]; + + /* use crend hrtf filters */ + if ( hHrtf != NULL ) + { + /* Compute HRTF set properties: average left/right energies, IA coherence */ + /* First, find the offset of the frequency-domain data for the 1st frame and assign HRTF pointers */ + for ( nr_out_ch = 0; nr_out_ch < BINAURAL_CHANNELS; nr_out_ch++ ) + { + for ( hrtf_idx = 0; hrtf_idx < hHrtf->max_num_ir; hrtf_idx++ ) + { + offset = 0; + for ( iter_idx = 0; iter_idx < hHrtf->num_iterations[hrtf_idx][nr_out_ch] - 1; iter_idx++ ) + { + offset += hHrtf->pIndex_frequency_max[hrtf_idx][nr_out_ch][iter_idx]; + } + + if ( nr_out_ch == 0 ) + { + pHrtf_set_l_re[hrtf_idx] = &hHrtf->pOut_to_bin_re[hrtf_idx][0][offset]; + pHrtf_set_l_im[hrtf_idx] = &hHrtf->pOut_to_bin_im[hrtf_idx][0][offset]; + } + else + { + pHrtf_set_r_re[hrtf_idx] = &hHrtf->pOut_to_bin_re[hrtf_idx][1][offset]; + pHrtf_set_r_im[hrtf_idx] = &hHrtf->pOut_to_bin_im[hrtf_idx][1][offset]; + } + } + } + + /* Compute HRTF set properties using frequency-domain HRTF data */ + ivas_reverb_get_hrtf_set_properties( pHrtf_set_l_re, pHrtf_set_l_im, pHrtf_set_r_re, pHrtf_set_r_im, input_audio_config, hHrtf->max_num_ir, subframe_len, + nr_fc_fft_filter, pParams->pHrtf_avg_pwr_response_l, pParams->pHrtf_avg_pwr_response_r, pParams->pHrtf_inter_aural_coherence ); + + pParams->pHrtf_avg_pwr_response_l_const = (const float *) pParams->pHrtf_avg_pwr_response_l; + pParams->pHrtf_avg_pwr_response_r_const = (const float *) pParams->pHrtf_avg_pwr_response_r; + pParams->pHrtf_inter_aural_coherence_const = (const float *) pParams->pHrtf_inter_aural_coherence; + } + else + { + pParams->pHrtf_avg_pwr_response_l_const = orange53_left_avg_power; + pParams->pHrtf_avg_pwr_response_r_const = orange53_right_avg_power; + pParams->pHrtf_inter_aural_coherence_const = orange53_coherence; + } + + /* interpolate input table data for T60 and DSR to the FFT filter grid */ + ivas_reverb_interpolate_acoustic_data( nr_fc_input, pRoomAcoustics->pFc_input, pRoomAcoustics->pAcoustic_rt60, pRoomAcoustics->pAcoustic_dsr, + nr_fc_fft_filter, pParams->pFc, pParams->pRt60, pParams->pDsr ); + + /* adjust DSR for the delay difference */ + delay_diff = pRoomAcoustics->inputPreDelay - pRoomAcoustics->acousticPreDelay; + ln_1e6_inverted = 1.0f / logf( 1e06f ); + for ( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ ) + { + exp_argument = delay_diff / ( pParams->pRt60[bin_idx] * ln_1e6_inverted ); + /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */ + exp_argument = min( exp_argument, 23.0f ); + exp_argument = max( exp_argument, -23.0f ); + pParams->pDsr[bin_idx] *= expf( exp_argument ); + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function setup_FDN_branches() + * + * Sets up feedback delay network system + *-----------------------------------------------------------------------------------------*/ + +static ivas_error setup_FDN_branches( + REVERB_HANDLE hReverb, + ivas_reverb_params_t *pParams ) +{ + int16_t nr_coefs, branch_idx, channel_idx; + ivas_error error; + float *pCoef_a, *pCoef_b; + error = IVAS_ERR_OK; + + /* initialize feedback branches */ + for ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ ) + { + ivas_rev_delay_line_init( &( hReverb->delay_line[branch_idx] ), hReverb->loop_delay_buffer[branch_idx], init_loop_delay[branch_idx], pParams->pLoop_delays[branch_idx] ); + ivas_reverb_iir_filt_init( &( hReverb->t60[branch_idx] ), IVAS_REV_MAX_IIR_FILTER_LENGTH ); + hReverb->mixer[0][branch_idx] = 0.0f; + hReverb->mixer[1][branch_idx] = 0.0f; + } + clear_buffers( hReverb ); + nr_coefs = pParams->t60_filter_order + 1; + + if ( IVAS_REV_MAX_IIR_FILTER_LENGTH < nr_coefs ) + { + return IVAS_ERR_INTERNAL; + } + else + { + for ( branch_idx = 0; branch_idx < pParams->nr_loops; branch_idx++ ) + { + pCoef_a = &pParams->pT60_filter_coeff[2 * nr_coefs * branch_idx + nr_coefs]; + pCoef_b = &pParams->pT60_filter_coeff[2 * nr_coefs * branch_idx]; + + if ( ( error = set_t60_filter( hReverb, branch_idx, nr_coefs, pCoef_a, pCoef_b ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = set_feedback_delay( hReverb, branch_idx, pParams->pLoop_delays[branch_idx] ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = set_feedback_gain( hReverb, branch_idx, &( pParams->pLoop_feedback_matrix[branch_idx * pParams->nr_loops] ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + for ( channel_idx = 0; channel_idx < pParams->nr_outputs; channel_idx++ ) + { + if ( ( error = set_mixer_level( hReverb, channel_idx, &( pParams->pLoop_extract_matrix[channel_idx * pParams->nr_loops] ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return error; +} + + +/*------------------------------------------------------------------------- + * ivas_reverb_open() + * + * Allocate and initialize Crend reverberation handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_reverb_open( + REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ + const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ + const HRTFS_HANDLE hHrtf, /* i : HRTF handle */ + RENDER_CONFIG_HANDLE hRenderConfig, /* i : Renderer configuration handle */ + const int32_t output_Fs /* i : output sampling rate */ +) +{ + ivas_error error; + REVERB_HANDLE pState = NULL; + int16_t bin_idx, subframe_len, output_frame, predelay_bf_len, loop_idx; + ivas_reverb_params_t params; + rv_fftwf_type_complex pFft_wf_filter_ch0[RV_LENGTH_NR_FC]; + rv_fftwf_type_complex pFft_wf_filter_ch1[RV_LENGTH_NR_FC]; + float pColor_target_l[RV_LENGTH_NR_FC]; + float pColor_target_r[RV_LENGTH_NR_FC]; + float pTime_window[RV_FILTER_MAX_FFT_SIZE]; + float freq_step; + int16_t fft_hist_size, transition_start, transition_length; + int16_t nr_fc_input, nr_fc_fft_filter; + + error = IVAS_ERR_OK; + output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + predelay_bf_len = output_frame; + nr_fc_input = hRenderConfig->roomAcoustics.nBands; + + /* Allocate main reverb. handle */ + if ( ( pState = (REVERB_HANDLE) malloc( sizeof( REVERB_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Reverberator " ); + } + + if ( ( error = set_base_config( ¶ms, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Allocate memory for feedback delay lines */ + for ( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ ) + { + if ( ( pState->loop_delay_buffer[loop_idx] = (float *) malloc( params.pLoop_delays[loop_idx] * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" ); + } + } + + /* Allocate memory for the pre-delay delay line */ + if ( ( pState->pPredelay_buffer = (float *) malloc( output_frame * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" ); + } + + pState->nr_of_branches = IVAS_REV_MAX_NR_BRANCHES; + set_fft_and_datablock_sizes( pState, subframe_len ); + nr_fc_fft_filter = ( pState->fft_size >> 1 ) + 1; + + /* === 'Control logic': compute the reverb processing parameters from the === */ + /* === room, source and listener acoustic information provided in the reverb config === */ + /* Setting up shared temporary buffers for fc, RT60, DSR, etc. */ + params.pHrtf_avg_pwr_response_l = &pFft_wf_filter_ch0[0][0]; + params.pHrtf_avg_pwr_response_r = params.pHrtf_avg_pwr_response_l + nr_fc_fft_filter; + params.pRt60 = &pFft_wf_filter_ch1[0][0]; + params.pDsr = params.pRt60 + nr_fc_fft_filter; + params.pFc = &pState->fft_filter_color_0.fft_spectrum[0]; + params.pHrtf_inter_aural_coherence = &pState->fft_filter_color_1.fft_spectrum[0]; + + /* Note: these temp buffers can only be used before the final step of the FFT filter design : */ + /* before calls to ivas_reverb_calc_correl_filters(...) or to ivas_reverb_calc_color_filters(...) */ + + /* set the uniform frequency grid for FFT filtering */ + freq_step = 0.5f * output_Fs / ( nr_fc_fft_filter - 1 ); + for ( bin_idx = 0; bin_idx < nr_fc_fft_filter; bin_idx++ ) + { + params.pFc[bin_idx] = freq_step * bin_idx; + } + + /* set up reverb acoustic data on the basis of HRTF data and renderer config */ + set_reverb_acoustic_data( ¶ms, input_audio_config, hHrtf, &hRenderConfig->roomAcoustics, subframe_len, nr_fc_input, nr_fc_fft_filter ); + + /* set reverb acoustic configuration based on renderer config */ +#ifdef DEBUGGING + pState->pConfig.renderer_type_override = hRenderConfig->renderer_type_override; +#endif + pState->pConfig.roomAcoustics.override = hRenderConfig->roomAcoustics.override; + pState->pConfig.roomAcoustics.use_brir = hRenderConfig->roomAcoustics.use_brir; + pState->pConfig.roomAcoustics.late_reverb_on = hRenderConfig->roomAcoustics.late_reverb_on; + pState->pConfig.roomAcoustics.nBands = hRenderConfig->roomAcoustics.nBands; + + /* set up input downmix */ + pState->dmx_gain = calc_dmx_gain(); + + /* set up predelay - must be after set_base_config() and before compute_t60_coeffs() */ + calc_predelay( ¶ms, hRenderConfig->roomAcoustics.acousticPreDelay, output_Fs ); + + /* set up jot reverb 60 filters - must be set up after set_reverb_acoustic_data() */ + if ( ( error = compute_t60_coeffs( ¶ms, nr_fc_fft_filter, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Compute target levels (gains) for the coloration filters */ + ivas_reverb_calc_color_levels( output_Fs, nr_fc_fft_filter, params.nr_loops, params.pFc, params.pDsr, params.pHrtf_avg_pwr_response_l_const, params.pHrtf_avg_pwr_response_r_const, + params.pLoop_delays, params.pT60_filter_coeff, pColor_target_l, pColor_target_r ); + + /* Defining appropriate windowing parameters for FFT filters to prevent aliasing */ + fft_hist_size = pState->fft_size - pState->fft_subblock_size; + transition_start = (int16_t) round( FFT_FILTER_WND_FLAT_REGION * fft_hist_size ); + transition_length = (int16_t) round( FFT_FILTER_WND_TRANS_REGION * fft_hist_size ); + + /* Compute the window used for FFT filters */ + ivas_reverb_define_window_fft( pTime_window, transition_start, transition_length, nr_fc_fft_filter ); + + + /* === Now, copy parameters from ivas_reverb_params_t into DSP blocks === */ + /* === to be used for subsequent audio signal processing === */ + + pState->do_corr_filter = params.do_corr_filter; + + /* clear & init jot reverb fft filters */ + if ( ( error = initialize_reverb_filters( pState ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( pState->do_corr_filter ) + { + /* Computing correlation filters on the basis of target IA coherence */ + ivas_reverb_calc_correl_filters( params.pHrtf_inter_aural_coherence_const, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 ); + + /* Copying the computed FFT correlation filters to the fft_filter components */ + if ( ( error = set_correl_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = set_correl_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Computing coloration filters on the basis of target responses */ + ivas_reverb_calc_color_filters( pColor_target_l, pColor_target_r, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 ); + + /* Copying the computed FFT colorations filters to the fft_filter components */ + if ( ( error = set_color_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = set_color_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* init predelay */ + ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer, params.pre_delay, predelay_bf_len ); + + /* set up feedback delay network */ + if ( ( error = setup_FDN_branches( pState, ¶ms ) ) != IVAS_ERR_OK ) + { + return error; + } + + *hReverb = pState; + + return error; +} + + +/*------------------------------------------------------------------------- + * ivas_reverb_close() + * + * Deallocate Crend reverberation handle + *------------------------------------------------------------------------*/ + +void ivas_reverb_close( + REVERB_HANDLE *hReverb_in /* i/o: Reverberator handle */ +) +{ + REVERB_HANDLE hReverb; + int16_t loop_idx; + + hReverb = *hReverb_in; + + if ( hReverb != NULL ) + { + for ( loop_idx = 0; loop_idx < IVAS_REV_MAX_NR_BRANCHES; loop_idx++ ) + { + if ( hReverb->loop_delay_buffer[loop_idx] != NULL ) + { + free( hReverb->loop_delay_buffer[loop_idx] ); + hReverb->loop_delay_buffer[loop_idx] = NULL; + } + } + + free( hReverb->pPredelay_buffer ); + hReverb->pPredelay_buffer = NULL; + + free( hReverb ); + hReverb = NULL; + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function post_fft_filter() + * + * + *-----------------------------------------------------------------------------------------*/ + +static void post_fft_filter( + REVERB_HANDLE hReverb, + float *p0, + float *p1, + float *pBuffer_0, + float *pBuffer_1 ) +{ + if ( hReverb->do_corr_filter ) + { + ivas_reverb_t2f_f2t_in( &hReverb->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 ); + ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_correl_0, pBuffer_0 ); + ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_correl_1, pBuffer_1 ); + ivas_reverb_fft_filter_CrossMix( pBuffer_0, pBuffer_1, hReverb->fft_filter_correl_0.fft_size ); + } + else + { + ivas_reverb_t2f_f2t_in( &hReverb->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 ); + } + + ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_color_0, pBuffer_0 ); + ivas_reverb_fft_filter_ComplexMul( &hReverb->fft_filter_color_1, pBuffer_1 ); + ivas_reverb_t2f_f2t_out( &hReverb->fft_filter_ols, pBuffer_0, pBuffer_1, p0, p1 ); + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function reverb_block() + * + * Input a block (mono) and calculate the 2 output blocks. + *-----------------------------------------------------------------------------------------*/ + +static void reverb_block( + REVERB_HANDLE hReverb, + float *pInput, + float *pOut0, + float *pOut1 ) + +{ + uint16_t nr_branches = hReverb->nr_of_branches; + uint16_t bsize = hReverb->full_block_size; + uint16_t inner_bsize = INNER_BLK_SIZE; + uint16_t i, j, k, ns, branch_idx, blk_idx, start_sample_idx; + + float *pFFT_buf[2], FFT_buf_1[RV_FILTER_MAX_FFT_SIZE], FFT_buf_2[RV_FILTER_MAX_FFT_SIZE]; + float pFeedback_input[INNER_BLK_SIZE]; + float pTemp[INNER_BLK_SIZE]; + float *ppOutput[IVAS_REV_MAX_NR_BRANCHES]; + float Output[IVAS_REV_MAX_NR_BRANCHES][INNER_BLK_SIZE]; + + pFFT_buf[0] = &FFT_buf_1[0]; + pFFT_buf[1] = &FFT_buf_2[0]; + + for ( branch_idx = 0; branch_idx < nr_branches; branch_idx++ ) + { + ppOutput[branch_idx] = (float *) Output + branch_idx * inner_bsize; + } + + for ( k = 0; k < bsize; k += inner_bsize ) + { + float *pO0 = &pOut0[k]; + float *pO1 = &pOut1[k]; + for ( i = 0; i < inner_bsize; i++ ) + { + pO0[i] = 0.0f; + pO1[i] = 0.0f; + } + + /* feedback network: */ + for ( i = 0; i < nr_branches; i++ ) + { + float *pOutput_i = &ppOutput[i][0]; + float mixer_0_i = hReverb->mixer[0][i]; + float mixer_1_i = hReverb->mixer[1][i]; + + /* output and feedback are same, get sample from delay line ... */ + ivas_rev_delay_line_get_sample_blk( &( hReverb->delay_line[i] ), inner_bsize, pTemp ); + ivas_reverb_iir_filt_2taps_feed_blk( &( hReverb->t60[i] ), inner_bsize, pTemp, ppOutput[i] ); + for ( ns = 0; ns < inner_bsize; ns++ ) + { + pO0[ns] += pOutput_i[ns] * mixer_0_i; /* mixer ch 0 */ + pO1[ns] += pOutput_i[ns] * mixer_1_i; /* mixer ch 1 */ + } + } + + for ( i = 0; i < nr_branches; i++ ) + { + float *pIn = &pInput[k]; + + for ( ns = 0; ns < inner_bsize; ns++ ) + { + pFeedback_input[ns] = pIn[ns]; + } + + for ( j = 0; j < nr_branches; j++ ) + { + float gain_matrix_j_i = hReverb->gain_matrix[j][i]; + float *pOutput = &ppOutput[j][0]; + for ( ns = 0; ns < inner_bsize; ns++ ) + { + pFeedback_input[ns] += gain_matrix_j_i * pOutput[ns]; + } + } + + ivas_rev_delay_line_feed_sample_blk( &( hReverb->delay_line[i] ), inner_bsize, pFeedback_input ); + } + } + + /* Applying FFT filter to each sub-frame */ + for ( blk_idx = 0; blk_idx < hReverb->num_fft_subblocks; blk_idx++ ) + { + start_sample_idx = blk_idx * hReverb->fft_subblock_size; + post_fft_filter( hReverb, pOut0 + start_sample_idx, pOut1 + start_sample_idx, pFFT_buf[0], pFFT_buf[1] ); + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function downmix_input_block() + * + * Downmix input to mono, taking also DSR gain into account + *-----------------------------------------------------------------------------------------*/ + +static ivas_error downmix_input_block( + const REVERB_HANDLE hReverb, + float pcm_in[][L_FRAME48k], + const AUDIO_CONFIG input_audio_config, + float *pPcm_out, + const int16_t input_offset ) +{ + int16_t i, s, nchan_transport; + float dmx_gain = hReverb->dmx_gain; + + switch ( input_audio_config ) + { + case AUDIO_CONFIG_STEREO: + case AUDIO_CONFIG_5_1: + case AUDIO_CONFIG_7_1: + case AUDIO_CONFIG_5_1_2: + case AUDIO_CONFIG_5_1_4: + case AUDIO_CONFIG_7_1_4: + case AUDIO_CONFIG_ISM1: + case AUDIO_CONFIG_ISM2: + case AUDIO_CONFIG_ISM3: + case AUDIO_CONFIG_ISM4: + { + nchan_transport = audioCfg2channels( input_audio_config ); + for ( s = 0; s < hReverb->full_block_size; s++ ) + { + float temp = pcm_in[0][input_offset + s]; + for ( i = 1; i < nchan_transport; i++ ) + { + temp += pcm_in[i][input_offset + s]; + } + pPcm_out[s] = dmx_gain * temp; + } + break; + } + case AUDIO_CONFIG_MONO: /* ~'ZOA_1' */ + case AUDIO_CONFIG_FOA: + case AUDIO_CONFIG_HOA2: + case AUDIO_CONFIG_HOA3: + { + for ( s = 0; s < hReverb->full_block_size; s++ ) + { + pPcm_out[s] = dmx_gain * pcm_in[0][input_offset + s]; + } + break; + } + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" ); + break; + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function predelay_block() + * + * Perform a predelay + *-----------------------------------------------------------------------------------------*/ + +static void predelay_block( + const REVERB_HANDLE hReverb, + float *pInput, + float *pOutput ) +{ + uint16_t i, idx, n_samples, blk_size; + uint16_t max_blk_size = (uint16_t) hReverb->predelay_line.Delay; + + if ( max_blk_size < 2 ) + { + if ( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */ + { + for ( i = 0; i < hReverb->full_block_size; i++ ) + { + pOutput[i] = pInput[i]; + } + } + else /* 1-sample length delay line: feed the data sample-by-sample */ + { + for ( i = 0; i < hReverb->full_block_size; i++ ) + { + pOutput[i] = ivas_rev_delay_line_get_sample( &( hReverb->predelay_line ) ); + ivas_rev_delay_line_feed_sample( &( hReverb->predelay_line ), pInput[i] ); + } + } + } + else /* multiple-sample length delay line: use block processing */ + { + idx = 0; + n_samples = hReverb->full_block_size; + while ( n_samples > 0 ) + { + blk_size = n_samples; + if ( blk_size > max_blk_size ) + { + blk_size = max_blk_size; + } + ivas_rev_delay_line_get_sample_blk( &( hReverb->predelay_line ), blk_size, &pOutput[idx] ); + ivas_rev_delay_line_feed_sample_blk( &( hReverb->predelay_line ), blk_size, &pInput[idx] ); + idx += blk_size; + n_samples -= blk_size; + } + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function mix_output_block() + * + * mix one block of *pInL and *pInR samples into *pOutL and *pOutL respectively + *-----------------------------------------------------------------------------------------*/ + +static void mix_output_block( + const REVERB_HANDLE hReverb, + const float *pInL, + const float *pInR, + float *pOutL, + float *pOutR ) +{ + uint16_t i; + + for ( i = 0; i < hReverb->full_block_size; i++ ) + { + pOutL[i] += pInL[i]; + pOutR[i] += pInR[i]; + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * ivas_reverb_process() + * + * Process the input PCM audio into output PCM audio, applying reverb + *-----------------------------------------------------------------------------------------*/ + +ivas_error ivas_reverb_process( + const REVERB_HANDLE hReverb, /* i : Reverberator handle */ + const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ + const int16_t mix_signals, /* i : add reverb to output signal */ + float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ + float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ + const int16_t i_ts /* i : subframe index */ +) +{ + float tmp0[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + ivas_error error; + + if ( ( error = downmix_input_block( hReverb, pcm_in, input_audio_config, tmp1, i_ts * hReverb->full_block_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + predelay_block( hReverb, tmp1, tmp0 ); + + reverb_block( hReverb, tmp0, tmp1, tmp2 ); + + if ( mix_signals ) + { + mix_output_block( hReverb, tmp1, tmp2, &pcm_out[0][i_ts * hReverb->full_block_size], &pcm_out[1][i_ts * hReverb->full_block_size] ); + } + else + { + mvr2r( tmp1, &pcm_out[0][i_ts * hReverb->full_block_size], hReverb->full_block_size ); + mvr2r( tmp2, &pcm_out[1][i_ts * hReverb->full_block_size], hReverb->full_block_size ); + } + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * ivas_binaural_reverb_processFrame() + * + * Compute the reverberation - room effect + *------------------------------------------------------------------------*/ + +void ivas_binaural_reverb_processFrame( + REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ + const int16_t numInChannels, /* i : num inputs to be processed */ + float inReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */ + float inImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : input CLDFB data imag */ + float outReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ + float outImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data imag */ + const uint8_t offsetSamplesIO /* i : number of offset samples */ +) +{ + /* Declare the required variables */ + int16_t idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr; + float **tapRealPr, **tapImagPr; + + /* 1) Rotate the data in the loop buffer of the reverberator. + * Notice that the audio at the loop buffers is at time-inverted order + * for convolution purposes later on. */ + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + /* Move the data forwards by blockSize (i.e. by the frame size of 16 CLDFB slots) */ + mvr2r( hReverb->loopBufReal[bin], hReverb->loopBufReal[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); + mvr2r( hReverb->loopBufImag[bin], hReverb->loopBufImag[bin] + hReverb->blockSize, hReverb->loopBufLength[bin] ); + + /* Add the data from the end of the loop to the beginning, with an attenuation factor + * according to RT60. This procedure generates an IIR decaying response. The response + * is decorrelated later on. */ + v_multc( hReverb->loopBufReal[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufReal[bin], hReverb->blockSize ); + v_multc( hReverb->loopBufImag[bin] + hReverb->loopBufLength[bin], hReverb->loopAttenuationFactor[bin], hReverb->loopBufImag[bin], hReverb->blockSize ); + } + + /* 2) Apply the determined pre-delay to the input audio, and add the delayed audio to the loop. */ + idx = hReverb->preDelayBufferIndex; + for ( sample = 0; sample < hReverb->blockSize; sample++ ) + { + uint16_t sampleWithOffset; + sampleWithOffset = sample + offsetSamplesIO; + invertSampleIndex = hReverb->blockSize - sample - 1; + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order. + * Also apply the spectral gains determined for the reverberation */ + hReverb->loopBufReal[bin][invertSampleIndex] += hReverb->preDelayBufferReal[idx][bin] * hReverb->reverbEqGains[bin]; + hReverb->loopBufImag[bin][invertSampleIndex] += hReverb->preDelayBufferImag[idx][bin] * hReverb->reverbEqGains[bin]; + hReverb->preDelayBufferReal[idx][bin] = 0.0f; + hReverb->preDelayBufferImag[idx][bin] = 0.0f; + } + + /* Add every second input channel as is to the pre-delay buffer, and every second input channel with + * 90 degrees phase shift to reduce energy imbalances between coherent and incoherent sounds */ + for ( ch = 0; ch < numInChannels; ch++ ) + { + if ( ch % 2 ) + { + v_add( hReverb->preDelayBufferReal[idx], inReal[ch][sampleWithOffset], hReverb->preDelayBufferReal[idx], hReverb->numBins ); + v_add( hReverb->preDelayBufferImag[idx], inImag[ch][sampleWithOffset], hReverb->preDelayBufferImag[idx], hReverb->numBins ); + } + else + { + v_sub( hReverb->preDelayBufferReal[idx], inImag[ch][sampleWithOffset], hReverb->preDelayBufferReal[idx], hReverb->numBins ); + v_add( hReverb->preDelayBufferImag[idx], inReal[ch][sampleWithOffset], hReverb->preDelayBufferImag[idx], hReverb->numBins ); + } + } + idx = ( idx + 1 ) % hReverb->preDelayBufferLength; + } + hReverb->preDelayBufferIndex = idx; + + /* 3) Perform the filtering/decorrelating, using complex and sparse FIR filtering */ + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + /* These tap pointers have been determined to point to the loop buffer at sparse locations */ + tapRealPr = hReverb->tapPointersReal[bin][ch]; + tapImagPr = hReverb->tapPointersImag[bin][ch]; + phaseShiftTypePr = hReverb->tapPhaseShiftType[bin][ch]; + + /* Flush output */ + set_f( hReverb->outputBufferReal[bin][ch], 0.0f, hReverb->blockSize ); + set_f( hReverb->outputBufferImag[bin][ch], 0.0f, hReverb->blockSize ); + + /* Add from temporally decaying sparse tap locations the audio to the output. */ + for ( tapIdx = 0; tapIdx < hReverb->taps[bin][ch]; tapIdx++ ) + { + switch ( phaseShiftTypePr[tapIdx] ) + { + case 0: /* 0 degrees phase */ + v_add( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_add( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + case 1: /* 90 degrees phase */ + v_sub( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_add( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + case 2: /* 180 degrees phase */ + v_sub( hReverb->outputBufferReal[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_sub( hReverb->outputBufferImag[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + default: /* 270 degrees phase */ + v_add( hReverb->outputBufferReal[bin][ch], tapImagPr[tapIdx], hReverb->outputBufferReal[bin][ch], hReverb->blockSize ); + v_sub( hReverb->outputBufferImag[bin][ch], tapRealPr[tapIdx], hReverb->outputBufferImag[bin][ch], hReverb->blockSize ); + break; + } + } + } + + /* Generate diffuse field binaural coherence by mixing the incoherent reverberated channels with pre-defined gains */ + if ( bin <= hReverb->highestBinauralCoherenceBin ) + { + if ( hReverb->useBinauralCoherence ) + { + for ( sample = 0; sample < hReverb->blockSize; sample++ ) + { + float leftRe, rightRe, leftIm, rightIm; + + leftRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][1][sample]; + rightRe = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferReal[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferReal[bin][0][sample]; + leftIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][0][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][1][sample]; + rightIm = hReverb->binauralCoherenceDirectGains[bin] * hReverb->outputBufferImag[bin][1][sample] + hReverb->binauralCoherenceCrossmixGains[bin] * hReverb->outputBufferImag[bin][0][sample]; + + hReverb->outputBufferReal[bin][0][sample] = leftRe; + hReverb->outputBufferReal[bin][1][sample] = rightRe; + hReverb->outputBufferImag[bin][0][sample] = leftIm; + hReverb->outputBufferImag[bin][1][sample] = rightIm; + } + } + } + } + + /* 4) Write data to output */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + for ( sample = 0; sample < hReverb->blockSize; sample++ ) + { + uint16_t sampleWithOffset; + + sampleWithOffset = sample + offsetSamplesIO; + /* Audio was in the temporally inverted order for convolution, re-invert audio to output */ + invertSampleIndex = hReverb->blockSize - sample - 1; + + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + outReal[ch][sampleWithOffset][bin] = hReverb->outputBufferReal[bin][ch][invertSampleIndex]; + outImag[ch][sampleWithOffset][bin] = hReverb->outputBufferImag[bin][ch][invertSampleIndex]; + } + for ( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) + { + outReal[ch][sampleWithOffset][bin] = 0.0f; + outImag[ch][sampleWithOffset][bin] = 0.0f; + } + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * ivas_binaural_reverb_open() + * + * Allocate and initialize binaural room reverberator handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_binaural_reverb_open( + REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ + const int16_t numBins, /* i : number of CLDFB bins */ + const int16_t numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */ + ivas_roomAcoustics_t *roomAcoustics, /* i/o: room acoustics parameters */ + const AUDIO_CONFIG output_config, /* i : output audio configuration */ + const int32_t sampling_rate, /* i : sampling rate */ + const RENDERER_TYPE renderer_type, /* i : renderer type */ + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, /* i : FastConv HRTF handle */ + const HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : Parametric binauralizer HRTF handle */ +) +{ + int16_t bin, chIdx, k, len; + REVERB_STRUCT_HANDLE hReverb; + const float *revTimes; + float t60[CLDFB_NO_CHANNELS_MAX]; + float ene[CLDFB_NO_CHANNELS_MAX]; + + if ( ( *hReverbPr = (REVERB_STRUCT_HANDLE) malloc( sizeof( REVERB_STRUCT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + hReverb = *hReverbPr; + + hReverb->useBinauralCoherence = 1; + hReverb->preDelayBufferLength = 1; + hReverb->preDelayBufferIndex = 0; + + hReverb->numBins = numBins; + hReverb->blockSize = numCldfbSlotsPerFrame; + + for ( k = 0; k < REVERB_PREDELAY_MAX + 1; k++ ) + { + set_f( hReverb->preDelayBufferReal[k], 0.0f, hReverb->numBins ); + set_f( hReverb->preDelayBufferImag[k], 0.0f, hReverb->numBins ); + } + + if ( renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + if ( !roomAcoustics->override ) + { + revTimes = hHrtfFastConv->fastconvReverberationTimes; + } + else + { + revTimes = t60; + } + } + else + { + revTimes = hHrtfParambin->parametricReverberationTimes; + } + + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + /* Loop Buffer */ + hReverb->loopBufLengthMax[bin] = (int16_t) ( 500 / ( 1 + bin ) + ( CLDFB_NO_CHANNELS_MAX - bin ) ); + + len = hReverb->loopBufLengthMax[bin] + hReverb->blockSize; + if ( ( hReverb->loopBufReal[bin] = (float *) malloc( len * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + if ( ( hReverb->loopBufImag[bin] = (float *) malloc( len * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + set_f( hReverb->loopBufReal[bin], 0.0f, len ); + set_f( hReverb->loopBufImag[bin], 0.0f, len ); + + /* Determine loop buffer length. The following formula is manually tuned to generate sufficiently long + * but not excessively long loops to generate reverberation. */ + /* Note: the resulted length is very sensitive to the precision of the constants below (e.g. 1.45 vs. 1.45f) */ + hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 ); + hReverb->loopBufLength[bin] = min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] ); + + /* Sparse Filter Tap Locations */ + for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) + { + len = hReverb->loopBufLength[bin]; + + if ( ( hReverb->tapPhaseShiftType[bin][chIdx] = (int16_t *) malloc( len * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + set_s( hReverb->tapPhaseShiftType[bin][chIdx], 0, len ); + + if ( ( hReverb->tapPointersReal[bin][chIdx] = (float **) malloc( len * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + if ( ( hReverb->tapPointersImag[bin][chIdx] = (float **) malloc( len * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + len = hReverb->blockSize; + if ( ( hReverb->outputBufferReal[bin][chIdx] = (float *) malloc( len * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + if ( ( hReverb->outputBufferImag[bin][chIdx] = (float *) malloc( len * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + set_f( hReverb->outputBufferReal[bin][chIdx], 0.0f, len ); + set_f( hReverb->outputBufferImag[bin][chIdx], 0.0f, len ); + } + } + + +#ifdef FIX_103_RA_PARAMS_PARAM_BIN_REND + if ( ( roomAcoustics ) && ( roomAcoustics->override ) ) + { + ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfFastConv, output_config, roomAcoustics->use_brir, sampling_rate, t60, ene ); + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, t60, ene ); + ivas_binaural_reverb_setPreDelay( hReverb, (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ) ); + } + else + { + if ( renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, hHrtfFastConv->fastconvReverberationTimes, hHrtfFastConv->fastconvReverberationEneCorrections ); + ivas_binaural_reverb_setPreDelay( hReverb, 10 ); + } + else + { + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, hHrtfParambin->parametricReverberationTimes, hHrtfParambin->parametricReverberationEneCorrections ); + ivas_binaural_reverb_setPreDelay( hReverb, 10 ); + } + } +#else + if ( renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + if ( !roomAcoustics->override ) + { + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, hHrtfFastConv->fastconvReverberationTimes, hHrtfFastConv->fastconvReverberationEneCorrections ); + ivas_binaural_reverb_setPreDelay( hReverb, 10 ); + } + else + { + ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfFastConv, output_config, roomAcoustics->use_brir, sampling_rate, t60, ene ); + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, t60, ene ); + ivas_binaural_reverb_setPreDelay( hReverb, (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ) ); + } + } + else + { + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, hHrtfParambin->parametricReverberationTimes, hHrtfParambin->parametricReverberationEneCorrections ); + ivas_binaural_reverb_setPreDelay( hReverb, 10 ); + } + +#endif + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * ivas_binaural_reverb_close() + * + * Close binaural room reverberator handle + *------------------------------------------------------------------------*/ + +void ivas_binaural_reverb_close( + REVERB_STRUCT_HANDLE *hReverb /* i/o: binaural reverb handle */ +) +{ + int16_t bin, chIdx; + + if ( hReverb == NULL || *hReverb == NULL ) + { + return; + } + + for ( bin = 0; bin < ( *hReverb )->numBins; bin++ ) + { + for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) + { + free( ( *hReverb )->tapPhaseShiftType[bin][chIdx] ); + free( ( *hReverb )->tapPointersReal[bin][chIdx] ); + free( ( *hReverb )->tapPointersImag[bin][chIdx] ); + free( ( *hReverb )->outputBufferReal[bin][chIdx] ); + free( ( *hReverb )->outputBufferImag[bin][chIdx] ); + } + free( ( *hReverb )->loopBufReal[bin] ); + free( ( *hReverb )->loopBufImag[bin] ); + } + + free( ( *hReverb ) ); + ( *hReverb ) = NULL; + + return; +} diff --git a/lib_dec/ivas_reverb_delay_line.c b/lib_rend/ivas_reverb_delay_line.c similarity index 98% rename from lib_dec/ivas_reverb_delay_line.c rename to lib_rend/ivas_reverb_delay_line.c index 9ad1a03bf98b81623c1b0b70eb67981436ba3b5d..892a0d21c9854000fce1f913f16ff88ac3f3a7d8 100644 --- a/lib_dec/ivas_reverb_delay_line.c +++ b/lib_rend/ivas_reverb_delay_line.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,11 +33,12 @@ #include #include "options.h" #include "ivas_prot.h" +#include "ivas_prot_rend.h" #include "prot.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------------------------* diff --git a/lib_dec/ivas_reverb_fft_filter.c b/lib_rend/ivas_reverb_fft_filter.c similarity index 98% rename from lib_dec/ivas_reverb_fft_filter.c rename to lib_rend/ivas_reverb_fft_filter.c index 7a304aaf7c3df0b460aded859dcb66da947e2fef..725f5e6bc14dc5a43eecb292e2e23745d85c2be5 100644 --- a/lib_dec/ivas_reverb_fft_filter.c +++ b/lib_rend/ivas_reverb_fft_filter.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,13 +32,13 @@ #include #include "options.h" -#include "ivas_prot.h" +#include "prot.h" +#include "ivas_prot_rend.h" #ifdef DEBUGGING #include "debug.h" #endif #include -#include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -46,6 +46,7 @@ *------------------------------------------------------------------------------------------*/ static void fft_wrapper_2ch( float *buffer_L, float *buffer_R, const int16_t fft_size ); + static void ifft_wrapper_2ch( float *buffer_L, float *buffer_R, const int16_t fft_size ); diff --git a/lib_dec/ivas_reverb_filter_design.c b/lib_rend/ivas_reverb_filter_design.c similarity index 90% rename from lib_dec/ivas_reverb_filter_design.c rename to lib_rend/ivas_reverb_filter_design.c index a101a2308b05cfe12e34a741673334146524ad50..3069d1248af05a5429d318a1b7ea331de1dd0131 100644 --- a/lib_dec/ivas_reverb_filter_design.c +++ b/lib_rend/ivas_reverb_filter_design.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,15 +32,15 @@ #include #include "options.h" -#include "ivas_prot.h" +#include "prot.h" +#include "ivas_prot_rend.h" #ifdef DEBUGGING #include "debug.h" #endif #include #include #include -#include "prot.h" -#include "wmops.h" +#include "wmc_auto.h" /*------------------------------------------------------------------------------------------* @@ -57,8 +57,13 @@ * Function definitions *------------------------------------------------------------------------------------------*/ -/* getMinPhase computes the minimum phase spectrum that can be derived from the - amplitude spectrum of the input. */ +/*-------------------------------------------------------------------* + * calc_min_phase() + * + * Compute the minimum phase spectrum that can be derived + * from the amplitude spectrum of the input. + *-------------------------------------------------------------------*/ + static void calc_min_phase( rv_fftwf_type_complex *pSpectrum, const int16_t fft_size, @@ -186,8 +191,13 @@ static void calc_min_phase( } -/* Converts FFT-domain pFilter pH_flt into a minimum-phase pFilter. -This function expects only the positive frequency bins up to Nyquist/2 */ +/*-------------------------------------------------------------------* + * calc_min_phase_filter() + * + * Convert FFT-domain pFilter pH_flt into a minimum-phase pFilter. + * This function expects only the positive frequency bins up to Nyquist/2 + *-------------------------------------------------------------------*/ + static void calc_min_phase_filter( rv_fftwf_type_complex *pH_flt, const int16_t fft_size, @@ -220,7 +230,12 @@ static void calc_min_phase_filter( } -/* Applies the smoothing (anti-aliasing) window in the time domain */ +/*-------------------------------------------------------------------* + * apply_window_fft() + * + * Apply the smoothing (anti-aliasing) window in the time domain + *-------------------------------------------------------------------*/ + static void apply_window_fft( rv_fftwf_type_complex *pH_flt, const float *pWindow, @@ -270,7 +285,12 @@ static void apply_window_fft( } -/* Limits the gain vs frequency slope to T db per bin */ +/*-------------------------------------------------------------------* + * response_step_limit() + * + * Limit the gain vs frequency slope to T db per bin + *-------------------------------------------------------------------*/ + static void response_step_limit( float *X, const int16_t dim_x, @@ -333,7 +353,12 @@ static void response_step_limit( } -/* This function computes a smoothing window used later to avoid aliasing in FFT filters */ +/*-------------------------------------------------------------------* + * ivas_reverb_define_window_fft() + * + * Compute a smoothing window used later to avoid aliasing in FFT filters + *-------------------------------------------------------------------*/ + void ivas_reverb_define_window_fft( float *pWindow, const int16_t transitionStart, @@ -373,6 +398,11 @@ void ivas_reverb_define_window_fft( return; } +/*-------------------------------------------------------------------* + * apply_window_fft() + * + * Applies the smoothing (anti-aliasing) window in the time domain + *-------------------------------------------------------------------*/ /* Computes colorations filters for the target frequency responses */ int16_t ivas_reverb_calc_color_filters( @@ -415,7 +445,12 @@ int16_t ivas_reverb_calc_color_filters( } -/* Computes correlation filters for the target frequency response */ +/*-------------------------------------------------------------------* + * ivas_reverb_calc_correl_filters() + * + * Compute correlation filters for the target frequency response + *-------------------------------------------------------------------*/ + int16_t ivas_reverb_calc_correl_filters( const float *pTargetICC, const float *pWindow, @@ -455,7 +490,12 @@ int16_t ivas_reverb_calc_correl_filters( } -/* Computes the target levels (gains) for the coloration filters */ +/*-------------------------------------------------------------------* + * ivas_reverb_calc_color_levels() + * + * Compute the target levels (gains) for the coloration filters + *-------------------------------------------------------------------*/ + void ivas_reverb_calc_color_levels( const int32_t output_Fs, const int16_t freq_count, @@ -540,9 +580,9 @@ void ivas_reverb_calc_color_levels( const float alpha = -log__0_001 / t60[freq_idx]; const float revPredNormEnergy = ( A0_square_est / ( 2.0f * alpha ) ) * output_Fs / ( 0.8776f * minDelayDiff + 26.7741f ); - pTarget_color_L[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_L[freq_idx] ) / sqrtf( revPredNormEnergy ); + pTarget_color_L[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_L[freq_idx] ) / max( sqrtf( revPredNormEnergy ), EPS ); - pTarget_color_R[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_R[freq_idx] ) / sqrtf( revPredNormEnergy ); + pTarget_color_R[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_R[freq_idx] ) / max( sqrtf( revPredNormEnergy ), EPS ); } /* Limiting the frequency response gradients @@ -557,11 +597,12 @@ void ivas_reverb_calc_color_levels( } -/*-----------------------------------------------------------------------------------------* - * Function description : Interpolates data from the input T60 and DSR tables - * to the FFT pFilter uniform grid +/*-------------------------------------------------------------------* + * ivas_reverb_interpolate_acoustic_data() + * + * Interpolates data from the input T60 and DSR tables to the FFT pFilter uniform grid * Note: the fc frequencies both for the input and the output must be in the ascending order - *-----------------------------------------------------------------------------------------*/ + *-------------------------------------------------------------------*/ void ivas_reverb_interpolate_acoustic_data( const int16_t input_table_size, @@ -614,13 +655,19 @@ void ivas_reverb_interpolate_acoustic_data( } -/* Function analyses the HRTF set and computes avarage left/right power spectrum - and frequency-dependent IA coherence. Expects frequency-domain HRTF input */ +/*-------------------------------------------------------------------* + * ivas_reverb_get_hrtf_set_properties() + * + * Function analyses the HRTF set and computes avarage left/right power spectrum + * and frequency-dependent IA coherence. Expects frequency-domain HRTF input + *-------------------------------------------------------------------*/ + void ivas_reverb_get_hrtf_set_properties( float **ppHrtf_set_L_re, float **ppHrtf_set_L_im, float **ppHrtf_set_R_re, float **ppHrtf_set_R_im, + const AUDIO_CONFIG input_audio_config, const int16_t hrtf_count, const int16_t in_freq_count, const int16_t out_freq_count, @@ -644,7 +691,7 @@ void ivas_reverb_get_hrtf_set_properties( float avg_pwr_right[2]; float IA_coherence[2]; - if ( hrtf_count == 4 || hrtf_count == 9 || hrtf_count == 16 ) + if ( input_audio_config == AUDIO_CONFIG_FOA || input_audio_config == AUDIO_CONFIG_HOA2 || input_audio_config == AUDIO_CONFIG_HOA3 ) { is_ambisonics = 1; used_hrtf_count = 4; /* Using only 1st order HRTFs */ @@ -780,4 +827,6 @@ void ivas_reverb_get_hrtf_set_properties( pOut_avg_pwr_R[out_bin_idx] = weight_1st * avg_pwr_right[0] + relative_pos * avg_pwr_right[1]; out_i_a_coherence[out_bin_idx] = weight_1st * IA_coherence[0] + relative_pos * IA_coherence[1]; } + + return; } diff --git a/lib_dec/ivas_reverb_iir_filter.c b/lib_rend/ivas_reverb_iir_filter.c similarity index 97% rename from lib_dec/ivas_reverb_iir_filter.c rename to lib_rend/ivas_reverb_iir_filter.c index b633f8e82cbe0c9bc86955e72135340457dfacd2..ce73c9d864ed12705a82e739e891aef31c558b30 100644 --- a/lib_dec/ivas_reverb_iir_filter.c +++ b/lib_rend/ivas_reverb_iir_filter.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,13 +32,12 @@ #include #include "options.h" -#include "ivas_prot.h" #include "prot.h" +#include "ivas_prot_rend.h" #ifdef DEBUGGING #include "debug.h" #endif -#include -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------------------------* diff --git a/lib_dec/ivas_reverb_utils.c b/lib_rend/ivas_reverb_utils.c similarity index 78% rename from lib_dec/ivas_reverb_utils.c rename to lib_rend/ivas_reverb_utils.c index bfb48f735b769cd49291f877b96b5edd7f747f04..6ff101bec56d53d8b040a4504c027ec5b2e64250 100644 --- a/lib_dec/ivas_reverb_utils.c +++ b/lib_rend/ivas_reverb_utils.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,14 +33,13 @@ #include #include "options.h" #include "prot.h" -#include "ivas_prot.h" -#include "ivas_rom_binauralRenderer.h" -#include "ivas_rom_dec.h" +#include "ivas_prot_rend.h" +#include "ivas_rom_rend.h" #include #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" +#include "wmc_auto.h" /*-----------------------------------------------------------------------------------------* @@ -52,6 +51,8 @@ #define CLDFB_CONVOLVER_NTAPS_MAX ( 16 ) #define FFT_SPECTRUM_SIZE ( 1 + ( RV_FILTER_MAX_FFT_SIZE / 2 ) ) +#define N_INITIAL_IGNORED_FRAMES 4 +#define NUM_CLDFB_TAPES 7 /*-----------------------------------------------------------------------------------------* * Local function prototypes @@ -67,12 +68,7 @@ typedef struct cldfb_convolver_state float filter_states_im[BINAURAL_CONVBANDS][CLDFB_CONVOLVER_NTAPS_MAX]; } cldfb_convolver_state; -static void ivas_reverb_get_fastconv_hrtf_set_energies( - AUDIO_CONFIG input_config, - int16_t use_brir, - int32_t sampling_rate, - float *avg_pwr_left, - float *avg_pwr_right ); +static void ivas_reverb_get_fastconv_hrtf_set_energies( const HRTFS_FASTCONV_HANDLE hHrtfFastConv, const AUDIO_CONFIG input_audio_config, const int16_t use_brir, const int32_t sampling_rate, float *avg_pwr_left, float *avg_pwr_right ); /*-----------------------------------------------------------------------------------------* @@ -83,8 +79,9 @@ static void ivas_reverb_get_fastconv_hrtf_set_energies( void ivas_reverb_prepare_cldfb_params( ivas_roomAcoustics_t *pInput_params, - AUDIO_CONFIG renderer_config, - int16_t use_brir, + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, + const AUDIO_CONFIG input_audio_config, + const int16_t use_brir, const int32_t output_Fs, float *pOutput_t60, float *pOutput_ene ) @@ -94,8 +91,7 @@ void ivas_reverb_prepare_cldfb_params( float avg_pwr_left[CLDFB_NO_CHANNELS_MAX]; float avg_pwr_right[CLDFB_NO_CHANNELS_MAX]; - float delay_diff; - float ln_1e6_inverted; + float delay_diff, ln_1e6_inverted, exp_argument; const float dist = DEFAULT_SRC_DIST; const float dmx_gain_2 = 4.0f * EVS_PI * dist * dist / 0.001f; @@ -111,11 +107,15 @@ void ivas_reverb_prepare_cldfb_params( ln_1e6_inverted = 1.0f / logf( 1e06f ); for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { - const float tau = pOutput_t60[idx] * ln_1e6_inverted; - pOutput_ene[idx] *= expf( delay_diff / tau ); + exp_argument = delay_diff / ( pOutput_t60[idx] * ln_1e6_inverted ); + /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */ + exp_argument = min( exp_argument, 23.0f ); + exp_argument = max( exp_argument, -23.0f ); + pOutput_ene[idx] *= expf( exp_argument ); } - ivas_reverb_get_fastconv_hrtf_set_energies( renderer_config, use_brir, output_Fs, avg_pwr_left, avg_pwr_right ); + ivas_reverb_get_fastconv_hrtf_set_energies( hHrtfFastConv, input_audio_config, use_brir, output_Fs, avg_pwr_left, avg_pwr_right ); + for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { pOutput_ene[idx] *= 0.5f * ( avg_pwr_left[idx] + avg_pwr_right[idx] ) * dmx_gain_2; @@ -132,13 +132,14 @@ void ivas_reverb_prepare_cldfb_params( *-----------------------------------------------------------------------------------------*/ static void ivas_cldfb_convolver( - cldfb_convolver_state *pState, /* pointer to convolver state structure */ - float out_CLDFB_real[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* o : real part of binaural signals */ - float out_CLDFB_imag[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* o : imag part of binaural signals */ - float in_CLDFB_real[CLDFB_NO_CHANNELS_MAX], /* i : real part of input signals */ - float in_CLDFB_imag[CLDFB_NO_CHANNELS_MAX], /* i : imag part of input signals */ - int16_t num_conv_bands, /* i : number of convolution bands */ - int16_t num_taps ) /* i : number of filter taps */ + cldfb_convolver_state *convolver_state, /* i/o: pointer to convolver state structure */ + float out_CLDFB_real[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* o : real part of binaural signals */ + float out_CLDFB_imag[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* o : imag part of binaural signals */ + float in_CLDFB_real[CLDFB_NO_CHANNELS_MAX], /* i : real part of input signals */ + float in_CLDFB_imag[CLDFB_NO_CHANNELS_MAX], /* i : imag part of input signals */ + const int16_t num_conv_bands, /* i : number of convolution bands */ + const int16_t num_taps /* i : number of filter taps */ +) { int16_t band_idx, tap_idx; float *filter_states_real_ptr, *filter_states_imag_ptr; @@ -152,13 +153,13 @@ static void ivas_cldfb_convolver( out_imag_left = 0.0f; out_imag_right = 0.0f; - filter_states_real_ptr = (float *) &( pState->filter_states_re[band_idx][0] ); - filter_states_imag_ptr = (float *) &( pState->filter_states_im[band_idx][0] ); + filter_states_real_ptr = (float *) &( convolver_state->filter_states_re[band_idx][0] ); + filter_states_imag_ptr = (float *) &( convolver_state->filter_states_im[band_idx][0] ); - filter_taps_left_re_ptr = pState->filter_taps_left_re[band_idx]; - filter_taps_left_im_ptr = pState->filter_taps_left_im[band_idx]; - filter_taps_right_re_ptr = pState->filter_taps_right_re[band_idx]; - filter_taps_right_im_ptr = pState->filter_taps_right_im[band_idx]; + filter_taps_left_re_ptr = convolver_state->filter_taps_left_re[band_idx]; + filter_taps_left_im_ptr = convolver_state->filter_taps_left_im[band_idx]; + filter_taps_right_re_ptr = convolver_state->filter_taps_right_re[band_idx]; + filter_taps_right_im_ptr = convolver_state->filter_taps_right_im[band_idx]; for ( tap_idx = num_taps - 1; tap_idx > 0; tap_idx-- ) { @@ -197,19 +198,16 @@ static void ivas_cldfb_convolver( *-----------------------------------------------------------------------------------------*/ static void get_IR_from_filter_taps( - int16_t hrtf_idx, - AUDIO_CONFIG input_config, - int16_t use_brir, - int32_t sampling_rate, - int16_t pulse_length, + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, + const int16_t hrtf_idx, + const AUDIO_CONFIG input_audio_config, + const int16_t use_brir, + const int32_t sampling_rate, + const int16_t pulse_length, float *pOut_l, float *pOut_r ) { - const int16_t n_initial_ignored_frames = 4; - const int16_t num_cldfb_taps = 7; - int16_t i, j, band_idx, block_idx, block_len, block_count, input_sample_idx, output_sample_idx, array_idx; - int16_t is_ambisonics; HANDLE_CLDFB_FILTER_BANK handle_cldfb_analysis, handle_cldfb_synthesis_l, handle_cldfb_synthesis_r; cldfb_convolver_state convolver_state; float real_buffer_in[CLDFB_NO_CHANNELS_MAX]; @@ -218,17 +216,8 @@ static void get_IR_from_filter_taps( float out_CLDFB_imag[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; /* o : imag part of Binaural signals */ float dirac_pls[CLDFB_NO_CHANNELS_MAX + 1]; - if ( ( input_config == AUDIO_CONFIG_FOA ) || ( input_config == AUDIO_CONFIG_HOA2 ) || ( input_config == AUDIO_CONFIG_HOA3 ) ) - { - is_ambisonics = true; - } - else - { - is_ambisonics = false; - } - block_len = (int16_t) ( sampling_rate * INV_CLDFB_BANDWIDTH ); - block_count = n_initial_ignored_frames + ( pulse_length / block_len ); + block_count = N_INITIAL_IGNORED_FRAMES + ( pulse_length / block_len ); set_f( dirac_pls, 0, block_len + 1 ); dirac_pls[0] = 1.0f; @@ -236,36 +225,36 @@ static void get_IR_from_filter_taps( output_sample_idx = 0; /* Assign CLDFB taps */ - if ( is_ambisonics ) + if ( input_audio_config == AUDIO_CONFIG_FOA || input_audio_config == AUDIO_CONFIG_HOA2 || input_audio_config == AUDIO_CONFIG_HOA3 ) { for ( band_idx = 0; band_idx < BINAURAL_CONVBANDS; band_idx++ ) { - convolver_state.filter_taps_left_re[band_idx] = leftHRIRReal_HOA3[band_idx][hrtf_idx]; - convolver_state.filter_taps_left_im[band_idx] = leftHRIRImag_HOA3[band_idx][hrtf_idx]; - convolver_state.filter_taps_right_re[band_idx] = rightHRIRReal_HOA3[band_idx][hrtf_idx]; - convolver_state.filter_taps_right_im[band_idx] = rightHRIRImag_HOA3[band_idx][hrtf_idx]; + convolver_state.filter_taps_left_re[band_idx] = hHrtfFastConv->leftHRIRReal_HOA3[band_idx][hrtf_idx]; + convolver_state.filter_taps_left_im[band_idx] = hHrtfFastConv->leftHRIRImag_HOA3[band_idx][hrtf_idx]; + convolver_state.filter_taps_right_re[band_idx] = hHrtfFastConv->rightHRIRReal_HOA3[band_idx][hrtf_idx]; + convolver_state.filter_taps_right_im[band_idx] = hHrtfFastConv->rightHRIRImag_HOA3[band_idx][hrtf_idx]; } } else { array_idx = 0; - if ( input_config == AUDIO_CONFIG_5_1 ) + if ( input_audio_config == AUDIO_CONFIG_5_1 ) { array_idx = channelIndex_CICP6[hrtf_idx]; } - else if ( input_config == AUDIO_CONFIG_7_1 ) + else if ( input_audio_config == AUDIO_CONFIG_7_1 ) { array_idx = channelIndex_CICP12[hrtf_idx]; } - else if ( input_config == AUDIO_CONFIG_5_1_2 ) + else if ( input_audio_config == AUDIO_CONFIG_5_1_2 ) { array_idx = channelIndex_CICP14[hrtf_idx]; } - else if ( input_config == AUDIO_CONFIG_5_1_4 ) + else if ( input_audio_config == AUDIO_CONFIG_5_1_4 ) { array_idx = channelIndex_CICP16[hrtf_idx]; } - else if ( input_config == AUDIO_CONFIG_7_1_4 ) + else if ( input_audio_config == AUDIO_CONFIG_7_1_4 ) { array_idx = channelIndex_CICP19[hrtf_idx]; } @@ -274,20 +263,20 @@ static void get_IR_from_filter_taps( { for ( band_idx = 0; band_idx < BINAURAL_CONVBANDS; band_idx++ ) { - convolver_state.filter_taps_left_re[band_idx] = leftBRIRReal[band_idx][array_idx]; - convolver_state.filter_taps_left_im[band_idx] = leftBRIRImag[band_idx][array_idx]; - convolver_state.filter_taps_right_re[band_idx] = rightBRIRReal[band_idx][array_idx]; - convolver_state.filter_taps_right_im[band_idx] = rightBRIRImag[band_idx][array_idx]; + convolver_state.filter_taps_left_re[band_idx] = hHrtfFastConv->leftBRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_left_im[band_idx] = hHrtfFastConv->leftBRIRImag[band_idx][array_idx]; + convolver_state.filter_taps_right_re[band_idx] = hHrtfFastConv->rightBRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_right_im[band_idx] = hHrtfFastConv->rightBRIRImag[band_idx][array_idx]; } } else { for ( band_idx = 0; band_idx < BINAURAL_CONVBANDS; band_idx++ ) { - convolver_state.filter_taps_left_re[band_idx] = leftHRIRReal[band_idx][array_idx]; - convolver_state.filter_taps_left_im[band_idx] = leftHRIRImag[band_idx][array_idx]; - convolver_state.filter_taps_right_re[band_idx] = rightHRIRReal[band_idx][array_idx]; - convolver_state.filter_taps_right_im[band_idx] = rightHRIRImag[band_idx][array_idx]; + convolver_state.filter_taps_left_re[band_idx] = hHrtfFastConv->leftHRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_left_im[band_idx] = hHrtfFastConv->leftHRIRImag[band_idx][array_idx]; + convolver_state.filter_taps_right_re[band_idx] = hHrtfFastConv->rightHRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_right_im[band_idx] = hHrtfFastConv->rightHRIRImag[band_idx][array_idx]; } } } @@ -324,7 +313,7 @@ static void get_IR_from_filter_taps( } } - ivas_cldfb_convolver( &convolver_state, out_CLDFB_real, out_CLDFB_imag, real_buffer_in, imag_buffer_in, BINAURAL_CONVBANDS, num_cldfb_taps ); + ivas_cldfb_convolver( &convolver_state, out_CLDFB_real, out_CLDFB_imag, real_buffer_in, imag_buffer_in, BINAURAL_CONVBANDS, NUM_CLDFB_TAPES ); ppRealBuf[0] = out_CLDFB_real[0]; ppImagBuf[0] = out_CLDFB_imag[0]; @@ -339,7 +328,7 @@ static void get_IR_from_filter_taps( input_sample_idx = 1; } - if ( block_idx >= n_initial_ignored_frames ) + if ( block_idx >= N_INITIAL_IGNORED_FRAMES ) { output_sample_idx += block_len; } @@ -362,9 +351,10 @@ static void get_IR_from_filter_taps( *-----------------------------------------------------------------------------------------*/ static void ivas_reverb_get_cldfb_hrtf_set_properties( - AUDIO_CONFIG input_config, - int16_t use_brir, - int32_t sampling_rate, + AUDIO_CONFIG input_audio_config, + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, + const int16_t use_brir, + const int32_t sampling_rate, float *avg_pwr_left, float *avg_pwr_right ) { @@ -381,18 +371,18 @@ static void ivas_reverb_get_cldfb_hrtf_set_properties( freq_count = 1 + half_fft_size; /* chosing between ambisonics, 5.1 and 7.1 MC audio */ - if ( ( input_config == AUDIO_CONFIG_FOA ) || ( input_config == AUDIO_CONFIG_HOA2 ) || ( input_config == AUDIO_CONFIG_HOA3 ) ) + if ( ( input_audio_config == AUDIO_CONFIG_FOA ) || ( input_audio_config == AUDIO_CONFIG_HOA2 ) || ( input_audio_config == AUDIO_CONFIG_HOA3 ) ) { hrtf_count = 1; } - else if ( input_config == AUDIO_CONFIG_7_1 ) + else if ( input_audio_config == AUDIO_CONFIG_7_1 ) { hrtf_count = 7; } else { hrtf_count = 5; - input_config = AUDIO_CONFIG_5_1; + input_audio_config = AUDIO_CONFIG_5_1; } /* Zeroing before accumalation for average value computing */ @@ -406,7 +396,7 @@ static void ivas_reverb_get_cldfb_hrtf_set_properties( Loop over all the HRTFs available */ for ( hrtf_idx = 0; hrtf_idx < hrtf_count; hrtf_idx++ ) { - get_IR_from_filter_taps( hrtf_idx, input_config, use_brir, sampling_rate, IR_length, current_HRTF_data_L, current_HRTF_data_R ); + get_IR_from_filter_taps( hHrtfFastConv, hrtf_idx, input_audio_config, use_brir, sampling_rate, IR_length, current_HRTF_data_L, current_HRTF_data_R ); /* Perform forward FFT on both L/R channels */ fft_rel( current_HRTF_data_L, (int16_t) fft_size, (int16_t) log2_fft_size ); @@ -455,9 +445,10 @@ static void ivas_reverb_get_cldfb_hrtf_set_properties( *-----------------------------------------------------------------------------------------*/ static void ivas_reverb_get_fastconv_hrtf_set_energies( - AUDIO_CONFIG input_config, - int16_t use_brir, - int32_t sampling_rate, + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, + const AUDIO_CONFIG input_audio_config, + const int16_t use_brir, + const int32_t sampling_rate, float *avg_pwr_left, float *avg_pwr_right ) { @@ -478,7 +469,7 @@ static void ivas_reverb_get_fastconv_hrtf_set_energies( output_fc[freq_idx] = (float) ( ( 2 * freq_idx + 1 ) * cldfb_freq_halfstep ); } - ivas_reverb_get_cldfb_hrtf_set_properties( input_config, use_brir, sampling_rate, avg_pwr_left_fft, avg_pwr_right_fft ); + ivas_reverb_get_cldfb_hrtf_set_properties( input_audio_config, hHrtfFastConv, use_brir, sampling_rate, avg_pwr_left_fft, avg_pwr_right_fft ); ivas_reverb_interpolate_acoustic_data( FFT_SPECTRUM_SIZE, input_fc, avg_pwr_left_fft, avg_pwr_right_fft, CLDFB_NO_CHANNELS_MAX, output_fc, avg_pwr_left, avg_pwr_right ); diff --git a/lib_dec/ivas_rom_TdBinauralRenderer.c b/lib_rend/ivas_rom_TdBinauralRenderer.c similarity index 99% rename from lib_dec/ivas_rom_TdBinauralRenderer.c rename to lib_rend/ivas_rom_TdBinauralRenderer.c index 34263ea8f3d9ce8e23ff5abab66c5cdc898e6d65..4b56fb4883d7fb0b26d230409dd250cb75406f85 100644 --- a/lib_dec/ivas_rom_TdBinauralRenderer.c +++ b/lib_rend/ivas_rom_TdBinauralRenderer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -39,13 +39,15 @@ #endif #include "cnst.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" +#define WMC_TOOL_SKIP /*------------------------------------------------------------------------- * TD Binaural rendering related ROM tables *------------------------------------------------------------------------*/ /* TD renderer HRTF default model Orange53 */ +const float orange53_rom_latency_s = 0.000020834f; const int16_t orange53_rom_azimDim2[18] = { 1, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 1, }; @@ -12455,4 +12457,6 @@ const uint32_t orange53_rom_ITD_elevBsShape[28] = { 0x3ebda12f,0x3f12f685,0x3f2aaaab, }; +#undef WMC_TOOL_SKIP + /* clang-format on */ diff --git a/lib_dec/ivas_rom_TdBinauralRenderer.h b/lib_rend/ivas_rom_TdBinauralRenderer.h similarity index 96% rename from lib_dec/ivas_rom_TdBinauralRenderer.h rename to lib_rend/ivas_rom_TdBinauralRenderer.h index 7aeff4f0ff222fc08587775056a43a71bb882ec4..ccb5362c9a4a7d691e8fe738bcd83b4a23bf2187 100644 --- a/lib_dec/ivas_rom_TdBinauralRenderer.h +++ b/lib_rend/ivas_rom_TdBinauralRenderer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -42,6 +42,7 @@ * TD Binaural rendering related ROM tables *------------------------------------------------------------------------*/ /* TD renderer HRTF default model Orange53 */ +extern const float orange53_rom_latency_s; extern const int16_t orange53_rom_azimDim2[18]; extern const int16_t orange53_rom_azimDim3[18]; extern const int16_t orange53_rom_azim_start_idx[18]; diff --git a/lib_dec/ivas_rom_binauralRenderer.c b/lib_rend/ivas_rom_binauralRenderer.c similarity index 99% rename from lib_dec/ivas_rom_binauralRenderer.c rename to lib_rend/ivas_rom_binauralRenderer.c index 28c8856012ef604951b516b59533fa846c8c58ad..9708bac83aec16af96f97ae080fba9933f23d4bb 100644 --- a/lib_dec/ivas_rom_binauralRenderer.c +++ b/lib_rend/ivas_rom_binauralRenderer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,10 +37,12 @@ #endif #include "cnst.h" #include "ivas_cnst.h" -#include "wmops.h" +#include "wmc_auto.h" /* clang-format off */ +#define WMC_TOOL_SKIP + /*------------------------------------------------------------------------- * Binaural rendering related ROM tables *------------------------------------------------------------------------*/ @@ -52,7 +54,7 @@ * Generated with Matlab version 9.3.0.713579 (R2017b) by MUXE6256 */ const float FASTCONV_HOA3_latency_s = 0.001979167f; -const float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= +const float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= { { {-0.004181f, +0.093228f, +0.655506f, +0.048565f, -0.005834f, -0.005472f, -0.000066f}, @@ -956,7 +958,7 @@ const float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= } }; -const float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= +const float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= { { {-0.007849f, -0.189662f, +0.310868f, +0.002657f, -0.000617f, -0.002064f, +0.000079f}, @@ -1860,7 +1862,7 @@ const float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= } }; -const float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= +const float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= { { {-0.004181f, +0.093228f, +0.655506f, +0.048565f, -0.005834f, -0.005472f, -0.000066f}, @@ -2764,7 +2766,7 @@ const float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= } }; -const float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= +const float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= { { {-0.007849f, -0.189662f, +0.310868f, +0.002657f, -0.000617f, -0.002064f, +0.000079f}, @@ -3669,7 +3671,7 @@ const float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= }; const float FASTCONV_HRIR_latency_s = 0.000666667f; -const float leftHRIRReal[BINAURAL_CONVBANDS][15][7]= +const float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= { { {+0.331798f, +0.500334f, +0.042057f, -0.000623f, -0.000260f}, @@ -4523,7 +4525,7 @@ const float leftHRIRReal[BINAURAL_CONVBANDS][15][7]= } }; -const float leftHRIRImag[BINAURAL_CONVBANDS][15][7]= +const float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= { { {-0.346479f, +0.553523f, -0.074098f, +0.001288f, +0.000309f}, @@ -5377,7 +5379,7 @@ const float leftHRIRImag[BINAURAL_CONVBANDS][15][7]= } }; -const float rightHRIRReal[BINAURAL_CONVBANDS][15][7]= +const float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= { { {+0.065097f, +0.755993f, -0.042308f, -0.016140f, -0.000353f}, @@ -6231,7 +6233,7 @@ const float rightHRIRReal[BINAURAL_CONVBANDS][15][7]= } }; -const float rightHRIRImag[BINAURAL_CONVBANDS][15][7]= +const float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= { { {-0.179291f, +0.196331f, +0.055128f, -0.017382f, +0.000411f}, @@ -7617,7 +7619,7 @@ const float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]= /* Binaural rendering data set based on BRIRs */ /* Tables derived from Mozart IIS BRIRs.*/ const float FASTCONV_BRIR_latency_s = 0.000937500f; -const float leftBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +const float leftBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= { { { @@ -16721,7 +16723,7 @@ const float leftBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= } }; -const float leftBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +const float leftBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= { { { @@ -25825,7 +25827,7 @@ const float leftBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= } }; -const float rightBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +const float rightBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= { { { @@ -34929,7 +34931,7 @@ const float rightBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= } }; -const float rightBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +const float rightBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= { { { @@ -44033,19 +44035,20 @@ const float rightBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= } }; -const float fastconvReverberationTimes[60] = +const float fastconvReverberationTimes[CLDFB_NO_CHANNELS_MAX] = { 0.429201f, 0.205110f, 0.202338f, 0.208383f, 0.215664f, 0.236545f, 0.230598f, 0.228400f, 0.227467f, 0.218956f, 0.226083f, 0.220702f, 0.221501f, 0.223471f, 0.223705f, 0.227063f, 0.227899f, 0.223071f, 0.220000f, 0.218583f, 0.220417f, 0.218250f, 0.213250f, 0.210333f, 0.207417f, 0.198750f, 0.196250f, 0.194917f, 0.190333f, 0.184500f, 0.180333f, 0.176167f, 0.176500f, 0.177583f, 0.183583f, 0.195917f, 0.203250f, 0.208417f, 0.214667f, 0.220000f, 0.222917f, 0.230417f, 0.233928f, 0.233647f, 0.236333f, 0.237428f, 0.241629f, 0.241118f, 0.238847f, 0.242384f, 0.246292f, 0.245948f, 0.246100f, 0.245396f, 0.243951f, 0.244123f, 0.239270f, 0.241474f, 0.234824f, 0.253040f, }; -const float fastconvReverberationEneCorrections[60] = +const float fastconvReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX] = { 0.000584f, 0.000210f, 0.000233f, 0.000212f, 0.000257f, 0.001518f, 0.001154f, 0.001097f, 0.001265f, 0.001298f, 0.002320f, 0.002432f, 0.002686f, 0.002702f, 0.002632f, 0.002564f, 0.002732f, 0.002727f, 0.002609f, 0.002524f, 0.003417f, 0.001783f, 0.000987f, 0.000699f, 0.000606f, 0.000536f, 0.000511f, 0.000569f, 0.000600f, 0.000543f, 0.001257f, 0.001209f, 0.000957f, 0.000601f, 0.000274f, 0.000106f, 0.000072f, 0.000051f, 0.000040f, 0.000030f, 0.000024f, 0.000018f, 0.000014f, 0.000013f, 0.000012f, 0.000011f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000007f, 0.000006f, 0.000005f, 0.000003f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000000f, 0.000000f, }; -const float parametricReverberationTimes[CLDFB_NO_CHANNELS_MAX] = { +const float parametricReverberationTimes[CLDFB_NO_CHANNELS_MAX] = +{ 0.345494f, 0.319454f, 0.332961f, 0.360923f, 0.374299f, 0.370777f, 0.358625f, 0.348103f, 0.343109f, 0.331351f, 0.316502f, 0.304975f, 0.294855f, 0.287549f, 0.279920f, 0.270277f, 0.264042f, 0.256404f, 0.249899f, 0.242040f, 0.235074f, 0.229647f, 0.223730f, 0.218795f, 0.212599f, 0.207689f, 0.202082f, 0.198094f, 0.193907f, 0.185908f, @@ -44055,7 +44058,8 @@ const float parametricReverberationTimes[CLDFB_NO_CHANNELS_MAX] = { }; -const float parametricReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX] = { +const float parametricReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX] = +{ 0.191981f, 0.143739f, 0.113528f, 0.093836f, 0.090147f, 0.079961f, 0.066594f, 0.072700f, 0.076491f, 0.082065f, 0.085265f, 0.093864f, 0.101901f, 0.113728f, 0.117646f, 0.113494f, 0.126125f, 0.126304f, 0.123928f, 0.116067f, 0.098528f, 0.051482f, 0.029950f, 0.025223f, 0.021143f, 0.019358f, 0.016707f, 0.016227f, 0.018416f, 0.018419f, @@ -44065,7 +44069,8 @@ const float parametricReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX] = { }; -const float parametricEarlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX] = { +const float parametricEarlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX] = +{ 0.595541f, 0.684107f, 1.041399f, 0.880102f, 0.726599f, 0.529105f, 0.456758f, 0.383174f, 0.331734f, 0.330565f, 0.436469f, 0.592478f, 0.767344f, 1.110786f, 1.548546f, 1.946089f, 2.550005f, 3.382855f, 4.235532f, 4.688064f, 3.328668f, 1.312207f, 0.376543f, 0.176443f, 0.149840f, 0.130307f, 0.137089f, 0.292711f, 0.580265f, 0.733105f, @@ -44074,4 +44079,6 @@ const float parametricEarlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX] = { 0.016350f, 0.042709f, 0.077337f, 0.066238f, 0.042046f, 0.020017f, 0.007896f, 0.002947f, 0.000932f, 0.000152f }; +#undef WMC_TOOL_SKIP + /* clang-format on */ diff --git a/lib_dec/ivas_rom_binauralRenderer.h b/lib_rend/ivas_rom_binauralRenderer.h similarity index 71% rename from lib_dec/ivas_rom_binauralRenderer.h rename to lib_rend/ivas_rom_binauralRenderer.h index 3bed3c5ec9d9c5d853fa492434df1ee43e815a7d..939f6ef78fa76c7b82a6755f985294490a26d1c8 100644 --- a/lib_dec/ivas_rom_binauralRenderer.h +++ b/lib_rend/ivas_rom_binauralRenderer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -44,26 +44,27 @@ /* Binaural rendering data set based on HRIRs */ extern const float FASTCONV_HRIR_latency_s; -extern const float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]; -extern const float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]; -extern const float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]; -extern const float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]; +extern float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; +extern float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; -extern const float leftHRIRReal[BINAURAL_CONVBANDS][15][7]; -extern const float leftHRIRImag[BINAURAL_CONVBANDS][15][7]; -extern const float rightHRIRReal[BINAURAL_CONVBANDS][15][7]; -extern const float rightHRIRImag[BINAURAL_CONVBANDS][15][7]; +extern float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; +extern float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; + +extern float FASTCONV_HOA3_latency_s; +extern float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; +extern float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; -extern const float FASTCONV_HOA3_latency_s; -extern const float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; -extern const float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; /* Binaural rendering data set based on BRIRs */ extern const float FASTCONV_BRIR_latency_s; -extern const float leftBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; -extern const float leftBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; -extern const float rightBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; -extern const float rightBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; +extern float leftBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; +extern float leftBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; +extern float rightBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; +extern float rightBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; /* Reverberation parameters based on BRIRs for fastconv */ extern float fastconvReverberationTimes[CLDFB_NO_CHANNELS_MAX]; diff --git a/lib_dec/ivas_rom_binaural_crend_head.c b/lib_rend/ivas_rom_binaural_crend_head.c similarity index 99% rename from lib_dec/ivas_rom_binaural_crend_head.c rename to lib_rend/ivas_rom_binaural_crend_head.c index ac4216ef77e21c2ed351dfdb88a5652f62920c24..56a9a9ef5352414618cbc049009c64d61d3d1af9 100644 --- a/lib_dec/ivas_rom_binaural_crend_head.c +++ b/lib_rend/ivas_rom_binaural_crend_head.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,8 +37,8 @@ *------------------------------------------------------------------------*/ /* Binaural rendering data set based on HRIRs */ -/* Tables generated by the exe at "scripts/binauralRenderer_interface/generate_cren_ivas_tables*.* */ -/* Can be replaced by your own generated HRIR or BRIRI tables */ +/* Tables generated by scripts/binauralRenderer_interface/generate_cren_ivas_tables.c, see mixer_conv_sofa_to_rom_table_converter_readme.txt */ +/* Can be replaced by your own generated HRIR or BRIR tables */ @@ -47,10 +47,17 @@ #include "cnst.h" #include "ivas_cnst.h" +#define WMC_TOOL_SKIP -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_HRIR **********************/ +#ifdef FIX_BINAURAL_DELAY_PRECISION +const float CRendBin_Combined_HRIR_latency_s = 0.000020834f; +#else +const float CRendBin_Combined_HRIR_latency_s = 0.000020833333110f; +#endif + +/* Sample Rate = 48000 */ -const float CRendBin_Combined_HRIR_latency_s_48kHz = 0.000020833333110f; const int16_t CRendBin_Combined_HRIR_max_num_iterations_48kHz = 1; const uint16_t CRendBin_Combined_HRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]={{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1} }; const uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -305,9 +312,8 @@ const float CRendBin_Combined_HRIR_coeff_im_48kHz[15][BINAURAL_CHANNELS][240]={ const float *CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -const float CRendBin_Combined_HRIR_latency_s_32kHz = 0.000020833333110f; const int16_t CRendBin_Combined_HRIR_max_num_iterations_32kHz = 1; const uint16_t CRendBin_Combined_HRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]={{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1} }; const uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -502,9 +508,8 @@ const float CRendBin_Combined_HRIR_coeff_im_32kHz[15][BINAURAL_CHANNELS][160]={ const float *CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -const float CRendBin_Combined_HRIR_latency_s_16kHz = 0.000020833333110f; const int16_t CRendBin_Combined_HRIR_max_num_iterations_16kHz = 1; const uint16_t CRendBin_Combined_HRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]={{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1} }; const uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -639,9 +644,16 @@ const float CRendBin_Combined_HRIR_coeff_im_16kHz[15][BINAURAL_CHANNELS][80]={ const float *CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_HOA3_HRIR **********************/ + +#ifdef FIX_BINAURAL_DELAY_PRECISION +const float CRendBin_HOA3_HRIR_latency_s = 0.001333334f; +#else +const float CRendBin_HOA3_HRIR_latency_s = 0.001333333319053f; +#endif + +/* Sample Rate = 48000 */ -const float CRendBin_HOA3_HRIR_latency_s_48kHz = 0.001333333319053f; const int16_t CRendBin_HOA3_HRIR_max_num_iterations_48kHz = 2; const uint16_t CRendBin_HOA3_HRIR_num_iterations_48kHz[16][BINAURAL_CHANNELS]={{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2} }; const uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -1040,9 +1052,8 @@ const float CRendBin_HOA3_HRIR_coeff_im_48kHz[16][BINAURAL_CHANNELS][480]={ const float *CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -const float CRendBin_HOA3_HRIR_latency_s_32kHz = 0.001333333319053f; const int16_t CRendBin_HOA3_HRIR_max_num_iterations_32kHz = 2; const uint16_t CRendBin_HOA3_HRIR_num_iterations_32kHz[16][BINAURAL_CHANNELS]={{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2} }; const uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -1377,9 +1388,8 @@ const float CRendBin_HOA3_HRIR_coeff_im_32kHz[16][BINAURAL_CHANNELS][320]={ const float *CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -const float CRendBin_HOA3_HRIR_latency_s_16kHz = 0.001333333319053f; const int16_t CRendBin_HOA3_HRIR_max_num_iterations_16kHz = 2; const uint16_t CRendBin_HOA3_HRIR_num_iterations_16kHz[16][BINAURAL_CHANNELS]={{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2} }; const uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -1586,9 +1596,16 @@ const float CRendBin_HOA3_HRIR_coeff_im_16kHz[16][BINAURAL_CHANNELS][160]={ const float *CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_BRIR **********************/ + +#ifdef FIX_BINAURAL_DELAY_PRECISION +const float CRendBin_Combined_BRIR_latency_s = 0.000145834f; +#else +const float CRendBin_Combined_BRIR_latency_s = 0.000145833328133f; +#endif + +/* Sample Rate = 48000 */ -const float CRendBin_Combined_BRIR_latency_s_48kHz = 0.000145833328133f; const int16_t CRendBin_Combined_BRIR_max_num_iterations_48kHz = 22; const uint16_t CRendBin_Combined_BRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]={{22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22} }; const uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS] = {40, 40}; @@ -3623,9 +3640,8 @@ const float CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS][288 0.008540f, 0.000569f, 0.002267f, -0.000988f, 0.001342f} }; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -const float CRendBin_Combined_BRIR_latency_s_32kHz = 0.000145833328133f; const int16_t CRendBin_Combined_BRIR_max_num_iterations_32kHz = 22; const uint16_t CRendBin_Combined_BRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]={{22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22} }; const uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS] = {40, 40}; @@ -5584,9 +5600,8 @@ const float CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS][287 -0.030519f, 0.027258f, -0.004872f, -0.024412f, -0.025958f, 0.005865f, -0.034537f, -0.048705f, 0.008013f, -0.011347f, -0.010463f, -0.010480f, 0.009340f, -0.029039f, 0.030517f, -0.017776f, 0.020717f, -0.014466f, -0.013902f, 0.000316f, 0.016725f, -0.023690f, -0.022640f, 0.012110f, -0.004311f, 0.033404f, -0.014684f, 0.019133f, 0.028780f, 0.013672f, -0.010535f, -0.004820f, -0.003049f, 0.023610f, -0.008334f, 0.015840f, 0.031862f, -0.026837f, -0.046802f, -0.018449f, 0.015820f, 0.019420f, -0.022107f, 0.036264f, -0.011732f, -0.013165f, -0.004432f, -0.004019f, -0.011290f, -0.029439f, -0.012475f, -0.030418f, -0.029136f, -0.018067f, 0.021415f, 0.005020f, -0.005215f, 0.001915f, 0.033137f, 0.031128f, 0.002152f, -0.014470f, 0.005893f, -0.003315f, 0.013612f, 0.004239f, -0.006009f, -0.013786f, -0.001289f, -0.002803f, -0.021865f, -0.005694f, 0.008246f, 0.022588f, -0.010185f, -0.000025f, 0.008581f, -0.012767f, -0.000458f, -0.000932f, 0.000324f, -0.006676f, 0.008426f, 0.000455f, 0.002150f, -0.001106f} }; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -const float CRendBin_Combined_BRIR_latency_s_16kHz = 0.000145833328133f; const int16_t CRendBin_Combined_BRIR_max_num_iterations_16kHz = 23; const uint16_t CRendBin_Combined_BRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]={{23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23} }; const uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS] = {40, 40}; @@ -6909,3 +6924,4 @@ const float CRendBin_Combined_BRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS][252 0.050578f, 0.012222f, 0.020049f, -0.020057f, -0.032135f, -0.002553f, -0.037541f, -0.023567f, -0.008392f, -0.012215f, 0.001644f, -0.001142f, 0.000540f, 0.001404f, -0.027979f, -0.022362f, -0.012091f, -0.022963f, 0.009075f, 0.010977f, -0.007069f, -0.000183f, -0.022228f, -0.001348f, 0.006548f, -0.003034f} }; +#undef WMC_TOOL_SKIP diff --git a/lib_dec/ivas_rom_binaural_crend_head.h b/lib_rend/ivas_rom_binaural_crend_head.h similarity index 88% rename from lib_dec/ivas_rom_binaural_crend_head.h rename to lib_rend/ivas_rom_binaural_crend_head.h index af012e7fa62c0321b636bae715f2a28239b8a4cb..64582a16723b9f0dd5956d6c213fa4f5ab0d44f7 100644 --- a/lib_dec/ivas_rom_binaural_crend_head.h +++ b/lib_rend/ivas_rom_binaural_crend_head.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,8 +37,8 @@ *------------------------------------------------------------------------*/ /* Binaural rendering data set based on HRIRs */ -/* Tables generated by the exe at "scripts/binauralRenderer_interface/generate_cren_ivas_tables*.* */ -/* Can be replaced by your own generated HRIR or BRIRI tables */ +/* Tables generated by scripts/binauralRenderer_interface/generate_cren_ivas_tables.c, see mixer_conv_sofa_to_rom_table_converter_readme.txt */ +/* Can be replaced by your own generated HRIR or BRIR tables */ @@ -50,9 +50,12 @@ #include "ivas_cnst.h" -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_HRIR **********************/ + +extern float CRendBin_Combined_HRIR_latency_s; + +/* Sample Rate = 48000 */ -extern float CRendBin_Combined_HRIR_latency_s_48kHz; extern int16_t CRendBin_Combined_HRIR_max_num_iterations_48kHz; extern uint16_t CRendBin_Combined_HRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS]; @@ -65,9 +68,8 @@ extern float CRendBin_Combined_HRIR_coeff_im_48kHz[15][BINAURAL_CHANNELS][240]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -extern float CRendBin_Combined_HRIR_latency_s_32kHz; extern int16_t CRendBin_Combined_HRIR_max_num_iterations_32kHz; extern uint16_t CRendBin_Combined_HRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS]; @@ -80,9 +82,8 @@ extern float CRendBin_Combined_HRIR_coeff_im_32kHz[15][BINAURAL_CHANNELS][160]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -extern float CRendBin_Combined_HRIR_latency_s_16kHz; extern int16_t CRendBin_Combined_HRIR_max_num_iterations_16kHz; extern uint16_t CRendBin_Combined_HRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS]; @@ -95,9 +96,12 @@ extern float CRendBin_Combined_HRIR_coeff_im_16kHz[15][BINAURAL_CHANNELS][80]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_HOA3_HRIR **********************/ + +extern float CRendBin_HOA3_HRIR_latency_s; + +/* Sample Rate = 48000 */ -extern float CRendBin_HOA3_HRIR_latency_s_48kHz; extern int16_t CRendBin_HOA3_HRIR_max_num_iterations_48kHz; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_48kHz[16][BINAURAL_CHANNELS]; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS]; @@ -110,9 +114,8 @@ extern float CRendBin_HOA3_HRIR_coeff_im_48kHz[16][BINAURAL_CHANNELS][480]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -extern float CRendBin_HOA3_HRIR_latency_s_32kHz; extern int16_t CRendBin_HOA3_HRIR_max_num_iterations_32kHz; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_32kHz[16][BINAURAL_CHANNELS]; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS]; @@ -125,9 +128,8 @@ extern float CRendBin_HOA3_HRIR_coeff_im_32kHz[16][BINAURAL_CHANNELS][320]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -extern float CRendBin_HOA3_HRIR_latency_s_16kHz; extern int16_t CRendBin_HOA3_HRIR_max_num_iterations_16kHz; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_16kHz[16][BINAURAL_CHANNELS]; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS]; @@ -140,9 +142,12 @@ extern float CRendBin_HOA3_HRIR_coeff_im_16kHz[16][BINAURAL_CHANNELS][160]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_BRIR **********************/ + +extern float CRendBin_Combined_BRIR_latency_s; + +/* Sample Rate = 48000 */ -extern float CRendBin_Combined_BRIR_latency_s_48kHz; extern int16_t CRendBin_Combined_BRIR_max_num_iterations_48kHz; extern uint16_t CRendBin_Combined_BRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS]; @@ -155,9 +160,8 @@ extern float CRendBin_Combined_BRIR_coeff_im_48kHz[15][BINAURAL_CHANNELS][2955]; extern float CRendBin_Combined_BRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS][2885]; extern float CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS][2885]; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -extern float CRendBin_Combined_BRIR_latency_s_32kHz; extern int16_t CRendBin_Combined_BRIR_max_num_iterations_32kHz; extern uint16_t CRendBin_Combined_BRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS]; @@ -170,9 +174,8 @@ extern float CRendBin_Combined_BRIR_coeff_im_32kHz[15][BINAURAL_CHANNELS][2819]; extern float CRendBin_Combined_BRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS][2870]; extern float CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS][2870]; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -extern float CRendBin_Combined_BRIR_latency_s_16kHz; extern int16_t CRendBin_Combined_BRIR_max_num_iterations_16kHz; extern uint16_t CRendBin_Combined_BRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS]; diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c new file mode 100644 index 0000000000000000000000000000000000000000..dd8ca99d80ee6cb990fa7f65db3db9539cd837f5 --- /dev/null +++ b/lib_rend/ivas_rom_rend.c @@ -0,0 +1,700 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "ivas_rom_rend.h" + +/* clang-format off */ + +/*----------------------------------------------------------------------------------* + * FASTCONV and PARAMETRIC binaural renderer ROM tables + *----------------------------------------------------------------------------------*/ + +/* +* 0 = 30,0 +* 1 = -30,0 +* 2 = 0,0 +* 3 = 135,0 +* 4 = -135,0 +* 5 = 110,0 +* 6 = -110,0 +* 7 = 90,0 +* 8 = -90,0 +* 9 = 30,35 +* 10 = -30,35 +* 11 = 110,35 +* 12 = -110,35 +* 13 = 135, 35 +* 14 = -135, 35 +*/ +const int16_t channelIndex_CICP6[5] = { 0, 1, 2, 5, 6 }; +const int16_t channelIndex_CICP12[7] = { 0, 1, 2, 5, 6, 3, 4 }; +const int16_t channelIndex_CICP14[7] = { 0, 1, 2, 5, 6, 9, 10 }; +const int16_t channelIndex_CICP16[9] = { 0, 1, 2, 5, 6, 9, 10, 11, 12 }; +const int16_t channelIndex_CICP19[11] = { 0, 1, 2, 3, 4, 7, 8, 9, 10, 13, 14 }; + + +const float surCohEne[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = +{ + 3.0903f, 2.0053f, 1.0860f, 0.8072f, 0.7079f +}; + +const float spreadCohEne05[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = +{ + 2.3988f, 1.7783f, 1.1220f, 1.1220f, 1.1220f +}; + +const float spreadCohEne1[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = +{ + 1.5975f, 1.1220f, 1.1220f, 1.1220f, 1.1220f +}; + +const float lowBitRateBinauralEQ[LOW_BIT_RATE_BINAURAL_EQ_BINS] = +{ + 0.979f, 0.893f, 0.762f, 0.615f, 0.52f, 0.48f, 0.477f, 0.477f, 0.48f, 0.501f, 0.546f, 0.602f, 0.652f, 0.664f, 0.652f, 0.639f, 0.635f +}; + +const float diffuseFieldCoherenceDifferenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS] = +{ + 0.047421f, 0.19773f, 0.22582f, 0.10637f, 0.0087111f, 0.012028f, 0.031972f, 0.019668f, 0.0079928f +}; + +const float diffuseFieldCoherenceDifferenceY[BINAURAL_COHERENCE_DIFFERENCE_BINS] = +{ + -0.095628f, -0.30569f, -0.34427f, -0.15425f, -0.044628f, -0.057224f, -0.050835f, -0.035214f, -0.02215f +}; + +const float diffuseFieldCoherenceDifferenceZ[BINAURAL_COHERENCE_DIFFERENCE_BINS] = +{ + 0.048207f, 0.10796f, 0.11845f, 0.047886f, 0.035917f, 0.045196f, 0.018863f, 0.015547f, 0.014157f +}; + + +/*----------------------------------------------------------------------------------* + * TD ISM binaural renderer ROM tables + *----------------------------------------------------------------------------------*/ + +const int16_t HRTF_MODEL_N_CPTS_VAR[HRTF_MODEL_N_SECTIONS] = +{ + 13, 12, 11 +}; + +const float SincTable[321] = +{ + 1.00000000f, 0.99957629f, 0.99830587f, 0.99619078f, 0.99323448f, 0.98944177f, 0.98481881f, 0.97937311f, + 0.97311350f, 0.96605012f, 0.95819441f, 0.94955907f, 0.94015803f, 0.93000645f, 0.91912066f, 0.90751815f, + 0.89521750f, 0.88223838f, 0.86860150f, 0.85432856f, 0.83944219f, 0.82396595f, 0.80792425f, 0.79134231f, + 0.77424608f, 0.75666226f, 0.73861817f, 0.72014174f, 0.70126144f, 0.68200624f, 0.66240553f, 0.64248906f, + 0.62228691f, 0.60182943f, 0.58114713f, 0.56027070f, 0.53923087f, 0.51805843f, 0.49678411f, 0.47543856f, + 0.45405225f, 0.43265547f, 0.41127824f, 0.38995024f, 0.36870081f, 0.34755883f, 0.32655271f, 0.30571035f, + 0.28505905f, 0.26462549f, 0.24443569f, 0.22451493f, 0.20488776f, 0.18557791f, 0.16660829f, 0.14800093f, + 0.12977695f, 0.11195656f, 0.09455895f, 0.07760236f, 0.06110400f, 0.04508003f, 0.02954554f, 0.01451456f, + 0.00000000f, -0.01398631f, -0.02743368f, -0.04033255f, -0.05267447f, -0.06445214f, -0.07565940f, -0.08629121f, + -0.09634367f, -0.10581400f, -0.11470052f, -0.12300268f, -0.13072098f, -0.13785702f, -0.14441345f, -0.15039394f, + -0.15580318f, -0.16064685f, -0.16493160f, -0.16866498f, -0.17185547f, -0.17451243f, -0.17664604f, -0.17826729f, + -0.17938796f, -0.18002054f, -0.18017822f, -0.17987486f, -0.17912493f, -0.17794347f, -0.17634608f, -0.17434883f, + -0.17196824f, -0.16922125f, -0.16612516f, -0.16269761f, -0.15895648f, -0.15491992f, -0.15060625f, -0.14603396f, + -0.14122162f, -0.13618787f, -0.13095139f, -0.12553081f, -0.11994473f, -0.11421163f, -0.10834984f, -0.10237755f, + -0.09631271f, -0.09017300f, -0.08397586f, -0.07773838f, -0.07147731f, -0.06520902f, -0.05894946f, -0.05271415f, + -0.04651815f, -0.04037601f, -0.03430179f, -0.02830902f, -0.02241063f, -0.01661904f, -0.01094605f, -0.00540284f, + -0.00000000f, 0.00525251f, 0.01034538f, 0.01526993f, 0.02001814f, 0.02458266f, 0.02895676f, 0.03313441f, + 0.03711021f, 0.04087943f, 0.04443799f, 0.04778246f, 0.05091003f, 0.05381856f, 0.05650650f, 0.05897292f, + 0.06121749f, 0.06324047f, 0.06504268f, 0.06662549f, 0.06799083f, 0.06914112f, 0.07007930f, 0.07080878f, + 0.07133343f, 0.07165755f, 0.07178588f, 0.07172352f, 0.07147595f, 0.07104902f, 0.07044886f, 0.06968193f, + 0.06875494f, 0.06767485f, 0.06644886f, 0.06508435f, 0.06358888f, 0.06197015f, 0.06023599f, 0.05839432f, + 0.05645314f, 0.05442051f, 0.05230450f, 0.05011320f, 0.04785466f, 0.04553692f, 0.04316793f, 0.04075558f, + 0.03830765f, 0.03583181f, 0.03333557f, 0.03082630f, 0.02831121f, 0.02579730f, 0.02329137f, 0.02080003f, + 0.01832963f, 0.01588629f, 0.01347589f, 0.01110403f, 0.00877607f, 0.00649705f, 0.00427175f, 0.00210467f, + 0.00000000f, -0.00203837f, -0.00400686f, -0.00590216f, -0.00772131f, -0.00946162f, -0.01112072f, -0.01269654f, + -0.01418731f, -0.01559156f, -0.01690810f, -0.01813605f, -0.01927478f, -0.02032396f, -0.02128352f, -0.02215366f, + -0.02293482f, -0.02362769f, -0.02423318f, -0.02475245f, -0.02518686f, -0.02553797f, -0.02580754f, -0.02599752f, + -0.02611000f, -0.02614728f, -0.02611175f, -0.02600597f, -0.02583262f, -0.02559449f, -0.02529446f, -0.02493550f, + -0.02452066f, -0.02405306f, -0.02353586f, -0.02297226f, -0.02236549f, -0.02171881f, -0.02103547f, -0.02031874f, + -0.01957185f, -0.01879802f, -0.01800043f, -0.01718225f, -0.01634655f, -0.01549638f, -0.01463471f, -0.01376443f, + -0.01288838f, -0.01200928f, -0.01112977f, -0.01025241f, -0.00937962f, -0.00851376f, -0.00765705f, -0.00681160f, + -0.00597942f, -0.00516238f, -0.00436225f, -0.00358068f, -0.00281917f, -0.00207914f, -0.00136185f, -0.00066846f, + -0.00000000f, 0.00064260f, 0.00125856f, 0.00184718f, 0.00240790f, 0.00294026f, 0.00344390f, 0.00391857f, + 0.00436413f, 0.00478051f, 0.00516776f, 0.00552600f, 0.00585544f, 0.00615637f, 0.00642915f, 0.00667420f, + 0.00689203f, 0.00708318f, 0.00724827f, 0.00738795f, 0.00750293f, 0.00759395f, 0.00766178f, 0.00770723f, + 0.00773114f, 0.00773435f, 0.00771774f, 0.00768218f, 0.00762857f, 0.00755779f, 0.00747075f, 0.00736831f, + 0.00725138f, 0.00712082f, 0.00697748f, 0.00682221f, 0.00665584f, 0.00647916f, 0.00629295f, 0.00609797f, + 0.00589494f, 0.00568458f, 0.00546754f, 0.00524448f, 0.00501600f, 0.00478270f, 0.00454511f, 0.00430377f, + 0.00405916f, 0.00381176f, 0.00356198f, 0.00331023f, 0.00305690f, 0.00280234f, 0.00254687f, 0.00229079f, + 0.00203440f, 0.00177795f, 0.00152168f, 0.00126584f, 0.00101062f, 0.00075625f, 0.00050289f, 0.00025075f, + 0.00000000f +}; + +const float orange53_left_avg_power[257] = { + 0.999231100f, 0.992580175f, 0.969233215f, 0.925614893f, 0.871408045f, 0.826101780f, 0.803222895f, 0.800087631f, 0.802672029f, + 0.801490188f, 0.796555817f, 0.790879488f, 0.784882724f, 0.777585745f, 0.769326210f, 0.761789441f, 0.756145239f, 0.752754092f, + 0.751703024f, 0.752594173f, 0.754317880f, 0.755515277f, 0.754378498f, 0.748860359f, 0.738919020f, 0.727488697f, 0.718792558f, + 0.714865267f, 0.713446736f, 0.711076498f, 0.706021905f, 0.697553098f, 0.684623063f, 0.667031527f, 0.647006035f, 0.627680719f, + 0.609939933f, 0.592472672f, 0.574803054f, 0.558499217f, 0.544599831f, 0.532128096f, 0.520152628f, 0.509682238f, 0.501904130f, + 0.496162385f, 0.491121918f, 0.486813396f, 0.483951330f, 0.482198298f, 0.480713189f, 0.479654074f, 0.479590476f, 0.479965866f, + 0.479589254f, 0.478181243f, 0.476334095f, 0.474199444f, 0.471616089f, 0.469089746f, 0.467486322f, 0.466943622f, 0.467153549f, + 0.468381166f, 0.470996737f, 0.474416614f, 0.477639019f, 0.480612457f, 0.483910263f, 0.487287015f, 0.489909321f, 0.491668850f, + 0.493155539f, 0.494319856f, 0.494512051f, 0.493615031f, 0.492155492f, 0.490116775f, 0.486886710f, 0.482303619f, 0.476902038f, + 0.470775038f, 0.463377595f, 0.454571068f, 0.445130944f, 0.435581058f, 0.425568998f, 0.414717495f, 0.403531373f, 0.392556936f, + 0.381436378f, 0.369506508f, 0.357099295f, 0.345049500f, 0.333368897f, 0.321326375f, 0.308959186f, 0.297232091f, 0.286592871f, + 0.276453108f, 0.266589880f, 0.257950366f, 0.251341701f, 0.246435612f, 0.242861211f, 0.241405189f, 0.242839754f, 0.246688128f, + 0.252115428f, 0.259297341f, 0.268399984f, 0.278481483f, 0.288520366f, 0.298599035f, 0.308846802f, 0.318350822f, 0.326248646f, + 0.332813978f, 0.338464528f, 0.342543274f, 0.344278336f, 0.344031811f, 0.342641503f, 0.339995682f, 0.335437506f, 0.329174429f, + 0.322237372f, 0.315035462f, 0.306967229f, 0.297821850f, 0.288482070f, 0.279766560f, 0.271234214f, 0.262228251f, 0.253214896f, + 0.245183259f, 0.237939596f, 0.230546176f, 0.223051578f, 0.216552779f, 0.211263061f, 0.206180066f, 0.200917527f, 0.196485907f, + 0.193453044f, 0.190857053f, 0.187853232f, 0.185171053f, 0.183685005f, 0.182665780f, 0.180928215f, 0.178784713f, 0.177342966f, + 0.176323384f, 0.174430951f, 0.171496049f, 0.168740034f, 0.166518897f, 0.163711995f, 0.159658119f, 0.155442193f, 0.152056932f, + 0.148795277f, 0.144545168f, 0.139905334f, 0.136263832f, 0.133493021f, 0.130194828f, 0.126240104f, 0.123071767f, 0.121281922f, + 0.119557180f, 0.117016964f, 0.114773229f, 0.114072219f, 0.114103459f, 0.113414355f, 0.112460621f, 0.112842396f, 0.114564091f, + 0.115944758f, 0.116569765f, 0.117913686f, 0.120910525f, 0.124211200f, 0.126575813f, 0.128826424f, 0.132578567f, 0.137430578f, + 0.141675219f, 0.144987956f, 0.148879051f, 0.154273912f, 0.159992099f, 0.164641231f, 0.168560207f, 0.173201621f, 0.178906262f, + 0.184429348f, 0.188756809f, 0.192309171f, 0.196154252f, 0.200732291f, 0.205381230f, 0.209404662f, 0.212832779f, 0.216197237f, + 0.220162451f, 0.225029215f, 0.230637416f, 0.236752108f, 0.243243530f, 0.249900997f, 0.256293535f, 0.261716694f, 0.265186161f, + 0.265652657f, 0.262010813f, 0.253508776f, 0.243198514f, 0.244490802f, 0.255167097f, 0.258825988f, 0.257396817f, 0.256197631f, + 0.256865948f, 0.258354962f, 0.259370565f, 0.259730458f, 0.259894609f, 0.260285556f, 0.260970831f, 0.261650831f, 0.262020200f, + 0.262095064f, 0.262225062f, 0.262741268f, 0.263585031f, 0.264350951f, 0.264654577f, 0.264539272f, 0.264409125f, 0.264633715f, + 0.265172601f, 0.265621960f, 0.265678704f, 0.265469313f, 0.265454412f, 0.265907466f, 0.266625792f, 0.267101586f, 0.266997635f, + 0.266522497f, 0.266185820f, 0.266298562f, 0.266692907f, 0.266907692f +}; + +const float orange53_right_avg_power[257] = { + 0.999231100f, 0.992580175f, 0.969233215f, 0.925614893f, 0.871408045f, 0.826101780f, 0.803222895f, 0.800087631f, 0.802672029f, + 0.801490188f, 0.796555817f, 0.790879488f, 0.784882724f, 0.777585745f, 0.769326210f, 0.761789441f, 0.756145239f, 0.752754092f, + 0.751703024f, 0.752594173f, 0.754317880f, 0.755515277f, 0.754378498f, 0.748860359f, 0.738919020f, 0.727488697f, 0.718792558f, + 0.714865267f, 0.713446736f, 0.711076498f, 0.706021905f, 0.697553098f, 0.684623063f, 0.667031527f, 0.647006035f, 0.627680719f, + 0.609939933f, 0.592472672f, 0.574803054f, 0.558499217f, 0.544599831f, 0.532128096f, 0.520152628f, 0.509682238f, 0.501904130f, + 0.496162385f, 0.491121918f, 0.486813396f, 0.483951330f, 0.482198298f, 0.480713189f, 0.479654074f, 0.479590476f, 0.479965866f, + 0.479589254f, 0.478181243f, 0.476334095f, 0.474199444f, 0.471616089f, 0.469089746f, 0.467486322f, 0.466943622f, 0.467153549f, + 0.468381166f, 0.470996737f, 0.474416614f, 0.477639019f, 0.480612457f, 0.483910263f, 0.487287015f, 0.489909321f, 0.491668850f, + 0.493155539f, 0.494319856f, 0.494512051f, 0.493615031f, 0.492155492f, 0.490116775f, 0.486886710f, 0.482303619f, 0.476902038f, + 0.470775038f, 0.463377595f, 0.454571068f, 0.445130944f, 0.435581058f, 0.425568998f, 0.414717495f, 0.403531373f, 0.392556936f, + 0.381436378f, 0.369506508f, 0.357099295f, 0.345049500f, 0.333368897f, 0.321326375f, 0.308959186f, 0.297232091f, 0.286592871f, + 0.276453108f, 0.266589880f, 0.257950366f, 0.251341701f, 0.246435612f, 0.242861211f, 0.241405189f, 0.242839754f, 0.246688128f, + 0.252115428f, 0.259297341f, 0.268399984f, 0.278481483f, 0.288520366f, 0.298599035f, 0.308846802f, 0.318350822f, 0.326248646f, + 0.332813978f, 0.338464528f, 0.342543274f, 0.344278336f, 0.344031811f, 0.342641503f, 0.339995682f, 0.335437506f, 0.329174429f, + 0.322237372f, 0.315035462f, 0.306967229f, 0.297821850f, 0.288482070f, 0.279766560f, 0.271234214f, 0.262228251f, 0.253214896f, + 0.245183259f, 0.237939596f, 0.230546176f, 0.223051578f, 0.216552779f, 0.211263061f, 0.206180066f, 0.200917527f, 0.196485907f, + 0.193453044f, 0.190857053f, 0.187853232f, 0.185171053f, 0.183685005f, 0.182665780f, 0.180928215f, 0.178784713f, 0.177342966f, + 0.176323384f, 0.174430951f, 0.171496049f, 0.168740034f, 0.166518897f, 0.163711995f, 0.159658119f, 0.155442193f, 0.152056932f, + 0.148795277f, 0.144545168f, 0.139905334f, 0.136263832f, 0.133493021f, 0.130194828f, 0.126240104f, 0.123071767f, 0.121281922f, + 0.119557180f, 0.117016964f, 0.114773229f, 0.114072219f, 0.114103459f, 0.113414355f, 0.112460621f, 0.112842396f, 0.114564091f, + 0.115944758f, 0.116569765f, 0.117913686f, 0.120910525f, 0.124211200f, 0.126575813f, 0.128826424f, 0.132578567f, 0.137430578f, + 0.141675219f, 0.144987956f, 0.148879051f, 0.154273912f, 0.159992099f, 0.164641231f, 0.168560207f, 0.173201621f, 0.178906262f, + 0.184429348f, 0.188756809f, 0.192309171f, 0.196154252f, 0.200732291f, 0.205381230f, 0.209404662f, 0.212832779f, 0.216197237f, + 0.220162451f, 0.225029215f, 0.230637416f, 0.236752108f, 0.243243530f, 0.249900997f, 0.256293535f, 0.261716694f, 0.265186161f, + 0.265652657f, 0.262010813f, 0.253508776f, 0.243198514f, 0.244490802f, 0.255167097f, 0.258825988f, 0.257396817f, 0.256197631f, + 0.256865948f, 0.258354962f, 0.259370565f, 0.259730458f, 0.259894609f, 0.260285556f, 0.260970831f, 0.261650831f, 0.262020200f, + 0.262095064f, 0.262225062f, 0.262741268f, 0.263585031f, 0.264350951f, 0.264654577f, 0.264539272f, 0.264409125f, 0.264633715f, + 0.265172601f, 0.265621960f, 0.265678704f, 0.265469313f, 0.265454412f, 0.265907466f, 0.266625792f, 0.267101586f, 0.266997635f, + 0.266522497f, 0.266185820f, 0.266298562f, 0.266692907f, 0.266907692f +}; + +const float orange53_coherence[257] = { + 0.929530263f, 0.921171963f, 0.900268972f, 0.876067519f, 0.855227590f, 0.837884128f, 0.823401272f, 0.818804145f, 0.835025251f, + 0.871971071f, 0.911253273f, 0.929330528f, 0.921199203f, 0.900894165f, 0.882577479f, 0.867001534f, 0.849280477f, 0.832460761f, + 0.824062645f, 0.823441386f, 0.820908070f, 0.811902404f, 0.802339375f, 0.798648477f, 0.797345281f, 0.791158736f, 0.779512227f, + 0.768243194f, 0.760565042f, 0.754912853f, 0.751044095f, 0.752276063f, 0.759258866f, 0.766927004f, 0.769716740f, 0.767338514f, + 0.763358235f, 0.759508014f, 0.755201221f, 0.750362694f, 0.746060252f, 0.742611766f, 0.739434779f, 0.736354828f, 0.733443379f, + 0.730109870f, 0.726028502f, 0.722365141f, 0.720153689f, 0.718220115f, 0.714793265f, 0.710619092f, 0.708084404f, 0.707218647f, + 0.705624878f, 0.702472746f, 0.700073540f, 0.699947894f, 0.700519860f, 0.699934483f, 0.699344158f, 0.700895131f, 0.704551995f, + 0.708814025f, 0.713567019f, 0.719995975f, 0.728467822f, 0.738399088f, 0.749545693f, 0.761859894f, 0.774593413f, 0.787218869f, + 0.800481200f, 0.814727187f, 0.828367889f, 0.839860320f, 0.850490928f, 0.862034321f, 0.873037636f, 0.880097568f, 0.883217216f, + 0.885473788f, 0.887664974f, 0.886511028f, 0.880120754f, 0.871120989f, 0.862524390f, 0.853262126f, 0.840783834f, 0.825854301f, + 0.811407208f, 0.798167706f, 0.784307659f, 0.769172490f, 0.754072189f, 0.739893615f, 0.726129174f, 0.712544501f, 0.699519753f, + 0.686980069f, 0.674778104f, 0.663931608f, 0.655511260f, 0.648816824f, 0.642671287f, 0.638217211f, 0.637585819f, 0.640332758f, + 0.643755615f, 0.647433281f, 0.653589368f, 0.662824631f, 0.672268033f, 0.680022597f, 0.687623680f, 0.696763635f, 0.705829978f, + 0.712574661f, 0.717432320f, 0.721986175f, 0.725707173f, 0.727064371f, 0.726255059f, 0.724350274f, 0.720927835f, 0.715189219f, + 0.708206475f, 0.701428175f, 0.693923056f, 0.684313059f, 0.674107075f, 0.666009307f, 0.659245491f, 0.650998116f, 0.641600072f, + 0.634524226f, 0.630267978f, 0.625348687f, 0.618164837f, 0.611785769f, 0.608430445f, 0.605561733f, 0.600407422f, 0.594782710f, + 0.591767371f, 0.590365708f, 0.587845862f, 0.584915996f, 0.584355533f, 0.585834682f, 0.586913347f, 0.587935925f, 0.591403484f, + 0.596784472f, 0.601111054f, 0.604539037f, 0.610374093f, 0.618451059f, 0.624519289f, 0.627448440f, 0.631859899f, 0.639748096f, + 0.646256745f, 0.647378445f, 0.647664309f, 0.652599990f, 0.659044445f, 0.659743190f, 0.656243205f, 0.656651020f, 0.662200928f, + 0.664544880f, 0.660030127f, 0.656303048f, 0.659881413f, 0.664978266f, 0.662953973f, 0.657274961f, 0.658065319f, 0.665406108f, + 0.668446958f, 0.663809955f, 0.661349833f, 0.668595374f, 0.677367866f, 0.677208483f, 0.672289610f, 0.675831020f, 0.688208520f, + 0.695776582f, 0.691749871f, 0.687812865f, 0.696674168f, 0.711764693f, 0.716045380f, 0.706839681f, 0.701565385f, 0.711955190f, + 0.726487696f, 0.723370016f, 0.700417101f, 0.677427649f, 0.670733511f, 0.671355724f, 0.654210806f, 0.608316183f, 0.549225986f, + 0.504217446f, 0.484227657f, 0.475346446f, 0.452598959f, 0.399407327f, 0.319485664f, 0.229244962f, 0.146649837f, 0.083417825f, + 0.041744832f, 0.018142883f, 0.006854009f, 0.002511850f, 0.001177550f, 0.000840970f, 0.000701097f, 0.000571384f, 0.000458581f, + 0.000376965f, 0.000320562f, 0.000278847f, 0.000245546f, 0.000218281f, 0.000195632f, 0.000176647f, 0.000160827f, 0.000147978f, + 0.000137649f, 0.000129066f, 0.000121431f, 0.000114406f, 0.000108067f, 0.000102595f, 0.000097917f, 0.000093750f, 0.000089854f, + 0.000086255f, 0.000083183f, 0.000080804f, 0.000079026f, 0.000077552f, 0.000076117f, 0.000074693f, 0.000073431f, 0.000072456f, + 0.000071701f, 0.000071002f, 0.000070286f, 0.000069692f, 0.000069457f +}; + +/*----------------------------------------------------------------------------------* + * t-design and SN3D normalization table + *----------------------------------------------------------------------------------*/ + + /* SN3D norm */ +const float norm_sn3d_hoa3[16] = +{ + 1.f, 1.7320508f, 1.7320508f, 1.7320508f, 2.2360680f, 2.2360680f, 2.2360680f, 2.2360680f, + 2.2360680f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f, 2.6457512f +}; + +/* Order 11 t-design */ +const uint16_t t_design_11_size = 70; + +const float t_design_11_azimuth[70] = +{ + 1.329273e+02f, -8.393495e+01f, 8.474100e+00f, -1.133408e+02f, -1.032659e+02f, -3.323704e+01f, 2.185643e+01f, -1.565395e+02f, + -6.426475e+01f, 1.657795e+02f, -2.520283e+01f, -9.700380e+01f, 2.785464e+01f, 1.532142e+02f, -1.550616e+02f, -1.184214e+01f, + 8.053873e+01f, -4.205616e+01f, -3.122333e+01f, 3.883790e+01f, 9.376069e+01f, -8.475602e+01f, 7.755368e+00f, -1.222769e+02f, + 4.680127e+01f, -2.476863e+01f, 9.989047e+01f, -1.347840e+02f, -8.308802e+01f, 6.012817e+01f, 1.526447e+02f, 2.975767e+01f, + 4.077932e+01f, 1.101839e+02f, 1.656521e+02f, -1.299266e+01f, 7.973599e+01f, -5.052453e+01f, 1.189239e+02f, 4.722029e+01f, + 1.719253e+02f, -6.251458e+01f, -1.111567e+01f, 1.320180e+02f, -1.353555e+02f, 1.023709e+02f, 1.127393e+02f, -1.783050e+02f, + -1.223199e+02f, 5.907635e+01f, 1.517042e+02f, 2.137634e+01f, -1.690055e+02f, 1.189808e+02f, -1.160893e+02f, 9.647679e+00f, + 6.089332e+01f, -1.560215e+02f, -6.346030e+01f, 1.749298e+02f, -1.752888e+02f, -1.059519e+02f, -5.019283e+01f, 1.313583e+02f, + -1.362968e+02f, 9.356446e+01f, -9.708401e+01f, -1.691583e+02f, -4.413238e+01f, 8.147954e+01f +}; + +const float t_design_11_elevation[70] = +{ + 7.692547e+00f, -2.373007e+01f, 2.351276e+01f, 7.042259e+01f, -9.896944e+00f, -7.075133e+01f, -2.646185e+01f, 4.777649e+01f, + -7.720470e+00f, 4.453436e+01f, 2.638979e+01f, -4.465789e+01f, 9.767035e+00f, -4.770533e+01f, 7.453029e+00f, -2.359012e+01f, + 2.371945e+01f, 7.043827e+01f, -9.835416e+00f, -7.049808e+01f, -2.629492e+01f, 4.761480e+01f, -7.517185e+00f, 4.428623e+01f, + 2.664426e+01f, -4.456937e+01f, 9.912719e+00f, -4.795996e+01f, 7.296799e+00f, -2.334460e+01f, 2.364153e+01f, 7.068431e+01f, + -9.581404e+00f, -7.039345e+01f, -2.642582e+01f, 4.775107e+01f, -7.308536e+00f, 4.426328e+01f, 2.671406e+01f, -4.431497e+01f, + 9.758997e+00f, -4.803619e+01f, 7.439651e+00f, -2.333261e+01f, 2.338690e+01f, 7.082191e+01f, -9.485964e+00f, -7.058019e+01f, + -2.667403e+01f, 4.799784e+01f, -7.382762e+00f, 4.449706e+01f, 2.650250e+01f, -4.424619e+01f, 9.518451e+00f, -4.782814e+01f, + 7.684274e+00f, -2.357068e+01f, 2.330745e+01f, 7.065865e+01f, -9.680889e+00f, -7.080268e+01f, -2.669635e+01f, 4.801363e+01f, + -7.637348e+00f, 4.466512e+01f, 2.630235e+01f, -4.445764e+01f, 9.523415e+00f, -4.762422e+01f +}; + + +/*----------------------------------------------------------------------* +* Reverberator ROM tables +*-----------------------------------------------------------------------*/ + +const float ivas_reverb_default_fc[IVAS_REVERB_DEFAULT_N_BANDS] = +{ + 20.0f, 25.0f, 31.5f, 40.0f, + 50.0f, 63.0f, 80.0f, 100.0f, + 125.0f, 160.0f, 200.0f, 250.0f, + 315.0f, 400.0f, 500.0f, 630.0f, + 800.0f, 1000.0f, 1250.0f, 1600.0f, + 2000.0f, 2500.0f, 3150.0f, 4000.0f, + 5000.0f, 6300.0f, 8000.0f, 10000.0f, + 12500.0f, 16000.0f, 20000.0f +}; + +const float ivas_reverb_default_RT60[IVAS_REVERB_DEFAULT_N_BANDS] = +{ + 1.3622f, 1.4486f, 1.3168f, 1.5787f, + 1.4766f, 1.3954f, 1.2889f, 1.3462f, + 1.0759f, 1.0401f, 1.097f, 1.085f, + 1.091f, 1.0404f, 1.0499f, 1.0699f, + 1.1028f, 1.1714f, 1.1027f, 1.0666f, + 1.055f, 1.0553f, 1.0521f, 1.0569f, + 1.0421f, 0.97822f, 0.80487f, 0.75944f, + 0.71945f, 0.61682f, 0.60031f +}; + +const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = +{ + 1.8811e-08f, 2.1428e-08f, 1.3972e-08f, 1.51e-08f, + 1.287e-08f, 1.8747e-08f, 2.413e-08f, 3.9927e-08f, + 8.9719e-08f, 1.902e-07f, 3.702e-07f, 6.1341e-07f, + 7.1432e-07f, 6.5331e-07f, 4.6094e-07f, 5.4683e-07f, + 7.0134e-07f, 6.856e-07f, 7.114e-07f, 6.9604e-07f, + 5.2939e-07f, 5.699e-07f, 6.1773e-07f, 5.7488e-07f, + 4.7748e-07f, 2.7213e-07f, 1.3681e-07f, 1.0941e-07f, + 6.2001e-08f, 2.8483e-08f, 2.6267e-08f +}; + +/*----------------------------------------------------------------------------------* + * Renderer SBA & MC enc/dec matrices + *----------------------------------------------------------------------------------*/ + +/* CICP1 - Mono */ +const float ls_azimuth_CICP1[1] = { 0.0f }; +const float ls_elevation_CICP1[1] = { 0.0f }; + + + +/*----------------------------------------------------------------------------------* + * LS Renderer ROM tables + *----------------------------------------------------------------------------------*/ + + /* All matrices are stored with dimensions nchan_in x nchan_out */ + /* Downmix matrices */ +const float ls_conversion_cicpX_mono[12][1] = +{ + {1.00000000f}, + {1.00000000f}, + {1.00000000f}, + {1.00000000f}, + {0.79999995f}, + {0.79999995f}, + {0.79999995f}, + {0.79999995f}, + {0.849999964f}, + {0.849999964f}, + {0.849999964f}, + {0.849999964f} +}; + +const float ls_conversion_cicpX_stereo[12][2] = +{ + {1.00000000f, 0.00000000f}, + {0.00000000f, 1.00000000f}, + {0.70710677f, 0.70710677f}, + {0.70710677f, 0.70710677f}, + {0.79999995f, 0.00000000f}, + {0.00000000f, 0.79999995f}, + {0.79999995f, 0.00000000f}, + {0.00000000f, 0.79999995f}, + {0.849999964f, 0.000000000f}, + {0.000000000f, 0.849999964f}, + {0.849999964f, 0.000000000f}, + {0.000000000f, 0.849999964f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp6[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {8, 6.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {7, 1.000000000f}, + {14, 1.000000000f}, + {21, 1.000000000f}, + {28, 1.000000000f}, + {35, 1.000000000f}, + {40, 1.000000000f}, + {47, 1.000000000f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp14_cicp6[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {8, 6.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {7, 1.000000000f}, + {14, 1.000000000f}, + {21, 1.000000000f}, + {28, 1.000000000f}, + {35, 1.000000000f}, + {36, 0.849999964f}, + {43, 0.849999964f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp14_cicp12[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {8, 8.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {9, 1.000000000f}, + {18, 1.000000000f}, + {27, 1.000000000f}, + {36, 1.000000000f}, + {45, 1.000000000f}, + {48, 0.849999964f}, + {57, 0.849999964f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp6[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {10, 6.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {7, 1.000000000f}, + {14, 1.000000000f}, + {21, 1.000000000f}, + {28, 1.000000000f}, + {35, 1.000000000f}, + {36, 0.849999964f}, + {43, 0.849999964f}, + {52, 0.849999964f}, + {59, 0.849999964f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp12[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {10, 8.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {9, 1.000000000f}, + {18, 1.000000000f}, + {27, 1.000000000f}, + {36, 1.000000000f}, + {45, 1.000000000f}, + {48, 0.849999964f}, + {57, 0.849999964f}, + {68, 0.849999964f}, + {77, 0.849999964f} + +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp14[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {10, 8.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {9, 1.000000000f}, + {18, 1.000000000f}, + {27, 1.000000000f}, + {36, 1.000000000f}, + {45, 1.000000000f}, + {54, 1.000000000f}, + {63, 1.000000000f}, + {68, 0.849999964f}, + {77, 0.849999964f}, +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp6[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {14, 6.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {7, 1.000000000f}, + {14, 1.000000000f}, + {21, 1.000000000f}, + {28, 1.000000000f}, + {35, 1.000000000f}, + {36, 0.367322683f}, + {40, 0.930093586f}, + {43, 0.367322683f}, + {47, 0.930093586f}, + {48, 0.849999964f}, + {55, 0.849999964f}, + {64, 0.849999964f}, + {71, 0.849999964f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp12[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {14, 8.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {9, 1.000000000f}, + {18, 1.000000000f}, + {27, 1.000000000f}, + {38, 1.000000000f}, + {47, 1.000000000f}, + {48, 0.367322683f}, + {52, 0.930093586f}, + {57, 0.367322683f}, + {61, 0.930093586f}, + {64, 0.849999964f}, + {73, 0.849999964f}, + {84, 0.849999964f}, + {93, 0.849999964f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp14[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {14, 8.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {9, 1.000000000f}, + {18, 1.000000000f}, + {27, 1.000000000f}, + {36, 1.000000000f}, + {45, 1.000000000f}, + {48, 0.367322683f}, + {52, 0.930093586f}, + {57, 0.367322683f}, + {61, 0.930093586f}, + {70, 1.000000000f}, + {79, 1.000000000f}, + {84, 0.849999964f}, + {93, 0.849999964f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp19_cicp16[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {14, 10.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.000000000f}, + {11, 1.000000000f}, + {22, 1.000000000f}, + {33, 1.000000000f}, + {44, 1.000000000f}, + {55, 1.000000000f}, + {60, 0.367322683f}, + {64, 0.930093586f}, + {71, 0.367322683f}, + {75, 0.930093586f}, + {86, 1.000000000f}, + {97, 1.000000000f}, + {108, 1.000000000f}, + {119, 1.000000000f} +}; + +/* Upmix matrices */ +const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp14[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {8, 8.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.0f}, + {9, 1.0f}, + {18, 1.0f}, + {27, 1.0f}, + {36, 1.0f}, + {45, 1.0f}, + {52, 1.0f}, + {61, 1.0f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp16[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {8, 10.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.0f}, + {11, 1.0f}, + {22, 1.0f}, + {33, 1.0f}, + {44, 1.0f}, + {55, 1.0f}, + {64, 1.0f}, + {75, 1.0f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp12_cicp19[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {8, 12.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.0f}, + {13, 1.0f}, + {26, 1.0f}, + {39, 1.0f}, + {54, 1.0f}, + {67, 1.0f}, + {76, 1.0f}, + {89, 1.0f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp14_cicp19[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {8, 12.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.0f}, + {13, 1.0f}, + {26, 1.0f}, + {39, 1.0f}, + {52, 1.0f}, + {65, 1.0f}, + {80, 1.0f}, + {93, 1.0f} +}; + +const LS_CONVERSION_MATRIX ls_conversion_cicp16_cicp19[] = +{ + /* First row indicates the number of non-zero elements and the number of matrix columns */ + {10, 12.0f}, + /* Index of non-zero element, value of non-zero element*/ + {0, 1.0f}, + {13, 1.0f}, + {26, 1.0f}, + {39, 1.0f}, + {52, 1.0f}, + {65, 1.0f}, + {80, 1.0f}, + {93, 1.0f}, + {106, 1.0f}, + {119, 1.0f} +}; + +/* + * Mapping table of input config : output config with corresponding matrix + * NULL indicates a 1:1 mapping of existing input channels to output channels ( used for upmix ) + */ + +const LS_CONVERSION_MAPPING ls_conversion_mapping[LS_SETUP_CONVERSION_NUM_MAPPINGS] = +{ + /* Dowmix mappings - NULL is a special case for MONO / STEREO downmix */ + {AUDIO_CONFIG_5_1, AUDIO_CONFIG_MONO, NULL}, + {AUDIO_CONFIG_7_1, AUDIO_CONFIG_MONO, NULL}, + {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_MONO, NULL}, + {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_MONO, NULL}, + {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_MONO, NULL}, + + {AUDIO_CONFIG_5_1, AUDIO_CONFIG_STEREO, NULL}, + {AUDIO_CONFIG_7_1, AUDIO_CONFIG_STEREO, NULL}, + {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_STEREO, NULL}, + {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_STEREO, NULL}, + {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_STEREO, NULL}, + + {AUDIO_CONFIG_7_1, AUDIO_CONFIG_5_1, ls_conversion_cicp12_cicp6}, + + {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_5_1, ls_conversion_cicp14_cicp6}, + {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_7_1, ls_conversion_cicp14_cicp12}, + + {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_5_1, ls_conversion_cicp16_cicp6}, + {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_7_1, ls_conversion_cicp16_cicp12}, + {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_5_1_2, ls_conversion_cicp16_cicp14}, + + {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_5_1, ls_conversion_cicp19_cicp6}, + {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_7_1, ls_conversion_cicp19_cicp12}, + {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_5_1_2, ls_conversion_cicp19_cicp14}, + {AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_5_1_4, ls_conversion_cicp19_cicp16}, + + /* Upmix mappings - NULL implies a 1:1 upmix */ + {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_5_1, NULL}, + {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_7_1, NULL}, + {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_5_1_2, NULL}, + {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_5_1_4, NULL}, + {AUDIO_CONFIG_STEREO, AUDIO_CONFIG_7_1_4, NULL}, + + {AUDIO_CONFIG_5_1, AUDIO_CONFIG_7_1, NULL}, + {AUDIO_CONFIG_5_1, AUDIO_CONFIG_5_1_2, NULL}, + {AUDIO_CONFIG_5_1, AUDIO_CONFIG_5_1_4, NULL}, + {AUDIO_CONFIG_5_1, AUDIO_CONFIG_7_1_4, NULL}, + + {AUDIO_CONFIG_7_1, AUDIO_CONFIG_5_1_2, ls_conversion_cicp12_cicp14}, + {AUDIO_CONFIG_7_1, AUDIO_CONFIG_5_1_4, ls_conversion_cicp12_cicp16}, + {AUDIO_CONFIG_7_1, AUDIO_CONFIG_7_1_4, ls_conversion_cicp12_cicp19}, + + {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_5_1_4, NULL}, + {AUDIO_CONFIG_5_1_2, AUDIO_CONFIG_7_1_4, ls_conversion_cicp14_cicp19}, + + {AUDIO_CONFIG_5_1_4, AUDIO_CONFIG_7_1_4, ls_conversion_cicp16_cicp19}, +}; + +/* clang-format on */ diff --git a/lib_rend/ivas_rom_rend.h b/lib_rend/ivas_rom_rend.h new file mode 100644 index 0000000000000000000000000000000000000000..c4e1ca153378923382ba84c162635b4b10d3bd17 --- /dev/null +++ b/lib_rend/ivas_rom_rend.h @@ -0,0 +1,122 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#ifndef IVAS_ROM_REND_H +#define IVAS_ROM_REND_H + +#include "options.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "ivas_cnst.h" +#include "ivas_stat_rend.h" + +/*----------------------------------------------------------------------------------* + * FASTCONV and PARAMETRIC binaural renderer ROM tables + *----------------------------------------------------------------------------------*/ + +extern const int16_t channelIndex_CICP6[5]; +extern const int16_t channelIndex_CICP12[7]; +extern const int16_t channelIndex_CICP14[7]; +extern const int16_t channelIndex_CICP16[9]; +extern const int16_t channelIndex_CICP19[11]; + +/* These are equalization values for spread and surround coherent sounds, approximating the spectrum + * for such sounds at anechoic multichannel listening. */ +extern const float surCohEne[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; +extern const float spreadCohEne05[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; +extern const float spreadCohEne1[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; + +/* Values for low-bit-rate equalization */ +extern const float lowBitRateBinauralEQ[LOW_BIT_RATE_BINAURAL_EQ_BINS]; + +/* Diffuse field binaural coherence directional adjustment values */ +extern const float diffuseFieldCoherenceDifferenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS]; +extern const float diffuseFieldCoherenceDifferenceY[BINAURAL_COHERENCE_DIFFERENCE_BINS]; +extern const float diffuseFieldCoherenceDifferenceZ[BINAURAL_COHERENCE_DIFFERENCE_BINS]; + + +/*----------------------------------------------------------------------------------* + * TD ISM Object renderer + *----------------------------------------------------------------------------------*/ + +extern const int16_t HRTF_MODEL_N_CPTS_VAR[HRTF_MODEL_N_SECTIONS]; + +extern const float SincTable[321]; + +extern const float orange53_left_avg_power[257]; +extern const float orange53_right_avg_power[257]; +extern const float orange53_coherence[257]; + + +/*----------------------------------------------------------------------------------* + * t-design and SN3D normalization table + *----------------------------------------------------------------------------------*/ + +/* SN3D norm */ +extern const float norm_sn3d_hoa3[16]; + +/* Order 11 t-design */ +extern const uint16_t t_design_11_size; +extern const float t_design_11_azimuth[70]; +extern const float t_design_11_elevation[70]; + + +/*----------------------------------------------------------------------* + * Reverberator ROM tables + *-----------------------------------------------------------------------*/ + +extern const float ivas_reverb_default_fc[]; +extern const float ivas_reverb_default_RT60[]; +extern const float ivas_reverb_default_DSR[]; + +/*----------------------------------------------------------------------------------* + * Renderer SBA & MC enc/dec matrices + *----------------------------------------------------------------------------------*/ + +extern const float ls_azimuth_CICP1[1]; +extern const float ls_elevation_CICP1[1]; + + +/*----------------------------------------------------------------------------------* + * LS Configuration Converter ROM tables + *----------------------------------------------------------------------------------*/ + +/* Downmix matrices */ +extern const float ls_conversion_cicpX_mono[12][1]; +extern const float ls_conversion_cicpX_stereo[12][2]; + +/* Mapping table of input config : output config with corresponding matrix */ +extern const LS_CONVERSION_MAPPING ls_conversion_mapping[]; + +#endif /* IVAS_ROM_REND_H */ diff --git a/lib_dec/ivas_rotation.c b/lib_rend/ivas_rotation.c similarity index 79% rename from lib_dec/ivas_rotation.c rename to lib_rend/ivas_rotation.c index 77809d8270e9e2b30a50800b5052fc2b696d827b..58536df19f343eff092a44f56a2f31d3b15c6739 100644 --- a/lib_dec/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,36 +30,18 @@ *******************************************************************************************************/ +#include "ivas_cnst.h" #include #include #include "options.h" #include #include "cnst.h" #include "prot.h" -#include "ivas_prot.h" -#include "ivas_cnst.h" -#include "ivas_rom_com.h" -#include "ivas_rom_dec.h" +#include "ivas_prot_rend.h" #ifdef DEBUGGING #include "debug.h" #endif -#include "wmops.h" - - -/*-----------------------------------------------------------------------* - * Local Constants - *-----------------------------------------------------------------------*/ - -#define HEADROT_ORDER 3 -#define HEADROT_SHMAT_DIM ( HEADROT_ORDER + 1 ) * ( HEADROT_ORDER + 1 ) -#define HEADROT_SHMAT_DIM2 HEADROT_SHMAT_DIM *HEADROT_SHMAT_DIM - - -/*-----------------------------------------------------------------------* - * Local Function prototypes - *-----------------------------------------------------------------------*/ - -static void SHrotmatgen( float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM], float Rmat[3][3], const int16_t order ); +#include "wmc_auto.h" /*-----------------------------------------------------------------------* @@ -73,9 +55,10 @@ ivas_error ivas_headTrack_open( ) { int16_t i; + ivas_error error; /* Allocate Head-Tracking handle */ - if ( ( *hHeadTrackData = (HEAD_TRACK_DATA_HANDLE) count_malloc( sizeof( HEAD_TRACK_DATA ) ) ) == NULL ) + if ( ( *hHeadTrackData = (HEAD_TRACK_DATA_HANDLE) malloc( sizeof( HEAD_TRACK_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for head-tracking memory\n" ) ); } @@ -85,6 +68,15 @@ ivas_error ivas_headTrack_open( ( *hHeadTrackData )->lrSwitchInterpVal = 0.0f; ( *hHeadTrackData )->lrSwitchedCurrent = 0; ( *hHeadTrackData )->lrSwitchedNext = 0; + if ( ( ( *hHeadTrackData )->OrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" ); + } + + if ( ( error = ivas_orient_trk_Init( ( *hHeadTrackData )->OrientationTracker ) ) != IVAS_ERR_OK ) + { + return error; + } /* Initialise Rmat_prev to I, Rmat will be computed later */ for ( i = 0; i < 3; i++ ) @@ -93,115 +85,127 @@ ivas_error ivas_headTrack_open( ( *hHeadTrackData )->Rmat_prev[i][i] = 1.0f; } +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS_OPT + set_zero( ( *hHeadTrackData )->chEneIIR[0], MASA_FREQUENCY_BANDS ); + set_zero( ( *hHeadTrackData )->chEneIIR[1], MASA_FREQUENCY_BANDS ); + set_zero( ( *hHeadTrackData )->procChEneIIR[0], MASA_FREQUENCY_BANDS ); + set_zero( ( *hHeadTrackData )->procChEneIIR[1], MASA_FREQUENCY_BANDS ); +#else + set_zero( ( *hHeadTrackData )->chEneIIR[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( ( *hHeadTrackData )->chEneIIR[1], CLDFB_NO_CHANNELS_MAX ); + set_zero( ( *hHeadTrackData )->procChEneIIR[0], CLDFB_NO_CHANNELS_MAX ); + set_zero( ( *hHeadTrackData )->procChEneIIR[1], CLDFB_NO_CHANNELS_MAX ); +#endif +#endif + return IVAS_ERR_OK; } -/*---------------------------------------------------------------------------------- - * QuatToRotMat() +/*-----------------------------------------------------------------------* + * ivas_headTrack_close() * - * Quaternion handling: calculate rotation matrices in real-space and SHD - *---------------------------------------------------------------------------------*/ + * Deallocate Head-Tracking handle + *-----------------------------------------------------------------------*/ -void QuatToRotMat( - const Quaternion quat, /* i : quaternion describing the rotation */ - float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ +void ivas_headTrack_close( + HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* i/o: head track handle */ ) { - float s1, s2, s3, c1, c2, c3; -#ifdef DEBUGGING - /* PrintQuat( quat ); */ -#endif + if ( hHeadTrackData == NULL || *hHeadTrackData == NULL ) + { + return; + } - /* For debugging purposes we can also calculate the rotation matrix from - * Euler angles instead of quaternions. In this case, all the w values must - * be set to -3.0 in the trajectory file to signal switching to Euler angles. - * The x,y, and z components of the quaternion are then interpreted as - * yaw-pitch-roll. - */ - if ( quat.w != -3.0 ) + if ( ( *hHeadTrackData )->OrientationTracker != NULL ) { - Rmat[0][0] = quat.w * quat.w + quat.x * quat.x - quat.y * quat.y - quat.z * quat.z; - Rmat[0][1] = 2.0f * ( quat.x * quat.y - quat.w * quat.z ); - Rmat[0][2] = 2.0f * ( quat.x * quat.z + quat.w * quat.y ); + free( ( *hHeadTrackData )->OrientationTracker ); + ( *hHeadTrackData )->OrientationTracker = NULL; + } - Rmat[1][0] = 2.0f * ( quat.x * quat.y + quat.w * quat.z ); - Rmat[1][1] = quat.w * quat.w - quat.x * quat.x + quat.y * quat.y - quat.z * quat.z; - Rmat[1][2] = 2.0f * ( quat.y * quat.z - quat.w * quat.x ); + free( ( *hHeadTrackData ) ); + *hHeadTrackData = NULL; - Rmat[2][0] = 2.0f * ( quat.x * quat.z - quat.w * quat.y ); - Rmat[2][1] = 2.0f * ( quat.y * quat.z + quat.w * quat.x ); - Rmat[2][2] = quat.w * quat.w - quat.x * quat.x - quat.y * quat.y + quat.z * quat.z; - } - else - { - /* Euler angles in R_X(roll)*R_Y(pitch)*R_Z(yaw) convention - * - * yaw: rotate scene counter-clockwise in the horizontal plane - * pitch: rotate scene in the median plane, increase elevation with positive values - * roll: rotate scene from the right ear to the top - */ + return; +} - c1 = cosf( quat.z / _180_OVER_PI ); - c2 = cosf( quat.y / _180_OVER_PI ); - c3 = cosf( quat.x / _180_OVER_PI ); - s1 = sinf( quat.z / _180_OVER_PI ); - s2 = sinf( -quat.y / _180_OVER_PI ); - s3 = sinf( quat.x / _180_OVER_PI ); +/*---------------------------------------------------------------------------------- + * QuatToRotMat() + * + * Quaternion handling: calculate rotation matrices in real-space and SHD + *---------------------------------------------------------------------------------*/ - Rmat[0][0] = c2 * c3; - Rmat[0][1] = -c2 * s3; - Rmat[0][2] = s2; +void QuatToRotMat( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ +) +{ + Rmat[0][0] = quat.w * quat.w + quat.x * quat.x - quat.y * quat.y - quat.z * quat.z; + Rmat[0][1] = 2.0f * ( quat.x * quat.y - quat.w * quat.z ); + Rmat[0][2] = 2.0f * ( quat.x * quat.z + quat.w * quat.y ); - Rmat[1][0] = c1 * s3 + c3 * s1 * s2; - Rmat[1][1] = c1 * c3 - s1 * s2 * s3; - Rmat[1][2] = -c2 * s1; + Rmat[1][0] = 2.0f * ( quat.x * quat.y + quat.w * quat.z ); + Rmat[1][1] = quat.w * quat.w - quat.x * quat.x + quat.y * quat.y - quat.z * quat.z; + Rmat[1][2] = 2.0f * ( quat.y * quat.z - quat.w * quat.x ); - Rmat[2][0] = s1 * s3 - c1 * c3 * s2; - Rmat[2][1] = c3 * s1 + c1 * s2 * s3; - Rmat[2][2] = c1 * c2; - } + Rmat[2][0] = 2.0f * ( quat.x * quat.z - quat.w * quat.y ); + Rmat[2][1] = 2.0f * ( quat.y * quat.z + quat.w * quat.x ); + Rmat[2][2] = quat.w * quat.w - quat.x * quat.x - quat.y * quat.y + quat.z * quat.z; return; } + /*------------------------------------------------------------------------- - * Quat2Euler() + * Euler2Quat() * - * Quaternion handling: calculate corresponding Euler angles + * Calculate corresponding Quaternion from Euler angles in radians *------------------------------------------------------------------------*/ -void Quat2Euler( - const Quaternion quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ +void Euler2Quat( + const float yaw, /* i : yaw (x) */ + const float pitch, /* i : pitch (y) */ + const float roll, /* i : roll (z) */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ ) { - if ( quat.w != -3.0 ) + float cr = cosf( roll * 0.5f ); + float sr = sinf( roll * 0.5f ); + float cp = cosf( pitch * 0.5f ); + float sp = sinf( -pitch * 0.5f ); + float cy = cosf( yaw * 0.5f ); + float sy = sinf( yaw * 0.5f ); + + quat->w = cr * cp * cy - sr * sp * sy; + quat->x = sr * cp * cy + cr * sp * sy; + quat->y = cr * sp * cy - sr * cp * sy; + quat->z = cr * cp * sy + sr * sp * cy; + + return; +} + +/*------------------------------------------------------------------------- + * deg2rad() + * + * Converts degrees to normalized radians + *------------------------------------------------------------------------*/ +float deg2rad( + float degrees ) +{ + while ( degrees >= 180.0f ) { - *yaw = atan2f( 2 * ( quat.w * quat.x + quat.y * quat.z ), 1 - 2 * ( quat.x * quat.x + quat.y * quat.y ) ); - *pitch = asinf( 2 * ( quat.w * quat.y - quat.z * quat.x ) ); - *roll = atan2f( 2 * ( quat.w * quat.z + quat.x * quat.y ), 1 - 2 * ( quat.y * quat.y + quat.z * quat.z ) ); + degrees = degrees - 360.0f; } - else + while ( degrees <= -180.0f ) { - /* Euler angles in R_X(roll)*R_Y(pitch)*R_Z(yaw) convention - * - * yaw: rotate scene counter-clockwise in the horizontal plane - * pitch: rotate scene in the median plane, increase elevation with positive values - * roll: rotate scene from the right ear to the top - */ - *yaw = quat.z; - *pitch = quat.y; - *roll = quat.x; + degrees = degrees + 360.0f; } - return; + return PI_OVER_180 * degrees; } - /*------------------------------------------------------------------------- * rotateAziEle() * @@ -248,51 +252,6 @@ void rotateAziEle( } -/*------------------------------------------------------------------------- - * rotateAziEle_DirAC() - * - * Apply rotation to DirAC DOAs - *------------------------------------------------------------------------*/ - -void rotateAziEle_DirAC( - int16_t *azi, /* i/o: array of azimuth values */ - int16_t *ele, /* i/o: array of elevation values */ - const int16_t band1, /* i : bands to work on (lower limit) */ - const int16_t band2, /* i : bands to work on (upper bound) */ - const float *p_Rmat /* i : pointer to real-space rotation matrix */ -) -{ - int16_t b; - float dv_0, dv_1, dv_2; - float dv_r_0, dv_r_1, dv_r_2; - float w; - - wmops_sub_start( "rotateAziEle_DirAC" ); - - for ( b = band1; b < band2; b++ ) - { - - /*Conversion spherical to cartesian coordinates*/ - w = cosf( ele[b] * PI_OVER_180 ); - dv_0 = w * cosf( azi[b] * PI_OVER_180 ); - dv_1 = w * sinf( azi[b] * PI_OVER_180 ); - dv_2 = sinf( ele[b] * PI_OVER_180 ); - - dv_r_0 = p_Rmat[0] * dv_0 + p_Rmat[1] * dv_1 + p_Rmat[2] * dv_2; - dv_r_1 = p_Rmat[3] * dv_0 + p_Rmat[4] * dv_1 + p_Rmat[5] * dv_2; - dv_r_2 = p_Rmat[6] * dv_0 + p_Rmat[7] * dv_1 + p_Rmat[8] * dv_2; - - /*Conversion spherical to cartesian coordinates*/ - azi[b] = (int16_t) ( atan2f( dv_r_1, dv_r_0 ) * _180_OVER_PI ); - ele[b] = (int16_t) ( atan2f( dv_r_2, sqrtf( dv_r_0 * dv_r_0 + dv_r_1 * dv_r_1 ) ) * _180_OVER_PI ); - } - - wmops_sub_end(); - - return; -} - - /*------------------------------------------------------------------------- * rotateFrame_shd() * @@ -302,7 +261,6 @@ void rotateAziEle_DirAC( void rotateFrame_shd( HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ float output[][L_FRAME48k], /* i/o: unrotated HOA3 signal buffer in TD */ - const int32_t output_fs, /* i : output sampling frequency */ const int16_t subframe_len, /* i : subframe length per channel */ const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ const int16_t subframe_idx /* i : subframe index */ @@ -310,22 +268,20 @@ void rotateFrame_shd( { int16_t i, l, n, m; int16_t m1, m2; - int16_t shd_rot_max_order, fade_len_smp; + int16_t shd_rot_max_order; float tmp; float tmpRot[2 * HEADROT_ORDER + 1]; float SHrotmat_prev[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM]; float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM]; - float cross_fade[IVAS_FB_1MS_48K_SAMP]; + float cross_fade[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; shd_rot_max_order = hTransSetup.ambisonics_order; - /* 1ms linear crossfade */ - fade_len_smp = NS2SA( output_fs, 1000000 ); - tmp = 1.0f / fade_len_smp; - for ( i = 0; i < fade_len_smp; i++ ) + tmp = 1.0f / ( subframe_len - 1 ); + for ( i = 0; i < subframe_len; i++ ) { - cross_fade[i] = ( i + 1 ) * tmp; + cross_fade[i] = i * tmp; } /* initialize rotation matrices with zeros */ @@ -360,14 +316,7 @@ void rotateFrame_shd( for ( m = m1; m < m2; m++ ) { /* crossfade with previous rotation gains */ - if ( i < fade_len_smp ) - { - tmpRot[n - m1] += cross_fade[i] * SHrotmat[n][m] * output[m][subframe_idx * subframe_len + i] + ( 1 - cross_fade[i] ) * SHrotmat_prev[n][m] * output[m][subframe_idx * subframe_len + i]; - } - else - { - tmpRot[n - m1] += SHrotmat[n][m] * output[m][subframe_idx * subframe_len + i]; - } + tmpRot[n - m1] += cross_fade[i] * SHrotmat[n][m] * output[m][subframe_idx * subframe_len + i] + ( 1 - cross_fade[i] ) * SHrotmat_prev[n][m] * output[m][subframe_idx * subframe_len + i]; } } /* write back the result */ @@ -415,7 +364,6 @@ void rotateFrame_shd( void rotateFrame_sd( HEAD_TRACK_DATA_HANDLE hHeadTrackData, /* i : head track handle */ float output[][L_FRAME48k], /* i/o: unrotated SD signal buffer in TD */ - const int32_t output_Fs, /* i : output sampling frequency */ const int16_t subframe_len, /* i : subframe length per channel */ const IVAS_OUTPUT_SETUP hTransSetup, /* i : format for rotation */ const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ @@ -426,26 +374,23 @@ void rotateFrame_sd( int16_t nchan, index_lfe; int16_t ch_in, ch_in_woLFE, ch_out, ch_out_woLFE; int16_t azimuth, elevation; - int16_t fade_len_smp; float tmp; float tmp_gains[MAX_CICP_CHANNELS - 1]; float gains[MAX_CICP_CHANNELS][MAX_CICP_CHANNELS]; float gains_prev[MAX_CICP_CHANNELS][MAX_CICP_CHANNELS]; float output_tmp[MAX_CICP_CHANNELS][L_FRAME48k]; - float cross_fade[IVAS_FB_1MS_48K_SAMP]; + float cross_fade[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - wmops_sub_start( "rotateFrame_sd" ); + push_wmops( "rotateFrame_sd" ); nchan = hTransSetup.nchan_out_woLFE + hTransSetup.num_lfe; index_lfe = hTransSetup.index_lfe[0]; - /* 1ms linear crossfade */ - fade_len_smp = NS2SA( output_Fs, 1000000 ); - tmp = 1.0f / fade_len_smp; - for ( i = 0; i < fade_len_smp; i++ ) + tmp = 1.0f / ( subframe_len - 1 ); + for ( i = 0; i < subframe_len; i++ ) { - cross_fade[i] = ( i + 1 ) * tmp; + cross_fade[i] = i * tmp; } /* Get next quaternion and calculate rotation matrix */ @@ -473,7 +418,7 @@ void rotateFrame_sd( /* gains for previous subframe rotation */ rotateAziEle( hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], &azimuth, &elevation, hHeadTrackData->Rmat_prev, hTransSetup.is_planar_setup ); - if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth && hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) ) + if ( hEFAPdata != NULL && ( hTransSetup.ls_azimuth[ch_in_woLFE] != azimuth || hTransSetup.ls_elevation[ch_in_woLFE] != elevation ) ) { efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP ); for ( ch_out = 0; ch_out < nchan; ch_out++ ) @@ -520,14 +465,10 @@ void rotateFrame_sd( for ( ch_in = 0; ch_in < nchan; ch_in++ ) { /* crossfade with previous rotation gains */ - for ( i = subframe_idx * subframe_len, j = 0; j < fade_len_smp; i++, j++ ) + for ( i = subframe_idx * subframe_len, j = 0; j < subframe_len; i++, j++ ) { output_tmp[ch_out][i] += ( cross_fade[j] ) * gains[ch_in][ch_out] * output[ch_in][i] + ( 1 - cross_fade[j] ) * gains_prev[ch_in][ch_out] * output[ch_in][i]; } - for ( ; i < ( subframe_idx + 1 ) * subframe_len; i++ ) - { - output_tmp[ch_out][i] += gains[ch_in][ch_out] * output[ch_in][i]; - } } } @@ -543,7 +484,7 @@ void rotateFrame_sd( mvr2r( &output_tmp[ch_out][subframe_idx * subframe_len], &output[ch_out][subframe_idx * subframe_len], subframe_len ); } - wmops_sub_end(); + pop_wmops(); return; } @@ -669,7 +610,7 @@ void rotateFrame_sd_cldfb( int16_t nInChannels; int16_t isPlanar; - wmops_sub_start( "rotateFrame_sd_cldfb" ); + push_wmops( "rotateFrame_sd_cldfb" ); nInChannels = hOutputSetup->nchan_out_woLFE; isPlanar = 1; @@ -748,7 +689,7 @@ void rotateFrame_sd_cldfb( } } } - wmops_sub_end(); + pop_wmops(); return; } @@ -819,14 +760,13 @@ static float SHrot_v( float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] ) { - float d = 0.0f; - float p0 = 0.0f, p1 = 0.0f; + float result, d, p0, p1; if ( m == 0 ) { p0 = SHrot_p( 1, l, 1, n, SHrotmat, R_lm1 ); p1 = SHrot_p( -1, l, -1, n, SHrotmat, R_lm1 ); - return p0 + p1; + result = p0 + p1; } else { @@ -835,16 +775,18 @@ static float SHrot_v( d = ( m == 1 ) ? 1.0f : 0.0f; p0 = SHrot_p( 1, l, m - 1, n, SHrotmat, R_lm1 ); p1 = SHrot_p( -1, l, -m + 1, n, SHrotmat, R_lm1 ); - return p0 * sqrtf( 1.0f + d ) - p1 * ( 1.0f - d ); + result = p0 * sqrtf( 1.0f + d ) - p1 * ( 1.0f - d ); } else { d = ( m == -1 ) ? 1.0f : 0.0f; p0 = SHrot_p( 1, l, m + 1, n, SHrotmat, R_lm1 ); p1 = SHrot_p( -1, l, -m - 1, n, SHrotmat, R_lm1 ); - return p0 * ( 1.0f - d ) + p1 * sqrtf( 1.0f + d ); + result = p0 * ( 1.0f - d ) + p1 * sqrtf( 1.0f + d ); } } + + return result; } static float SHrot_w( @@ -854,13 +796,12 @@ static float SHrot_w( float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM], float R_lm1[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM] ) { - float p0 = 0.0f; - float p1 = 0.0f; + float result, p0, p1; if ( m == 0 ) { printf( "ERROR should not be called\n" ); - return 0.0; + return 0.0f; } else { @@ -868,18 +809,27 @@ static float SHrot_w( { p0 = SHrot_p( 1, l, m + 1, n, SHrotmat, R_lm1 ); p1 = SHrot_p( -1, l, -m - 1, n, SHrotmat, R_lm1 ); - return p0 + p1; + result = p0 + p1; } else { p0 = SHrot_p( 1, l, m - 1, n, SHrotmat, R_lm1 ); p1 = SHrot_p( -1, l, -m + 1, n, SHrotmat, R_lm1 ); - return p0 - p1; + result = p0 - p1; } } + + return result; } -static void SHrotmatgen( + +/*------------------------------------------------------------------------- + * rotateFrame_sd_cldfb() + * + * + *------------------------------------------------------------------------*/ + +void SHrotmatgen( float SHrotmat[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM], /* o : rotation matrix in SHD */ float Rmat[3][3], /* i : real-space rotation matrix */ const int16_t order /* i : ambisonics order */ diff --git a/lib_rend/ivas_sba_rendering.c b/lib_rend/ivas_sba_rendering.c new file mode 100644 index 0000000000000000000000000000000000000000..8fd10d83ba3b261a3874eed9065197fbca20ab3a --- /dev/null +++ b/lib_rend/ivas_sba_rendering.c @@ -0,0 +1,204 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_stat_dec.h" +#include "ivas_cnst.h" +#include +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * ivas_sba_prototype_renderer() + * + * Render prototype audio signals using SBA mixing matrices + *-------------------------------------------------------------------*/ + +void ivas_sba_prototype_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder struct */ + float inRe[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, real */ + float inIm[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : Input audio in CLDFB domain, imag */ + const int16_t firstSubframe, /* i : First subframe to map */ + const int16_t nSubframes /* i : Number of subframes to map */ +) +{ + float mixer_mat[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; + SPAR_DEC_HANDLE hSpar; + DECODER_CONFIG_HANDLE hDecoderConfig; + int16_t num_spar_bands, spar_band; + int16_t b, ts; + int16_t num_cldfb_bands, numch_in, numch_out; + int16_t cldfb_band; + int16_t out_ch, in_ch; + int16_t firstSlot, slotEnd, firstInCh, inChEnd, firstOutCh, outChEnd; + int16_t sf_idx; + + push_wmops( "ivas_sba_prototype_renderer" ); + + hSpar = st_ivas->hSpar; + hDecoderConfig = st_ivas->hDecoderConfig; + num_spar_bands = hSpar->hFbMixer->pFb->filterbank_num_bands; + + firstSlot = firstSubframe * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); + slotEnd = ( firstSubframe + nSubframes ) * ( CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES ); + + num_cldfb_bands = hSpar->hFbMixer->pFb->fb_bin_to_band.num_cldfb_bands; + numch_in = hSpar->hFbMixer->fb_cfg->num_in_chans; + numch_out = hSpar->hFbMixer->fb_cfg->num_out_chans; + + if ( st_ivas->nchan_transport == 1 ) + { + firstInCh = 0; + inChEnd = 1; + firstOutCh = 0; + outChEnd = 1; + } + else /* 2 TC */ + { + firstInCh = 0; + inChEnd = 2; + firstOutCh = 1; + outChEnd = 2; + } + + /* Apply mixing matrix */ + for ( ts = firstSlot; ts < slotEnd; ts++ ) + { + /* determine SPAR parameters for this time slot */ + ivas_spar_get_parameters( hSpar, hDecoderConfig, ts, numch_out, numch_in, num_spar_bands, mixer_mat ); + + for ( cldfb_band = 0; cldfb_band < num_cldfb_bands; cldfb_band++ ) + { + float out_re[IVAS_SPAR_MAX_CH]; + float out_im[IVAS_SPAR_MAX_CH]; + float cldfb_par; + ivas_fb_bin_to_band_data_t *bin2band = &hSpar->hFbMixer->pFb->fb_bin_to_band; + + for ( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ ) + { + out_re[out_ch] = 0.0f; + out_im[out_ch] = 0.0f; + + for ( in_ch = firstInCh; in_ch < inChEnd; in_ch++ ) + { + if ( cldfb_band < CLDFB_PAR_WEIGHT_START_BAND ) /* tuning parameter, depends on how much SPAR Filters overlap for the CLDFB bands */ + { + spar_band = bin2band->p_cldfb_map_to_spar_band[cldfb_band]; + cldfb_par = mixer_mat[out_ch][in_ch][spar_band]; + } + else + { + cldfb_par = 0.0f; + for ( spar_band = bin2band->p_spar_start_bands[cldfb_band]; spar_band < num_spar_bands; spar_band++ ) + { + /* accumulate contributions from all SPAR bands */ + cldfb_par += mixer_mat[out_ch][in_ch][spar_band] * bin2band->pp_cldfb_weights_per_spar_band[cldfb_band][spar_band]; + } + } + + out_re[out_ch] += inRe[in_ch][ts][cldfb_band] * cldfb_par; + out_im[out_ch] += inIm[in_ch][ts][cldfb_band] * cldfb_par; + } + } + + /*update CLDFB data with the parameter-modified data*/ + for ( out_ch = firstOutCh; out_ch < outChEnd; out_ch++ ) + { + inRe[out_ch][ts][cldfb_band] = out_re[out_ch]; + inIm[out_ch][ts][cldfb_band] = out_im[out_ch]; + } + } + + /* Update mixing matrices */ + if ( ( ( ts + 1 ) % MAX_PARAM_SPATIAL_SUBFRAMES ) == 0 ) + { + sf_idx = ts / MAX_PARAM_SPATIAL_SUBFRAMES; + hSpar->i_subframe++; + hSpar->i_subframe = min( hSpar->i_subframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[1][0][0], hSpar->hMdDec->mixer_mat_prev[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[2][0][0], hSpar->hMdDec->mixer_mat_prev[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[3][0][0], hSpar->hMdDec->mixer_mat_prev[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + mvr2r( hSpar->hMdDec->mixer_mat_prev[4][0][0], hSpar->hMdDec->mixer_mat_prev[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS ); + + for ( out_ch = 0; out_ch < numch_out; out_ch++ ) + { + for ( in_ch = 0; in_ch < numch_in; in_ch++ ) + { + for ( b = 0; b < num_spar_bands; b++ ) + { + hSpar->hMdDec->mixer_mat_prev[4][out_ch][in_ch][b] = hSpar->hMdDec->mixer_mat[out_ch][in_ch][b + sf_idx * IVAS_MAX_NUM_BANDS]; + } + } + } + } + } + + /* Create prototypes */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + for ( ts = firstSlot; ts < slotEnd; ts++ ) + { + if ( st_ivas->nchan_transport == 1 ) /* Dual mono */ + { + mvr2r( inRe[0][ts], inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); + mvr2r( inIm[0][ts], inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); + } + else if ( st_ivas->nchan_transport == 2 ) /* Opposing cardioids */ + { + float temp_signal[CLDFB_NO_CHANNELS_MAX]; + + v_add( inRe[0][ts], inRe[1][ts], temp_signal, CLDFB_NO_CHANNELS_MAX ); + v_sub( inRe[0][ts], inRe[1][ts], inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); + mvr2r( temp_signal, inRe[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inRe[0][ts], 0.5f, inRe[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inRe[1][ts], 0.5f, inRe[1][ts], CLDFB_NO_CHANNELS_MAX ); + + v_add( inIm[0][ts], inIm[1][ts], temp_signal, CLDFB_NO_CHANNELS_MAX ); + v_sub( inIm[0][ts], inIm[1][ts], inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); + mvr2r( temp_signal, inIm[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inIm[0][ts], 0.5f, inIm[0][ts], CLDFB_NO_CHANNELS_MAX ); + v_multc( inIm[1][ts], 0.5f, inIm[1][ts], CLDFB_NO_CHANNELS_MAX ); + } + } + } + + pop_wmops(); + + return; +} diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h new file mode 100644 index 0000000000000000000000000000000000000000..e7ff9eb0bafafad55ac6ceb4fc5535955937b0dd --- /dev/null +++ b/lib_rend/ivas_stat_rend.h @@ -0,0 +1,835 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#ifndef IVAS_STAT_REND_H +#define IVAS_STAT_REND_H + +#include +#include "options.h" +#include "ivas_cnst.h" +#include "ivas_stat_com.h" // note: needed for DIRAC_DEC_BIN_HANDLE until #156 is solved +#include "common_api_types.h" + + +/*----------------------------------------------------------------------------------* + * Output configuration for renderer (e.g. DirAC, MASA, Binaural Renderer...) + *----------------------------------------------------------------------------------*/ + +typedef struct ivas_output_setup_structure +{ + AUDIO_CONFIG output_config; + int16_t nchan_out_woLFE; /* number of output audio channels without LFE */ + int16_t ambisonics_order; + int8_t is_loudspeaker_setup; + int8_t is_planar_setup; + int8_t is_binaural_setup; + + int16_t num_lfe; + int16_t index_lfe[1]; + const float *ls_azimuth; + const float *ls_elevation; + + uint8_t separateChannelEnabled; + int16_t separateChannelIndex; + +} IVAS_OUTPUT_SETUP, *IVAS_OUTPUT_SETUP_HANDLE; + + +/*----------------------------------------------------------------------------------* + * Binaural FastConv Rendering structure + *----------------------------------------------------------------------------------*/ + +/* Binaural reverberator structure */ +typedef struct ivas_binaural_reverb_struct +{ + float *loopBufReal[CLDFB_NO_CHANNELS_MAX]; + float *loopBufImag[CLDFB_NO_CHANNELS_MAX]; + float preDelayBufferReal[REVERB_PREDELAY_MAX + 1][CLDFB_NO_CHANNELS_MAX]; + float preDelayBufferImag[REVERB_PREDELAY_MAX + 1][CLDFB_NO_CHANNELS_MAX]; + float **tapPointersReal[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; + float **tapPointersImag[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; + + float binauralCoherenceCrossmixGains[CLDFB_NO_CHANNELS_MAX]; + float binauralCoherenceDirectGains[CLDFB_NO_CHANNELS_MAX]; + float reverbEqGains[CLDFB_NO_CHANNELS_MAX]; + float loopAttenuationFactor[CLDFB_NO_CHANNELS_MAX]; + + float *outputBufferReal[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; + float *outputBufferImag[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; + + int16_t numBins; + + int16_t useBinauralCoherence; + int16_t loopBufLength[CLDFB_NO_CHANNELS_MAX]; + int16_t loopBufLengthMax[CLDFB_NO_CHANNELS_MAX]; + int16_t preDelayBufferIndex; + int16_t preDelayBufferLength; + + int16_t taps[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; + int16_t *tapPhaseShiftType[CLDFB_NO_CHANNELS_MAX][BINAURAL_CHANNELS]; + + int16_t blockSize; + uint32_t binRend_RandNext; + int16_t highestBinauralCoherenceBin; + + float dmxmtx[BINAURAL_CHANNELS][MAX_OUTPUT_CHANNELS]; + float foa_enc[MAX_OUTPUT_CHANNELS][FOA_CHANNELS]; + +} REVERB_STRUCT, *REVERB_STRUCT_HANDLE; + +/* Parametric binaural data structure */ +typedef struct ivas_dirac_dec_binaural_data_structure +{ + float ChEnePrev[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float ChCrossRePrev[CLDFB_NO_CHANNELS_MAX]; + float ChCrossImPrev[CLDFB_NO_CHANNELS_MAX]; + float ChEne[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float ChCrossRe[CLDFB_NO_CHANNELS_MAX]; + float ChCrossIm[CLDFB_NO_CHANNELS_MAX]; + float ChEneOutPrev[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float ChCrossReOutPrev[CLDFB_NO_CHANNELS_MAX]; + float ChCrossImOutPrev[CLDFB_NO_CHANNELS_MAX]; + float ChEneOut[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float ChCrossReOut[CLDFB_NO_CHANNELS_MAX]; + float ChCrossImOut[CLDFB_NO_CHANNELS_MAX]; + float processMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; /* +1 refers to SeparateChannel */ + float processMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; + float processMtxDecRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float processMtxDecIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float diffuseFieldCoherence[CLDFB_NO_CHANNELS_MAX]; + float diffuseFieldCoherenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS]; + float diffuseFieldCoherenceY[BINAURAL_COHERENCE_DIFFERENCE_BINS]; + float diffuseFieldCoherenceZ[BINAURAL_COHERENCE_DIFFERENCE_BINS]; + float earlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; + REVERB_STRUCT_HANDLE hReverb; + uint8_t renderStereoOutputInsteadOfBinaural; + float frameMeanDiffuseness[CLDFB_NO_CHANNELS_MAX]; + float processMtxRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; + float processMtxImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS + 1][CLDFB_NO_CHANNELS_MAX]; + float processMtxDecRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float processMtxDecImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + uint16_t useSubframeMode; /* 0 = process in 20 ms frames, 1 = process in 5 ms subframes */ + uint16_t useTdDecorr; + ivas_td_decorr_state_t *hTdDecorr; +#ifdef NOKIA_PARAMBIN_REQULARIZATION + float reqularizationFactor; +#endif + +} DIRAC_DEC_BIN_DATA, *DIRAC_DEC_BIN_HANDLE; + +typedef struct ivas_binaural_rendering_conv_module_struct +{ + float ***filterTapsLeftReal; + float ***filterTapsLeftImag; + float ***filterTapsRightReal; + float ***filterTapsRightImag; + + float ***filterStatesLeftReal; + float ***filterStatesLeftImag; + + int16_t numTapsArray[BINAURAL_CONVBANDS]; + int16_t numTaps; + +} BINRENDERER_CONV_MODULE, *BINRENDERER_CONV_MODULE_HANDLE; + + +/*----------------------------------------------------------------------------------* + * EFAP structures + *----------------------------------------------------------------------------------*/ + +typedef struct EFAP_VERTEX +{ + float azi; /* azimuth of the loudspeaker */ + float ele; /* elevation of the loudspeaker */ + float pos[3]; /* [x y z] cartesian coordinate vector */ + int16_t idx; /* integer, that corresponds to the first index for the LS in the 1D output */ + int16_t isNaN; /* used to indicate if the vertex is a virtual speaker */ + EFAP_VTX_DMX_TYPE dmxType; /* virtual speaker downmix type */ + +} EFAP_VERTEX; + +typedef struct EFAP_VERTEX_DATA +{ + EFAP_VERTEX *vertexArray; /* Array of vertices */ + int16_t numVtx; /* Number of vertices */ + int16_t *vtxOrder; /* Array that indicates the order of the vertex ranked by increasing azimuth */ + +} EFAP_VERTEX_DATA; + +typedef struct EFAP_POLYSET +{ + int16_t chan[EFAP_MAX_CHAN_NUM]; /* An array indicating the loudspeaker index of the polygon vertices */ + int16_t isNaN[EFAP_MAX_CHAN_NUM]; /* Indicates if one of the vertices isNaN */ + int16_t numChan; /* An integer between 0 and EFAP_MAX_CHAN_NUM corresponding to the number of vertices of the polygon */ + float polyAzi[EFAP_MAX_CHAN_NUM]; /* An array (same length as "chan"), with the azimuth of the channels */ + float polyEle[EFAP_MAX_CHAN_NUM]; /* An array (same length as "chan"), with the elevation of the channels */ + +} EFAP_POLYSET; + +typedef struct EFAP_LS_TRIANGLE +{ + int16_t LS[3]; /* Array indicating the loudspeaker index of the triangle vertices */ + +} EFAP_LS_TRIANGLE; + +typedef struct EFAP_POLYSET_DATA +{ + EFAP_POLYSET polysetArray[EFAP_MAX_POLY_SET]; /* Array of polygons */ + int16_t numPoly; /* Number of polygons */ + EFAP_LS_TRIANGLE triArray[EFAP_MAX_POLY_SET]; /* Array of triangles */ + int16_t numTri; /* Number of triangles */ + +} EFAP_POLYSET_DATA; + +typedef struct EFAP +{ + int16_t numSpk; /* Number of loudspeakers */ + float *aziSpk; /* Loudspeaker azimuths */ + float *eleSpk; /* Loudspeaker elevations */ + EFAP_VERTEX_DATA vtxData; /* Vertex Data, contains all the data concerning the vertex */ + EFAP_POLYSET_DATA polyData; /* Polygon data */ + float **dmTranspose; /* Downmix Matrix used for redistributing the energy of ghosts LS and its transpose */ + float *bufferLong; /* tmp buffer that will be given as a parameter for computing the gain; this is a 1D array of length numVtx */ + float *bufferShort; /* tmp buffer that will be given as a parameter for computing the gain; this is the result of downMixMatrix*bufferLong, length is numSpk */ + int16_t numTot; /* Total number of real + ghost loudspeakers, used later for freeing memory */ + +} EFAP, *EFAP_HANDLE; + +/*----------------------------------------------------------------------------------* + * Orientation tracking structure + *----------------------------------------------------------------------------------*/ + +typedef struct ivas_orient_trk_state_t +{ + OTR_TRACKING_T trackingType; + float centerAdaptationRate; + float offCenterAdaptationRate; + float adaptationAngle; + + float alpha; + IVAS_QUATERNION absAvgRot; /* average absolute orientation */ + IVAS_QUATERNION refRot; /* reference orientation */ + IVAS_QUATERNION trkRot; /* tracked rotation */ + +} ivas_orient_trk_state_t; + +/*----------------------------------------------------------------------------------* + * Head rotation data structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + int8_t headRotEnabled; + IVAS_QUATERNION headPositions[RENDERER_HEAD_POSITIONS_PER_FRAME]; + IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME]; + float crossfade[L_FRAME48k / RENDERER_HEAD_POSITIONS_PER_FRAME]; + ivas_orient_trk_state_t *hOrientationTracker; + +} IVAS_REND_HeadRotData; + +typedef struct ivas_binaural_head_track_struct +{ + int16_t num_quaternions; + IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES]; + IVAS_POSITION Pos[MAX_PARAM_SPATIAL_SUBFRAMES]; + float Rmat[3][3]; + float Rmat_prev[3][3]; + + uint8_t lrSwitchedNext; + uint8_t lrSwitchedCurrent; + float lrSwitchInterpVal; + +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS +#ifdef NOKIA_ADAPTIVE_BINAURAL_PROTOS_OPT + float chEneIIR[2][MASA_FREQUENCY_BANDS]; /* independent of the format. MASA bands are suitable for the task and readily available in ROM. */ + float procChEneIIR[2][MASA_FREQUENCY_BANDS]; +#else + float chEneIIR[2][CLDFB_NO_CHANNELS_MAX]; + float procChEneIIR[2][CLDFB_NO_CHANNELS_MAX]; +#endif +#endif + + int16_t shd_rot_max_order; + ivas_orient_trk_state_t *OrientationTracker; + +} HEAD_TRACK_DATA, *HEAD_TRACK_DATA_HANDLE; + +/*----------------------------------------------------------------------------------* + * Reverberator structure + *----------------------------------------------------------------------------------*/ +/* Reverberator structures */ + + +typedef struct ivas_roomAcoustics_t +{ + int16_t override; + int16_t use_brir; + int16_t late_reverb_on; + int16_t nBands; /* Number of frequency bands for which reverb properties are provided, integer, range [2..256] */ + float pFc_input[CLDFB_NO_CHANNELS_MAX]; /* Center frequencies for which following values are provided: */ + float pAcoustic_rt60[CLDFB_NO_CHANNELS_MAX]; /* - The room's T60 per center frequency */ + float pAcoustic_dsr[CLDFB_NO_CHANNELS_MAX]; /* - The room's Diffuse to Source Ratio per center frequency */ + float acousticPreDelay; /* Time elapsed between input signal and late reverberation start, float, range [0.001..10] */ + float inputPreDelay; /* Offset in seconds from where DSR is computed in the RIR (0 = at source), float, range [0.001..10] */ + +} ivas_roomAcoustics_t; + +typedef struct ivas_render_config_t +{ +#ifdef DEBUGGING + ivas_renderTypeOverride renderer_type_override; +#endif + ivas_roomAcoustics_t roomAcoustics; + float directivity[3]; + +} RENDER_CONFIG_DATA, *RENDER_CONFIG_HANDLE; + +typedef struct ivas_rev_delay_line_t +{ + float *pBuffer; + uint16_t MaxDelay; + int16_t Delay; + uint16_t BufferPos; + float Gain; + +} ivas_rev_delay_line_t; + +typedef struct ivas_rev_iir_filter_t +{ + uint16_t MaxTaps; + uint16_t nr_taps; + uint16_t isFIR; + float Output; + float CoefA[IVAS_REV_MAX_IIR_FILTER_LENGTH]; + float CoefB[IVAS_REV_MAX_IIR_FILTER_LENGTH]; + float pBuffer[IVAS_REV_MAX_IIR_FILTER_LENGTH]; + +} ivas_rev_iir_filter_t; + + +typedef float rv_fftwf_type_complex[2]; /* complex type of fftwf library */ + +/* Convertion block for FFT filter: from time domain to frequency domain (with OLS) and back */ +typedef struct ivas_reverb_t2f_f2t_t +{ + int16_t fft_size; + int16_t log2_fft_size; + int16_t block_size; + int16_t hist_size; /* rv_fft_size - rv_block_size */ + float fft_history_L[RV_FILTER_MAX_HISTORY]; + float fft_history_R[RV_FILTER_MAX_HISTORY]; + +} ivas_reverb_t2f_f2t_t; + +/* FFT filter with its frequency response coefficients */ +typedef struct ivas_reverb_fft_filter_t +{ + int16_t fft_size; + float fft_spectrum[RV_FILTER_MAX_FFT_SIZE]; + +} ivas_reverb_fft_filter_t; + +typedef struct ivas_reverb_state_t +{ + RENDER_CONFIG_DATA pConfig; + + /* input downmixer: */ + float dmx_gain; /* downmix gain */ + + /* predelay: */ + ivas_rev_delay_line_t predelay_line; + float *pPredelay_buffer; + + /* jot reverberator: */ + uint16_t nr_of_branches; /* number of feedback loops */ + ivas_rev_delay_line_t delay_line[IVAS_REV_MAX_NR_BRANCHES]; /* feedback loop delays */ + float *loop_delay_buffer[IVAS_REV_MAX_NR_BRANCHES]; /* feedback loop delay sample buffers */ + ivas_rev_iir_filter_t t60[IVAS_REV_MAX_NR_BRANCHES]; /* feedback loop filters */ + float gain_matrix[IVAS_REV_MAX_NR_BRANCHES][IVAS_REV_MAX_NR_BRANCHES]; /* feedback matrix */ + float mixer[BINAURAL_CHANNELS][IVAS_REV_MAX_NR_BRANCHES]; /* output mixer matrix */ + + /* binauralization filters: */ + int16_t do_corr_filter; + ivas_reverb_t2f_f2t_t fft_filter_ols; + ivas_reverb_fft_filter_t fft_filter_correl_0; + ivas_reverb_fft_filter_t fft_filter_correl_1; + ivas_reverb_fft_filter_t fft_filter_color_0; + ivas_reverb_fft_filter_t fft_filter_color_1; + uint16_t fft_size; /* fft processing size */ + uint16_t fft_subblock_size; /* fft block processing size */ + uint16_t num_fft_subblocks; /* number of fft subblocks */ + uint16_t full_block_size; /* full block processing size */ + +} REVERB_DATA, *REVERB_HANDLE; + + +/*----------------------------------------------------------------------------------* + * TD ISM Object Renderer structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + int16_t modelROM; /* Flag that indicates that the model resides in ROM (controls init/dealloc). */ + int16_t UseItdModel; /* Controls whether ITD model is used. */ + int16_t SplineDegree; /* Degree of the spline functions */ + int16_t K; /* Length of filter */ + int16_t elevDim2; + int16_t elevDim3; + int16_t AlphaN; /* Number of rows in Alpha matrices */ + int16_t num_unique_azim_splines; + int16_t elevSegSamples; + + int16_t elevBsLen[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + int16_t elevBsStart[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + const int16_t *azimDim2; + const int16_t *azimDim3; + const int16_t *azim_start_idx; + const int16_t *azimSegSamples; + const int16_t *azimShapeIdx; + const int16_t *azimShapeSampFactor; + + const float *elevKSeq; /* Array, N x elevDim2 x elevDim3 */ + const float *AlphaL; /* Array, size AlphaN x K */ + const float *AlphaR; /* Array, size AlphaN x K */ + const float *elevBsShape; + float **azimKSeq; /* Array, length azimDim3+1 */ + const float **azimBsShape; + + int16_t azimDim3Max; + int16_t iSecFirst[HRTF_MODEL_N_SECTIONS]; /* Indices for start of sections */ + int16_t iSecLast[HRTF_MODEL_N_SECTIONS]; /* Indices for end of sections */ + const float *EL; /* Array, size (AlphaN*HRTF_MODEL_N_SECTIONS) */ + const float *ER; /* Array, size (AlphaN*HRTF_MODEL_N_SECTIONS) */ + + /* Pointers for allocation of dynamic memory */ + float *AlphaL_dyn; + float *AlphaR_dyn; + float *EL_dyn; + float *ER_dyn; + float *elevBsShape_dyn; + float *elevKSeq_dyn; + int16_t *azimDim2_dyn; + int16_t *azimDim3_dyn; + int16_t *azim_start_idx_dyn; + int16_t *azimSegSamples_dyn; + int16_t *azimShapeIdx_dyn; + int16_t *azimShapeSampFactor_dyn; + float **azimBsShape_dyn; + +} ModelParams_t; + +typedef struct +{ + int16_t N; /* Polynomial degree */ + + int16_t elevDim2; + int16_t elevDim3; + const float *elevKSeq; /* Array, length elevDim3-2 */ + int16_t azimDim2; + int16_t azimDim3; + const float *azimKSeq; /* Array, length azimDim3-2 */ + const float *W; /* Array, size (elevDim3*azimDim3) x K */ + + int16_t azimBsLen[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + int16_t azimBsStart[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + const float *azimBsShape; + int16_t azimSegSamples; + + int16_t elevBsLen[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + int16_t elevBsStart[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + const float *elevBsShape; + int16_t elevSegSamples; + float resamp_factor; + + /* Pointers for allocation of dynamic memory */ + float *elevKSeq_dyn; + float *azimKSeq_dyn; + float *W_dyn; + float *azimBsShape_dyn; + float *elevBsShape_dyn; + +} ModelParamsITD_t; + +typedef struct +{ + float val; + int16_t i; + +} ValueIndex_t; + +/* Shared memory for use when evaluating BSpline HR filter model*/ +typedef struct +{ + float BM[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + ValueIndex_t BMEnergiesL[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + ValueIndex_t BMEnergiesR[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + int16_t UseIndsL[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + int16_t UseIndsR[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + float *hrfModL; + float *hrfModR; + float elevBfVec[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + float azimBfVec[HRTF_MODEL_BSPLINE_NUM_COEFFS][HRTF_MODEL_BSPLINE_NUM_COEFFS]; + float BM_ITD[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; + float elevBfVecITD[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + float azimBfVecITD[HRTF_MODEL_BSPLINE_NUM_COEFFS]; + float itdMod; + +} ModelEval_t; + +/* Mixer listener */ +typedef struct +{ + int16_t PoseUpdated; + float Pos[3]; + float Front[3]; + float Up[3]; + float Right[3]; + + int16_t VelUpdated; + float Vel[3]; + +} TDREND_MIX_Listener_t; + +/* HR filter */ +typedef struct TDREND_HRFILT_FiltSet_struct +{ + int32_t SampleRate; /* Sample rate of the HR filter */ + int16_t NumPos; + int16_t NumElev; + float Dist; + float *ItdSet_p; + int16_t FiltLength; + float *Azim_p; + float *Elev_p; + float *ItdSetNominal_p; + float *LeftFiltSet_p; + float *RightFiltSet_p; + ModelParams_t ModelParams; + ModelEval_t ModelEval; + ModelParamsITD_t ModelParamsITD; + TDREND_HRFILT_Method_t FilterMethod; /* HR filtering method */ + float latency_s; + +} TDREND_HRFILT_FiltSet_t; + +/* Distance attenuation */ +typedef struct +{ + TDREND_DistAttenModel_t DistAttenModel; + float RefDist; + float MaxDist; + float RollOffFactor; + +} TDREND_DistAtten_t; + +/* Directional attenuation */ +typedef struct +{ + float ConeInnerAngle; + float ConeOuterAngle; + float ConeOuterGain; + +} TDREND_DirAtten_t; + +/* Mixer spatial specification */ +typedef struct +{ + int16_t UseCommonDistAttenModel; /* Common distance attenuation model flag */ + TDREND_DistAttenModel_t DistAttenModel; /* Distance attenuation model */ + +} TDREND_MixSpatSpec_t; + +typedef struct TDREND_SRC_REND_s +{ + int16_t InputAvailable; + TDREND_PlayStatus_t PlayStatus; + + /* Gains */ + int16_t SrcGainUpdated; + float SrcGain_p[SPAT_BIN_MAX_INPUT_CHANNELS]; + float SrcGainMin_p[SPAT_BIN_MAX_INPUT_CHANNELS]; + float SrcGainMax_p[SPAT_BIN_MAX_INPUT_CHANNELS]; + float DirGain_p[SPAT_BIN_MAX_INPUT_CHANNELS]; + float DistGain_p[SPAT_BIN_MAX_INPUT_CHANNELS]; +} TDREND_SRC_REND_t; + + +/* Source spatial parameters */ +typedef struct +{ + int16_t Updated; + TDREND_PosType_t PosType; + float Pos_p[3 * SPAT_BIN_MAX_INPUT_CHANNELS]; + float Front_p[3 * SPAT_BIN_MAX_INPUT_CHANNELS]; + int16_t DirAttenEnabled; + TDREND_DirAtten_t DirAtten; + int16_t DistAttenEnabled; + TDREND_DistAtten_t DistAtten; + +} TDREND_SRC_SPATIAL_t; + +typedef struct +{ + float *InputFrame_p; /* Input frame pointer */ + TDREND_SRC_SPATIAL_t *SrcSpatial_p; + TDREND_SRC_REND_t *SrcRend_p; + int16_t itd; + int16_t previtd; + int16_t filterlength; + float mem_itd[ITD_MEM_LEN]; + float hrf_left_prev[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; /* Todo: Should we allocate these buffers with malloc() instead of the maximum length? */ + float hrf_right_prev[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + float azim_prev; + float elev_prev; + float mem_hrf_left[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1]; + float mem_hrf_right[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1]; + float Gain; +} TDREND_SRC_t; + +/* Top level TD binaural renderer handle */ +typedef struct ivas_binaural_td_rendering_struct +{ + TDREND_MixSpatSpec_t *TdRend_MixSpatSpec_p; + TDREND_DirAtten_t *DirAtten_p; + int16_t NumOfSrcs; + int16_t MaxSrcInd; + + TDREND_SRC_t *Sources[MAX_NUM_TDREND_CHANNELS]; + + float Gain; /* Mixer gain */ + TDREND_MIX_Listener_t *Listener_p; /* The virtual listener */ + TDREND_HRFILT_FiltSet_t *HrFiltSet_p; /* HR filter set */ + + int16_t UseCommonDistAttenModel; /* Use common dist atten model (TRUE/FALSE) */ + int16_t DistAttenEnabled; /* (TRUE/FALSE) */ + TDREND_DistAttenModel_t DistAttenModel; /* Common distance attenuation model */ + +} BINAURAL_TD_OBJECT_RENDERER, *BINAURAL_TD_OBJECT_RENDERER_HANDLE; + +typedef struct +{ + int32_t binaural_latency_ns; + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd; + TDREND_HRFILT_FiltSet_t *hHrtfTD; + +} TDREND_WRAPPER, *TDREND_WRAPPER_HANDLE; + + +/*------------------------------------------------------------------------------------------* + * Crend structures + *------------------------------------------------------------------------------------------*/ + +typedef struct ivas_hrtfs_structure +{ + float *pOut_to_bin_re[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS]; + float *pOut_to_bin_im[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS]; + float *pOut_to_bin_diffuse_re[BINAURAL_CHANNELS]; + float *pOut_to_bin_diffuse_im[BINAURAL_CHANNELS]; + float latency_s; + uint16_t num_iterations[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS]; + uint16_t num_iterations_diffuse[BINAURAL_CHANNELS]; + uint16_t *pIndex_frequency_max[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS]; + uint16_t *pIndex_frequency_max_diffuse[BINAURAL_CHANNELS]; + uint16_t index_frequency_max_diffuse; + int16_t max_num_ir; + int16_t max_num_iterations; + float inv_diffuse_weight[MAX_INTERN_CHANNELS]; /* inverse diffuse weights array, access one inverse weight by pInvDiffuseWeight[channel] */ + float gain_lfe; + +} HRTFS_DATA, *HRTFS_HANDLE; + + +/* Main Crend structure */ +typedef struct ivas_crend_state_t +{ + float *freq_buffer_re[MAX_INTERN_CHANNELS]; + float *freq_buffer_im[MAX_INTERN_CHANNELS]; + float *freq_buffer_re_diffuse; + float *freq_buffer_im_diffuse; + float *prev_out_buffer[BINAURAL_CHANNELS]; + float *lfe_delay_line; + float m_fYaw; + float m_fPitch; + float m_fRoll; + ivas_orient_trk_state_t *hTrack; + REVERB_HANDLE hReverb; + int16_t delay_line_rw_index; + int16_t diffuse_delay_line_rw_index; + +} CREND_DATA, *CREND_HANDLE; + +/* Main Crend wrapper structure */ +typedef struct ivas_binaural_crend_wrapper_struct +{ + int32_t binaural_latency_ns; + CREND_HANDLE hCrend; + HRTFS_HANDLE hHrtfCrend; + +} CREND_WRAPPER, *CREND_WRAPPER_HANDLE; + + +/*------------------------------------------------------------------------------------------* + * HRTF structures - htrfs from binary files + *------------------------------------------------------------------------------------------*/ + +typedef struct ivas_hrtfs_crend_structure +{ + HRTFS_DATA *hHRTF_hrir_combined; + HRTFS_DATA *hHRTF_hrir_hoa3; + HRTFS_DATA *hHRTF_brir_combined; + +} HRTFS_CREND, *HRTFS_CREND_HANDLE; + + +/* Fastconv binaural data structure */ + +typedef struct ivas_hrtfs_fastconv_struct +{ + float FASTCONV_HRIR_latency_s; + float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + + float FASTCONV_HOA3_latency_s; + float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + + float FASTCONV_BRIR_latency_s; + float leftBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float leftBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float rightBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float rightBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + + float fastconvReverberationTimes[CLDFB_NO_CHANNELS_MAX]; + float fastconvReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX]; + +} HRTFS_FASTCONV, *HRTFS_FASTCONV_HANDLE; + + +typedef struct ivas_hrtfs_parambin_struct +{ + float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + + float parametricReverberationTimes[CLDFB_NO_CHANNELS_MAX]; + float parametricReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX]; + float parametricEarlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; + +} HRTFS_PARAMBIN, *HRTFS_PARAMBIN_HANDLE; + + +/*----------------------------------------------------------------------------------* + * Limiter structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + int16_t max_num_channels; + int16_t num_channels; + float **channel_ptrs; + int32_t sampling_rate; + float gain; + float release_heuristic; + float attack_constant; + int16_t strong_saturation_count; +#ifdef DEBUGGING + int32_t cnt_frames_limited; /* counter of frames in which the limiter is applied */ +#endif + +} IVAS_LIMITER, *IVAS_LIMITER_HANDLE; + + +/*----------------------------------------------------------------------------------* + * Loudspeaker Configuration Conversion structure + *----------------------------------------------------------------------------------*/ + +typedef struct ivas_LS_setupconversion_struct +{ + float *dmxMtx[MAX_OUTPUT_CHANNELS]; + float *targetEnergyPrev[MAX_OUTPUT_CHANNELS]; + float *dmxEnergyPrev[MAX_OUTPUT_CHANNELS]; + int16_t sfbOffset[MAX_SFB + 2]; + int16_t sfbCnt; + +} LSSETUP_CONVERSION_STRUCT, *LSSETUP_CONVERSION_HANDLE; + + +typedef struct ivas_LS_setupconversion_matrix +{ + int16_t index; + float value; +} LS_CONVERSION_MATRIX; + +typedef struct ivas_LS_setupconversion_mapping +{ + AUDIO_CONFIG input_config; + AUDIO_CONFIG output_config; + const LS_CONVERSION_MATRIX *conversion_matrix; +} LS_CONVERSION_MAPPING; + +typedef struct ivas_mono_downmix_renderer_struct +{ + float inputEnergy[CLDFB_NO_CHANNELS_MAX]; + float protoEnergy[CLDFB_NO_CHANNELS_MAX]; + +} MONO_DOWNMIX_RENDERER_STRUCT, *MONO_DOWNMIX_RENDERER_HANDLE; + + +/*----------------------------------------------------------------------------------* + * Custom Loudspeaker configuration structure + *----------------------------------------------------------------------------------*/ + +typedef struct ivas_LS_setup_custom +{ + int16_t is_planar_setup; /* flag to indicate if setup is planar or not */ + int16_t num_spk; /* number of custom loudspeakers */ + float ls_azimuth[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker azimuths */ + float ls_elevation[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker elevations */ + int16_t num_lfe; /* number of LFE channels */ + int16_t lfe_idx[MAX_OUTPUT_CHANNELS]; /* index for LFE channel insertion */ + int16_t separate_ch_found; /* flag to indicate if a center channel was found */ + float separate_ch_gains[MAX_OUTPUT_CHANNELS]; /* gains to pan McMASA separateChannel in case no center channel is present */ + +} LSSETUP_CUSTOM_STRUCT, *LSSETUP_CUSTOM_HANDLE; + +/* Channel types in a channel-based config */ +typedef enum +{ + CHANNEL_TYPE_UNUSED = 0, + CHANNEL_TYPE_SPEAKER, + CHANNEL_TYPE_LFE +} ChannelType; + +#endif /* IVAS_STAT_REND_H */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c new file mode 100644 index 0000000000000000000000000000000000000000..3d2420632d86ccac487ab5aeb6737bb9afb2631d --- /dev/null +++ b/lib_rend/lib_rend.c @@ -0,0 +1,5666 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "options.h" +#include "lib_rend.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_rend.h" +#include "ivas_cnst.h" +#include "ivas_rom_com.h" +#include "ivas_rom_rend.h" +#include +#include +#include +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +/* Maximum buffer length (per channel) in samples. + * Keep this separate from L_FRAME48k in case we want to support different size later */ +#define MAX_BUFFER_LENGTH_PER_CHANNEL ( L_FRAME48k ) + +/* Maximum buffer length (total) in samples. */ +#define MAX_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) + +/* Frame size required when rendering to binaural */ +#define BINAURAL_RENDERING_FRAME_SIZE_MS 20 + + +/*-------------------------------------------------------------------* + * Local types + *-------------------------------------------------------------------*/ + +typedef float pan_vector[MAX_OUTPUT_CHANNELS]; +typedef float pan_matrix[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; +typedef float rotation_gains[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS]; +typedef float rotation_matrix[3][3]; + +/* EFAP wrapper to simplify writing panning gains to a vector that includes LFE channels */ +typedef struct +{ + EFAP_HANDLE hEfap; + IVAS_REND_AudioConfig speakerConfig; + const LSSETUP_CUSTOM_STRUCT *pCustomLsSetup; /* Pointer to main custom LS struct from renderer handle - doesn't need freeing */ +} EFAP_WRAPPER; + +/* Lightweight helper struct that gathers all information required for rendering + * any config to any other config. Used to simplify signatures of rendering functions. + * + * This struct should store ONLY CONST POINTERS to data existing elsewhere. + * Storing pointers instead of data itself ensures that no additional updates + * are required when any of these are changed in the renderer. Making the pointers + * const ensures that this data is only read, but not modified by the rendering functions. */ +typedef struct +{ + const int32_t *pOutSampleRate; + const IVAS_REND_AudioConfig *pOutConfig; + const LSSETUP_CUSTOM_STRUCT *pCustomLsOut; + const EFAP_WRAPPER *pEfapOutWrapper; + const IVAS_REND_HeadRotData *pHeadRotData; + /* TODO @Philips : would this be a better place to store the render config data? + * bearing in mind we could have multiple inputs to the renderer, we might neeed to accomodate + * multiple rendering configurations unless one global one can be used. If this is not relevant, + * feel free to remove this TODO. + */ +} rendering_context; + +/* Common base for input structs */ +typedef struct +{ + IVAS_REND_AudioConfig inConfig; + IVAS_REND_InputId id; + IVAS_REND_AudioBuffer inputBuffer; + float bufferData[MAX_BUFFER_LENGTH]; + float gain; /* Linear, not in dB */ + rendering_context ctx; + int32_t numNewSamplesPerChannel; /* Used to keep track how much new audio was fed before rendering current frame */ +} input_base; + +typedef struct +{ + input_base base; + IVAS_REND_AudioObjectPosition currentPos; + IVAS_REND_AudioObjectPosition previousPos; + TDREND_WRAPPER tdRendWrapper; + CREND_WRAPPER_HANDLE crendWrapper; + REVERB_HANDLE hReverb; + rotation_matrix rot_mat_prev; +} input_ism; + +typedef struct +{ + int16_t numLfeChannels; + bool pan_lfe; + float lfeInputGain; + float lfeOutputAzimuth; + float lfeOutputElevation; + IVAS_REND_LfePanMtx lfePanMtx; +} lfe_routing; + +typedef struct +{ + input_base base; + + /* Full panning matrix. 1st index is input channel, 2nd index is output channel. + All LFE channels should be included, both for inputs and outputs */ + pan_matrix panGains; + + LSSETUP_CUSTOM_STRUCT customLsInput; + EFAP_WRAPPER efapInWrapper; + TDREND_WRAPPER tdRendWrapper; + CREND_WRAPPER_HANDLE crendWrapper; + REVERB_HANDLE hReverb; + rotation_gains rot_gains_prev; + lfe_routing lfeRouting; +} input_mc; + +typedef struct +{ + input_base base; + pan_matrix hoaDecMtx; + CREND_WRAPPER_HANDLE crendWrapper; + rotation_gains rot_gains_prev; +} input_sba; + +/* Due to API of some rendering methods, the renderer has to use the decoder struct. + Only struct members relevant for rendering will be initialized, therefore typedef as "dummy" decoder struct */ +typedef Decoder_Struct DecoderDummy; + +typedef struct +{ + input_base base; + DecoderDummy *decDummy; + MASA_METADATA_FRAME masaMetadata; + bool metadataHasBeenFed; +} input_masa; + +struct IVAS_REND +{ + int32_t sampleRateOut; + + IVAS_LIMITER_HANDLE hLimiter; +#ifdef DEBUGGING + int32_t numClipping; /* Counter of clipped output samples */ +#endif + + input_ism inputsIsm[RENDERER_MAX_ISM_INPUTS]; + input_mc inputsMc[RENDERER_MAX_MC_INPUTS]; + input_sba inputsSba[RENDERER_MAX_SBA_INPUTS]; + input_masa inputsMasa[RENDERER_MAX_MASA_INPUTS]; + + /* TODO @Philips - inputConfig should not be stored here, but read from e.g. input_mc->input_base.inConfig, please remove this */ + IVAS_REND_AudioConfig inputConfig; + IVAS_REND_AudioConfig outputConfig; + EFAP_WRAPPER efapOutWrapper; + IVAS_LSSETUP_CUSTOM_STRUCT customLsOut; + + IVAS_REND_HeadRotData headRotData; + + int8_t rendererConfigEnabled; + RENDER_CONFIG_DATA *hRendererConfig; /* Renderer config pointer */ +}; + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static IVAS_QUATERNION quaternionInit( + void ) +{ + IVAS_QUATERNION q; + q.w = 1.0f; + q.x = q.y = q.z = 0.0f; + return q; +} + +static float *getSmplPtr( + IVAS_REND_AudioBuffer buffer, + const uint32_t chnlIdx, + const uint32_t smplIdx ) +{ + return buffer.data + chnlIdx * buffer.config.numSamplesPerChannel + smplIdx; +} + +static void copyBufferTo2dArray( + const IVAS_REND_AudioBuffer buffer, + float array[MAX_OUTPUT_CHANNELS][L_FRAME48k] ) +{ + uint32_t smplIdx; + uint32_t chnlIdx; + const float *readPtr; + + readPtr = buffer.data; + + for ( chnlIdx = 0; chnlIdx < (uint32_t) buffer.config.numChannels; ++chnlIdx ) + { + for ( smplIdx = 0; smplIdx < (uint32_t) buffer.config.numSamplesPerChannel; ++smplIdx ) + { + array[chnlIdx][smplIdx] = *readPtr++; + } + } + + return; +} + +static void accumulate2dArrayToBuffer( + float array[MAX_OUTPUT_CHANNELS][L_FRAME48k], + IVAS_REND_AudioBuffer *buffer ) +{ + int16_t smplIdx, chnlIdx; + float *writePtr; + + writePtr = buffer->data; + for ( chnlIdx = 0; chnlIdx < buffer->config.numChannels; ++chnlIdx ) + { + for ( smplIdx = 0; smplIdx < buffer->config.numSamplesPerChannel; ++smplIdx ) + { + *writePtr++ += array[chnlIdx][smplIdx]; + } + } + + return; +} + +/*-------------------------------------------------------------------* + * limitRendererOutput() + * + * In-place saturation control for multichannel buffers with adaptive release time + *-------------------------------------------------------------------*/ + +/*! r: number of clipped output samples */ +static int32_t limitRendererOutput( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + float *output, /* i/o: I/O buffer */ + const int16_t output_frame, /* i : number of samples per channel in the buffer */ + const float threshold /* i : signal amplitude above which limiting starts to be applied */ +) +{ + int16_t i; + float **channels; + int16_t num_channels; + int32_t numClipping = 0; + + /* return early if given bad parameters */ + if ( hLimiter == NULL || output == NULL || output_frame <= 0 ) + { + return 0; + } + + channels = hLimiter->channel_ptrs; + num_channels = hLimiter->num_channels; + + for ( i = 0; i < num_channels; ++i ) + { + channels[i] = output + i * output_frame; + } + + limiter_process( hLimiter, output_frame, threshold, 0, NULL ); + + /* Apply clipping to buffer in case the limiter let through some samples > 1.0f */ + for ( i = 0; i < output_frame * num_channels; ++i ) + { +#ifdef DEBUGGING + if ( output[i] < INT16_MIN || output[i] > INT16_MAX ) + { + ++numClipping; + } +#endif + + output[i] = min( max( INT16_MIN, output[i] ), INT16_MAX ); + } + + return numClipping; +} + + +/*-------------------------------------------------------------------* + * getIvasAudioConfigFromRendAudioConfig() + * + * + *-------------------------------------------------------------------*/ + +AUDIO_CONFIG getIvasAudioConfigFromRendAudioConfig( + IVAS_REND_AudioConfig rendConfig ) +{ + switch ( rendConfig ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + return AUDIO_CONFIG_MONO; + case IVAS_REND_AUDIO_CONFIG_STEREO: + return AUDIO_CONFIG_STEREO; + case IVAS_REND_AUDIO_CONFIG_5_1: + return AUDIO_CONFIG_5_1; + case IVAS_REND_AUDIO_CONFIG_7_1: + return AUDIO_CONFIG_7_1; + case IVAS_REND_AUDIO_CONFIG_5_1_2: + return AUDIO_CONFIG_5_1_2; + case IVAS_REND_AUDIO_CONFIG_5_1_4: + return AUDIO_CONFIG_5_1_4; + case IVAS_REND_AUDIO_CONFIG_7_1_4: + return AUDIO_CONFIG_7_1_4; + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + return AUDIO_CONFIG_LS_CUSTOM; + case IVAS_REND_AUDIO_CONFIG_FOA: + return AUDIO_CONFIG_FOA; + case IVAS_REND_AUDIO_CONFIG_HOA2: + return AUDIO_CONFIG_HOA2; + case IVAS_REND_AUDIO_CONFIG_HOA3: + return AUDIO_CONFIG_HOA3; + case IVAS_REND_AUDIO_CONFIG_OBJECT: + return AUDIO_CONFIG_OBA; + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + return AUDIO_CONFIG_BINAURAL; + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + return AUDIO_CONFIG_BINAURAL_ROOM; + case IVAS_REND_AUDIO_CONFIG_MASA1: + return AUDIO_CONFIG_MASA1; + case IVAS_REND_AUDIO_CONFIG_MASA2: + return AUDIO_CONFIG_MASA2; + default: + break; + } + + return AUDIO_CONFIG_INVALID; +} + +/*-------------------------------------------------------------------* + * getRendAudioConfigFromIvasAudioConfig() + * + * + *-------------------------------------------------------------------*/ + +IVAS_REND_AudioConfig getRendAudioConfigFromIvasAudioConfig( + AUDIO_CONFIG config ) +{ + switch ( config ) + { + case AUDIO_CONFIG_MONO: + return IVAS_REND_AUDIO_CONFIG_MONO; + case AUDIO_CONFIG_STEREO: + return IVAS_REND_AUDIO_CONFIG_STEREO; + case AUDIO_CONFIG_BINAURAL: + return IVAS_REND_AUDIO_CONFIG_BINAURAL; + case AUDIO_CONFIG_BINAURAL_ROOM: + return IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM; + case AUDIO_CONFIG_5_1: + return IVAS_REND_AUDIO_CONFIG_5_1; + case AUDIO_CONFIG_7_1: + return IVAS_REND_AUDIO_CONFIG_7_1; + case AUDIO_CONFIG_5_1_2: + return IVAS_REND_AUDIO_CONFIG_5_1_2; + case AUDIO_CONFIG_5_1_4: + return IVAS_REND_AUDIO_CONFIG_5_1_4; + case AUDIO_CONFIG_7_1_4: + return IVAS_REND_AUDIO_CONFIG_7_1_4; + case AUDIO_CONFIG_FOA: + return IVAS_REND_AUDIO_CONFIG_FOA; + case AUDIO_CONFIG_HOA2: + return IVAS_REND_AUDIO_CONFIG_HOA2; + case AUDIO_CONFIG_HOA3: + return IVAS_REND_AUDIO_CONFIG_HOA3; + default: + break; + } + return IVAS_REND_AUDIO_CONFIG_UNKNOWN; +} + +/*-------------------------------------------------------------------* + * validateOutputAudioConfig() + * + * + *-------------------------------------------------------------------*/ + +static ivas_error validateOutputAudioConfig( + IVAS_REND_AudioConfig outConfig ) +{ + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + case IVAS_REND_AUDIO_CONFIG_STEREO: + case IVAS_REND_AUDIO_CONFIG_5_1: + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_5_1_4: + case IVAS_REND_AUDIO_CONFIG_7_1_4: + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + case IVAS_REND_AUDIO_CONFIG_FOA: + case IVAS_REND_AUDIO_CONFIG_HOA2: + case IVAS_REND_AUDIO_CONFIG_HOA3: + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + return IVAS_ERR_OK; + default: + break; + } + + return IVAS_ERR_INVALID_OUTPUT_FORMAT; +} + + +/*-------------------------------------------------------------------* + * getAudioConfigType() + * + * + *-------------------------------------------------------------------*/ + +IVAS_REND_AudioConfigType getAudioConfigType( + IVAS_REND_AudioConfig config ) +{ + /* By definition, config type is the second byte (from LSB) of IVAS_REND_AudioConfig enum. */ + return ( config & 0xFF00 ) >> 8; +} + + +/*-------------------------------------------------------------------* + * validateOutputSampleRate() + * + * + *-------------------------------------------------------------------*/ + +static ivas_error validateOutputSampleRate( + const int32_t sampleRate, + const IVAS_REND_AudioConfig outConfig ) +{ + if ( getAudioConfigType( outConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) + { + /* If no binaural rendering, any sampling rate is supported */ + return IVAS_ERR_OK; + } + + /* Otherwise rendering to binaural, support the same set as IVAS decoder */ + switch ( sampleRate ) + { + case 8000: + case 16000: + case 32000: + case 48000: + return IVAS_ERR_OK; + } + + return IVAS_ERR_INVALID_SAMPLING_RATE; +} + + +/*-------------------------------------------------------------------* + * getAudioConfigNumChannels() + * + * + *-------------------------------------------------------------------*/ + +ivas_error getAudioConfigNumChannels( + const IVAS_REND_AudioConfig config, + int16_t *numChannels ) +{ + switch ( config ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + case IVAS_REND_AUDIO_CONFIG_OBJECT: + case IVAS_REND_AUDIO_CONFIG_MASA1: + *numChannels = 1; + break; + case IVAS_REND_AUDIO_CONFIG_STEREO: + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + case IVAS_REND_AUDIO_CONFIG_MASA2: + *numChannels = 2; + break; + case IVAS_REND_AUDIO_CONFIG_FOA: + *numChannels = 4; + break; + case IVAS_REND_AUDIO_CONFIG_5_1: + *numChannels = 6; + break; + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + *numChannels = 8; + break; + case IVAS_REND_AUDIO_CONFIG_HOA2: + *numChannels = 9; + break; + case IVAS_REND_AUDIO_CONFIG_5_1_4: + *numChannels = 10; + break; + case IVAS_REND_AUDIO_CONFIG_7_1_4: + *numChannels = 12; + break; + case IVAS_REND_AUDIO_CONFIG_HOA3: + *numChannels = 16; + break; + default: + return IVAS_ERR_NUM_CHANNELS_UNKNOWN; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static ivas_error initLimiter( + IVAS_LIMITER_HANDLE *phLimiter, + const int16_t numChannels, + const int32_t sampleRate ) +{ + /* If re-initializing with unchanged values, return early */ + if ( *phLimiter != NULL && + ( *phLimiter )->num_channels == numChannels && + ( *phLimiter )->sampling_rate == sampleRate ) + { + return IVAS_ERR_OK; + } + + /* Support re-init: close if already allocated */ + if ( *phLimiter != NULL ) + { + ivas_limiter_close( phLimiter ); + } + + if ( ( *phLimiter = ivas_limiter_open( numChannels, sampleRate ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to open limiter handle" ); + } + + return IVAS_ERR_OK; +} + +static LSSETUP_CUSTOM_STRUCT defaultCustomLs( + void ) +{ + LSSETUP_CUSTOM_STRUCT ls; + + /* Set mono by default. This simplifies initialization, + since output config is never in an undefined state. */ + ls.is_planar_setup = 1; + ls.num_spk = 1; + set_zero( ls.ls_azimuth, MAX_OUTPUT_CHANNELS ); + set_zero( ls.ls_elevation, MAX_OUTPUT_CHANNELS ); + ls.num_lfe = 0; + set_s( ls.lfe_idx, 0, MAX_OUTPUT_CHANNELS ); + ls.separate_ch_found = 0; + set_f( ls.separate_ch_gains, 0, MAX_OUTPUT_CHANNELS ); + + return ls; +} + +static ivas_error getSpeakerAzimuths( + IVAS_REND_AudioConfig config, + const float **azimuths ) +{ + switch ( config ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + *azimuths = ls_azimuth_CICP1; + break; + case IVAS_REND_AUDIO_CONFIG_STEREO: + *azimuths = ls_azimuth_CICP2; + break; + case IVAS_REND_AUDIO_CONFIG_5_1: + *azimuths = ls_azimuth_CICP6; + break; + case IVAS_REND_AUDIO_CONFIG_7_1: + *azimuths = ls_azimuth_CICP12; + break; + case IVAS_REND_AUDIO_CONFIG_5_1_2: + *azimuths = ls_azimuth_CICP14; + break; + case IVAS_REND_AUDIO_CONFIG_5_1_4: + *azimuths = ls_azimuth_CICP16; + break; + case IVAS_REND_AUDIO_CONFIG_7_1_4: + *azimuths = ls_azimuth_CICP19; + break; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" ); + } + + return IVAS_ERR_OK; +} + +static ivas_error getSpeakerElevations( + IVAS_REND_AudioConfig config, + const float **elevations ) +{ + switch ( config ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + *elevations = ls_elevation_CICP1; + break; + case IVAS_REND_AUDIO_CONFIG_STEREO: + *elevations = ls_elevation_CICP2; + break; + case IVAS_REND_AUDIO_CONFIG_5_1: + *elevations = ls_elevation_CICP6; + break; + case IVAS_REND_AUDIO_CONFIG_7_1: + *elevations = ls_elevation_CICP12; + break; + case IVAS_REND_AUDIO_CONFIG_5_1_2: + *elevations = ls_elevation_CICP14; + break; + case IVAS_REND_AUDIO_CONFIG_5_1_4: + *elevations = ls_elevation_CICP16; + break; + case IVAS_REND_AUDIO_CONFIG_7_1_4: + *elevations = ls_elevation_CICP19; + break; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" ); + } + + return IVAS_ERR_OK; +} + +static ivas_error getAmbisonicsOrder( + IVAS_REND_AudioConfig config, + int16_t *order ) +{ + switch ( config ) + { + case IVAS_REND_AUDIO_CONFIG_FOA: + *order = 1; + break; + case IVAS_REND_AUDIO_CONFIG_HOA2: + *order = 2; + break; + case IVAS_REND_AUDIO_CONFIG_HOA3: + *order = 3; + break; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported audio config" ); + } + + return IVAS_ERR_OK; +} + +static int16_t getNumLfeChannels( + input_mc *inputMc ) +{ + switch ( inputMc->base.inConfig ) + { + case IVAS_REND_AUDIO_CONFIG_5_1: + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_5_1_4: + case IVAS_REND_AUDIO_CONFIG_7_1_4: + return 1; + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + return inputMc->customLsInput.num_lfe; + default: + break; + } + + return 0; +} + +static ivas_error getNumNonLfeChannelsInSpeakerLayout( + IVAS_REND_AudioConfig config, + int16_t *numNonLfeChannels ) +{ + switch ( config ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + *numNonLfeChannels = 1; + break; + case IVAS_REND_AUDIO_CONFIG_STEREO: + *numNonLfeChannels = 2; + break; + case IVAS_REND_AUDIO_CONFIG_5_1: + *numNonLfeChannels = 5; + break; + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_7_1: + *numNonLfeChannels = 7; + break; + case IVAS_REND_AUDIO_CONFIG_5_1_4: + *numNonLfeChannels = 9; + break; + case IVAS_REND_AUDIO_CONFIG_7_1_4: + *numNonLfeChannels = 11; + break; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" ); + } + + return IVAS_ERR_OK; +} + +static ivas_error getMcConfigValues( + IVAS_REND_AudioConfig inConfig, + LSSETUP_CUSTOM_STRUCT inCustomLs, + const float **azimuth, + const float **elevation, + int16_t *lfe_idx, + int16_t *is_planar ) +{ + int16_t i; + + *lfe_idx = -1; + *is_planar = 1; + switch ( inConfig ) + { + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + *azimuth = (const float *) &inCustomLs.ls_azimuth; + *elevation = (const float *) &inCustomLs.ls_elevation; + if ( inCustomLs.num_lfe > 0 ) + { + *lfe_idx = inCustomLs.lfe_idx[0]; + } + for ( i = 0; i < inCustomLs.num_spk; i++ ) + { + if ( inCustomLs.ls_elevation[i] != 0 ) + { + *is_planar = 0; + break; + } + } + break; + case IVAS_REND_AUDIO_CONFIG_MONO: + case IVAS_REND_AUDIO_CONFIG_STEREO: + getSpeakerAzimuths( inConfig, azimuth ); + getSpeakerElevations( inConfig, elevation ); + break; + case IVAS_REND_AUDIO_CONFIG_5_1: + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_5_1_4: + case IVAS_REND_AUDIO_CONFIG_7_1_4: + getSpeakerAzimuths( inConfig, azimuth ); + getSpeakerElevations( inConfig, elevation ); + *lfe_idx = LFE_CHANNEL; + *is_planar = ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) ? 1 : 0; + break; + default: + assert( !"Invalid speaker config" ); + return IVAS_ERR_WRONG_PARAMS; + } + + return IVAS_ERR_OK; +} + +static ivas_error initEfap( + EFAP_WRAPPER *pEfapWrapper, + IVAS_REND_AudioConfig outConfig, + const LSSETUP_CUSTOM_STRUCT *pCustomLsOut ) +{ + ivas_error error; + const float *azimuths; + const float *elevations; + int16_t numNonLfeChannels; + + if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) + { + pEfapWrapper->speakerConfig = IVAS_REND_AUDIO_CONFIG_7_1_4; + } + else + { + pEfapWrapper->speakerConfig = outConfig; + } + pEfapWrapper->pCustomLsSetup = pCustomLsOut; + + /* If re-initializing, free existing EFAP handle. */ + if ( pEfapWrapper->hEfap != NULL ) + { + efap_free_data( &pEfapWrapper->hEfap ); + } + + /* Only initialize EFAP handle if output config is channel-based */ + if ( getAudioConfigType( pEfapWrapper->speakerConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + pEfapWrapper->hEfap = NULL; + return IVAS_ERR_OK; + } + + if ( outConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = efap_init_data( &pEfapWrapper->hEfap, pCustomLsOut->ls_azimuth, pCustomLsOut->ls_elevation, pCustomLsOut->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = getSpeakerAzimuths( pEfapWrapper->speakerConfig, &azimuths ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getSpeakerElevations( pEfapWrapper->speakerConfig, &elevations ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getNumNonLfeChannelsInSpeakerLayout( pEfapWrapper->speakerConfig, &numNonLfeChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = efap_init_data( &pEfapWrapper->hEfap, azimuths, elevations, numNonLfeChannels, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +static ivas_error getEfapGains( + EFAP_WRAPPER efapWrapper, + const float azi, + const float ele, + pan_vector panGains ) +{ + pan_vector tmpPanGains; /* tmp pan gain buffer without LFE channels */ + float *readPtr; + int16_t i; + int16_t lfeCount; + int16_t numChannels; + ivas_error error; + + /* EFAP returns an array of gains only for non-LFE speakers */ + efap_determine_gains( efapWrapper.hEfap, tmpPanGains, azi, ele, EFAP_MODE_EFAP ); + + /* Now copy to buffer that includes LFE channels */ + if ( efapWrapper.speakerConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + numChannels = efapWrapper.pCustomLsSetup->num_spk + efapWrapper.pCustomLsSetup->num_lfe; + readPtr = tmpPanGains; + + for ( i = 0, lfeCount = 0; i < numChannels; ++i ) + { + if ( lfeCount < efapWrapper.pCustomLsSetup->num_lfe && i == efapWrapper.pCustomLsSetup->lfe_idx[lfeCount] ) + { + panGains[i] = 0.0f; + ++lfeCount; + } + else + { + panGains[i] = *readPtr; + ++readPtr; + } + } + } + else + { + if ( ( error = getAudioConfigNumChannels( efapWrapper.speakerConfig, &numChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + readPtr = tmpPanGains; + + for ( i = 0; i < numChannels; ++i ) + { + if ( i == LFE_CHANNEL ) + { + panGains[i] = 0.0f; + } + else + { + panGains[i] = *readPtr; + ++readPtr; + } + } + } + + return IVAS_ERR_OK; +} + +static ivas_error initHeadRotation( + IVAS_REND_HANDLE hIvasRend ) +{ + int16_t i, crossfade_len; + float tmp; + ivas_error error; + + /* Head rotation is enabled by default */ + hIvasRend->headRotData.headRotEnabled = 1; + + /* Initialize 5ms crossfade */ + crossfade_len = L_FRAME48k / RENDERER_HEAD_POSITIONS_PER_FRAME; + tmp = 1.f / ( crossfade_len - 1 ); + for ( i = 0; i < crossfade_len; i++ ) + { + hIvasRend->headRotData.crossfade[i] = i * tmp; + } + + /* Initialize with unit quaternions */ + for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; ++i ) + { + hIvasRend->headRotData.headPositions[i] = quaternionInit(); + } + + if ( ( hIvasRend->headRotData.hOrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" ); + } + + if ( ( error = ivas_orient_trk_Init( hIvasRend->headRotData.hOrientationTracker ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static void closeHeadRotation( + IVAS_REND_HANDLE hIvasRend ) +{ + if ( ( hIvasRend != NULL ) && ( hIvasRend->headRotData.hOrientationTracker != NULL ) ) + { + free( hIvasRend->headRotData.hOrientationTracker ); + } + + return; +} + +static void initRotMatrix( + rotation_matrix rot_mat ) +{ + int16_t i; + + /* Initialize rotation matrices */ + for ( i = 0; i < 3; i++ ) + { + set_zero( rot_mat[i], 3 ); + rot_mat[i][i] = 1.f; + } + + return; +} + + +static void initRotGains( + rotation_gains rot_gains ) +{ + int16_t i; + /* Set gains to passthrough */ + for ( i = 0; i < MAX_INPUT_CHANNELS; i++ ) + { + set_zero( rot_gains[i], MAX_INPUT_CHANNELS ); + rot_gains[i][i] = 1.f; + } + + return; +} + +static void initRendInputBase( + input_base *inputBase, + const IVAS_REND_AudioConfig inConfig, + const IVAS_REND_InputId id, + const rendering_context rendCtx ) +{ + inputBase->inConfig = inConfig; + inputBase->id = id; + inputBase->gain = 1.0f; + inputBase->ctx = rendCtx; + inputBase->numNewSamplesPerChannel = 0; + + inputBase->inputBuffer.config.numSamplesPerChannel = 0; + inputBase->inputBuffer.config.numChannels = 0; + inputBase->inputBuffer.data = inputBase->bufferData; + + set_zero( inputBase->bufferData, MAX_BUFFER_LENGTH ); + + return; +} + +static IVAS_REND_AudioObjectPosition defaultObjectPosition( + void ) +{ + IVAS_REND_AudioObjectPosition pos; + + pos.azimuth = 0.0f; + pos.elevation = 0.0f; + pos.radius = 1.0f; + pos.yaw = 0.0f; + pos.pitch = 0.0f; + + return pos; +} + +static rendering_context getRendCtx( + IVAS_REND_HANDLE hIvasRend ) +{ + rendering_context ctx; + + /* Note: when refactoring this, always take the ADDRESS of a member of the + * renderer struct, so that the context stores a POINTER to the member, even + * if the member is a pointer or handle itself. */ + ctx.pOutConfig = &hIvasRend->outputConfig; + ctx.pOutSampleRate = &hIvasRend->sampleRateOut; + ctx.pCustomLsOut = &hIvasRend->customLsOut; + ctx.pEfapOutWrapper = &hIvasRend->efapOutWrapper; + ctx.pHeadRotData = &hIvasRend->headRotData; + + return ctx; +} + +static TDREND_WRAPPER defaultTdRendWrapper( + void ) +{ + TDREND_WRAPPER w; + + w.binaural_latency_ns = 0; + w.hBinRendererTd = NULL; + w.hHrtfTD = NULL; + + return w; +} + +static CREND_WRAPPER defaultCrendWrapper( + void ) +{ + CREND_WRAPPER w; + + w.hCrend = NULL; + w.hHrtfCrend = NULL; + w.binaural_latency_ns = 0; + + return w; +} + +static bool isIoConfigPairSupported( + IVAS_REND_AudioConfig inConfig, + IVAS_REND_AudioConfig outConfig ) +{ + /* Rendering mono or stereo to binaural is not supported */ + if ( ( inConfig == IVAS_REND_AUDIO_CONFIG_MONO || inConfig == IVAS_REND_AUDIO_CONFIG_STEREO ) && + getAudioConfigType( outConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) + { + return false; + } + + /* If not returned so far, config pair is supported */ + return true; +} + +static ivas_error setRendInputActiveIsm( + void *input, + const IVAS_REND_AudioConfig inConfig, + const IVAS_REND_InputId id, + RENDER_CONFIG_DATA *hRendCfg ) +{ + ivas_error error; + rendering_context rendCtx; + IVAS_REND_AudioConfig outConfig; + input_ism *inputIsm; + + inputIsm = (input_ism *) input; + rendCtx = inputIsm->base.ctx; + outConfig = *rendCtx.pOutConfig; + + if ( !isIoConfigPairSupported( inConfig, outConfig ) ) + { + return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; + } + + initRendInputBase( &inputIsm->base, inConfig, id, rendCtx ); + + inputIsm->currentPos = defaultObjectPosition(); + inputIsm->previousPos = defaultObjectPosition(); + inputIsm->crendWrapper = NULL; + inputIsm->hReverb = NULL; + inputIsm->tdRendWrapper = defaultTdRendWrapper(); + initRotMatrix( inputIsm->rot_mat_prev ); + + error = IVAS_ERR_OK; + if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL ) + { + if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) + { + if ( hRendCfg != NULL && hRendCfg->roomAcoustics.use_brir == 0 && hRendCfg->roomAcoustics.late_reverb_on ) + { + if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_reverb_open( &( inputIsm->hReverb ), getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, hRendCfg, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_rend_openCrend( &inputIsm->crendWrapper, AUDIO_CONFIG_7_1_4, getIvasAudioConfigFromRendAudioConfig( outConfig ), hRendCfg, + NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + return IVAS_ERR_OK; +} + +static void clearInputIsm( + input_ism *inputIsm ) +{ + rendering_context rendCtx; + + rendCtx = inputIsm->base.ctx; + + initRendInputBase( &inputIsm->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx ); + + /* Free input's internal handles */ + + ivas_rend_closeCrend( &inputIsm->crendWrapper ); + + ivas_reverb_close( &inputIsm->hReverb ); + + if ( inputIsm->tdRendWrapper.hBinRendererTd != NULL ) + { + ivas_td_binaural_close( &inputIsm->tdRendWrapper.hBinRendererTd ); + inputIsm->tdRendWrapper.hHrtfTD = NULL; + } + + return; +} + +static void copyLsConversionMatrixToPanMatrix( + const LS_CONVERSION_MATRIX *lsConvMatrix, + pan_matrix panMatrix ) +{ + int16_t i; + int16_t inCh, outCh; + int16_t numNonZeroGains; + int16_t numColumns; + + /* Index 0 is special and describes the following values */ + numNonZeroGains = lsConvMatrix[0].index; + numColumns = (int16_t) lsConvMatrix[0].value; + + for ( i = 1; i < numNonZeroGains + 1; ++i ) + { + inCh = lsConvMatrix[i].index / numColumns; + outCh = lsConvMatrix[i].index % numColumns; + + panMatrix[inCh][outCh] = lsConvMatrix[i].value; + } + + return; +} + +static void setZeroPanMatrix( + pan_matrix panMatrix ) +{ + int16_t i; + + for ( i = 0; i < MAX_INPUT_CHANNELS; ++i ) + { + set_zero( panMatrix[i], MAX_OUTPUT_CHANNELS ); + } + + return; +} + +/* Note: this only sets non-zero elements, call setZeroPanMatrix() to init first. */ +static void fillIdentityPanMatrix( + pan_matrix panMatrix ) +{ + int16_t i; + + for ( i = 0; i < min( MAX_INPUT_CHANNELS, MAX_OUTPUT_CHANNELS ); ++i ) + { + panMatrix[i][i] = 1.0f; + } + + return; +} + +static ivas_error initMcPanGainsWithIdentMatrix( + input_mc *inputMc ) +{ + fillIdentityPanMatrix( inputMc->panGains ); + + return IVAS_ERR_OK; +} + +static ivas_error initMcPanGainsWithConversionMapping( + input_mc *inputMc, + const IVAS_REND_AudioConfig outConfig ) +{ + AUDIO_CONFIG ivasConfigIn, ivasConfigOut; + int16_t i; + + ivasConfigIn = getIvasAudioConfigFromRendAudioConfig( inputMc->base.inConfig ); + ivasConfigOut = getIvasAudioConfigFromRendAudioConfig( outConfig ); + + /* Find conversion mapping for current I/O config pair. + * Stay with default panning matrix if conversion_matrix is NULL */ + for ( i = 0; i < LS_SETUP_CONVERSION_NUM_MAPPINGS; ++i ) + { + if ( ls_conversion_mapping[i].input_config == ivasConfigIn && ls_conversion_mapping[i].output_config == ivasConfigOut ) + { + /* Mapping found with valid matrix - copy */ + if ( ls_conversion_mapping[i].conversion_matrix != NULL ) + { + copyLsConversionMatrixToPanMatrix( ls_conversion_mapping[i].conversion_matrix, inputMc->panGains ); + } + /* Mapping found with NULL matrix - use identity matrix */ + else + { + fillIdentityPanMatrix( inputMc->panGains ); + } + + return IVAS_ERR_OK; + } + } + + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Missing multichannel conversion mapping" ); +} + +static ivas_error initMcPanGainsWithEfap( + input_mc *inputMc, + const IVAS_REND_AudioConfig outConfig ) +{ + int16_t i; + int16_t numNonLfeInChannels; + int16_t inLfeChIdx, outChIdx; + const float *spkAzi, *spkEle; + ivas_error error; + + if ( inputMc->base.inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = getNumNonLfeChannelsInSpeakerLayout( inputMc->base.inConfig, &numNonLfeInChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getSpeakerAzimuths( inputMc->base.inConfig, &spkAzi ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getSpeakerElevations( inputMc->base.inConfig, &spkEle ) ) != IVAS_ERR_OK ) + { + return error; + } + + inLfeChIdx = LFE_CHANNEL; + } + else + { + numNonLfeInChannels = inputMc->customLsInput.num_spk; + spkAzi = inputMc->customLsInput.ls_azimuth; + spkEle = inputMc->customLsInput.ls_elevation; + inLfeChIdx = -1; + if ( inputMc->customLsInput.num_lfe > 0 ) + { + inLfeChIdx = inputMc->customLsInput.lfe_idx[0]; + } + } + + for ( i = 0, outChIdx = 0; i < numNonLfeInChannels; ++i, ++outChIdx ) + { + if ( i == inLfeChIdx ) + { + ++outChIdx; + } + + if ( ( error = getEfapGains( *inputMc->base.ctx.pEfapOutWrapper, spkAzi[i], spkEle[i], inputMc->panGains[outChIdx] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( outConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM && inLfeChIdx >= 0 ) + { + inputMc->panGains[inLfeChIdx][LFE_CHANNEL] = 1; + } + else if ( inputMc->base.ctx.pCustomLsOut->num_lfe > 0 && inLfeChIdx >= 0 ) + { + inputMc->panGains[inLfeChIdx][inputMc->base.ctx.pCustomLsOut->lfe_idx[0]] = 1; + } + + return IVAS_ERR_OK; +} + +static ivas_error getRendInputNumChannels( + const void *rendInput, + int16_t *numInChannels ) +{ + /* Using a void pointer for this function to be reusable for any input type (input_ism, input_mc, input_sba). + Assumptions: + - input_base is always the first member in the input struct + */ + + ivas_error error; + const input_base *pInputBase; + const input_mc *pInputMc; + + pInputBase = (const input_base *) rendInput; + + if ( pInputBase->inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + pInputMc = (const input_mc *) rendInput; + *numInChannels = pInputMc->customLsInput.num_spk + pInputMc->customLsInput.num_lfe; + } + else + { + if ( ( error = getAudioConfigNumChannels( pInputBase->inConfig, numInChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +static ivas_error initMcPanGainsWithMonoOut( + input_mc *inputMc ) +{ + int16_t i; + int16_t numInChannels; + int16_t readIdx; + int16_t writeIdx; + bool skipSideSpeakers; + ivas_error error; + + if ( ( error = getRendInputNumChannels( inputMc, &numInChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + for ( i = 0; i < numInChannels; ++i ) + { + /* It's OK to also set gain 1 for LFE input channels here. + * Correct LFE handling will be applied within updateMcPanGains() */ + inputMc->panGains[i][0] = 1.f; + } + } + else if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_STEREO ) + { + /* Special case for STEREO to MONO: Passive downmix (L+R)/2 */ + inputMc->panGains[0][0] = 0.5; + inputMc->panGains[1][0] = 0.5; + } + else + { + /* ls_conversion_cicpX_stereo contains gains for side speakers. + * These should be skipped with 5.1+X inputs. */ + skipSideSpeakers = false; + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 || inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) + { + skipSideSpeakers = true; + } + for ( readIdx = 0, writeIdx = 0; writeIdx < numInChannels; ++readIdx, ++writeIdx ) + { + if ( skipSideSpeakers && readIdx == 4 ) + { + /* Skip gains for side speakers in lookup table */ + readIdx += 2; + } + + inputMc->panGains[writeIdx][0] = ls_conversion_cicpX_mono[readIdx][0]; + } + } + + return IVAS_ERR_OK; +} + +static ivas_error initMcPanGainsWithStereoLookup( + input_mc *inputMc ) +{ + int16_t readIdx; + int16_t writeIdx; + bool skipSideSpeakers; + int16_t numInChannels; + ivas_error error; + + /* Special case - MONO input. + * Use gains for center CICP speaker and return early. */ + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_MONO ) + { + inputMc->panGains[0][0] = ls_conversion_cicpX_stereo[2][0]; + inputMc->panGains[0][1] = ls_conversion_cicpX_stereo[2][1]; + return IVAS_ERR_OK; + } + + /* ls_conversion_cicpX_stereo contains gains for side speakers. + * These should be skipped with 5.1+X inputs. */ + skipSideSpeakers = false; + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 || inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) + { + skipSideSpeakers = true; + } + + if ( ( error = getRendInputNumChannels( inputMc, &numInChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( readIdx = 0, writeIdx = 0; writeIdx < numInChannels; ++readIdx, ++writeIdx ) + { + if ( skipSideSpeakers && readIdx == 4 ) + { + /* Skip gains for side speakers in lookup table */ + readIdx += 2; + } + + inputMc->panGains[writeIdx][0] = ls_conversion_cicpX_stereo[readIdx][0]; + inputMc->panGains[writeIdx][1] = ls_conversion_cicpX_stereo[readIdx][1]; + } + + return IVAS_ERR_OK; +} + +/* Returns 1 (true) if configs A and B are equal, otherwise returns 0 (false). + * If both configs are custom LS layouts, layout details are compared to determine equality. */ +static bool configsAreEqual( + const IVAS_REND_AudioConfig configA, + const LSSETUP_CUSTOM_STRUCT customLsA, + const IVAS_REND_AudioConfig configB, + const LSSETUP_CUSTOM_STRUCT customLsB ) +{ + int16_t i; + + /* Both input and output are custom LS - compare structs */ + if ( configA == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM && configB == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( customLsA.num_spk != customLsB.num_spk ) + { + return false; + } + + if ( customLsA.num_lfe != customLsB.num_lfe ) + { + return false; + } + + if ( customLsA.is_planar_setup != customLsB.is_planar_setup ) + { + return false; + } + + for ( i = 0; i < customLsA.num_spk; ++i ) + { + /* Compare to nearest degree (hence the int cast) */ + if ( (int16_t) customLsA.ls_azimuth[i] != (int16_t) customLsB.ls_azimuth[i] || + (int16_t) customLsA.ls_elevation[i] != (int16_t) customLsB.ls_elevation[i] ) + { + return false; + } + } + for ( i = 0; i < customLsA.num_lfe; ++i ) + { + if ( customLsA.lfe_idx[i] != customLsB.lfe_idx[i] ) + { + return false; + } + } + + return true; + } + + /* Otherwise it's enough to compare config enums */ + return configA == configB; +} + +static ivas_error updateLfePanGainsForMcOut( + input_mc *inputMc, + const IVAS_REND_AudioConfig outConfig ) +{ + int16_t i, numLfeIn, numOutChannels; + ivas_error error; + error = IVAS_ERR_OK; + + /* If panning is not required, simply return */ + if ( !inputMc->lfeRouting.pan_lfe ) + { + return error; + } + + numLfeIn = getNumLfeChannels( inputMc ); + + if ( outConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + numOutChannels = inputMc->base.ctx.pCustomLsOut->num_spk + inputMc->base.ctx.pCustomLsOut->num_lfe; + } + else + { + if ( ( error = getAudioConfigNumChannels( outConfig, &numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + for ( i = 0; i < numLfeIn; i++ ) + { + /* panning gains */ + if ( ( error = getEfapGains( *inputMc->base.ctx.pEfapOutWrapper, + inputMc->lfeRouting.lfeOutputAzimuth, + inputMc->lfeRouting.lfeOutputElevation, + inputMc->lfeRouting.lfePanMtx[i] ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* linear input gain */ + v_multc( inputMc->lfeRouting.lfePanMtx[i], + inputMc->lfeRouting.lfeInputGain, + inputMc->lfeRouting.lfePanMtx[i], + numOutChannels ); + } + + return error; +} + +static ivas_error updateLfePanGainsForAmbiOut( + input_mc *inputMc, + const IVAS_REND_AudioConfig outConfig ) +{ + int16_t i; + int16_t numLfeIn, outAmbiOrder; + ivas_error error; + error = IVAS_ERR_OK; + + /* If panning is not required, simply return */ + if ( !inputMc->lfeRouting.pan_lfe ) + { + return error; + } + + if ( ( error = getAmbisonicsOrder( outConfig, &outAmbiOrder ) ) != IVAS_ERR_OK ) + { + return error; + } + + numLfeIn = getNumLfeChannels( inputMc ); + + for ( i = 0; i < numLfeIn; i++ ) + { + /* panning gains */ + ivas_dirac_dec_get_response( (int16_t) inputMc->lfeRouting.lfeOutputAzimuth, + (int16_t) inputMc->lfeRouting.lfeOutputElevation, + inputMc->lfeRouting.lfePanMtx[i], + outAmbiOrder ); + + /* linear input gain */ + v_multc( inputMc->lfeRouting.lfePanMtx[i], + inputMc->lfeRouting.lfeInputGain, + inputMc->lfeRouting.lfePanMtx[i], + IVAS_MAX_OUTPUT_CHANNELS ); + } + + return error; +} + +static ivas_error updateMcPanGainsForMcOut( + input_mc *inputMc, + const IVAS_REND_AudioConfig outConfig ) +{ + ivas_error error; + + /* "if" conditions below realize the following mapping: + + If in == out, use identity matrix, otherwise follow the table: + +-----------+-------------+---------------+-----------+--------------------+ + | in\out | MONO | STEREO | custom LS | other | + +-----------+-------------+---------------+-----------+--------------------+ + | MONO | mono out | EFAP | EFAP | EFAP | + | custom LS | mono out | EFAP | EFAP | EFAP | + | other | mono lookup | stereo lookup | EFAP | conversion mapping | + +-----------+-------------+---------------+-----------+--------------------+ + */ + + if ( configsAreEqual( inputMc->base.inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut ) ) + { + error = initMcPanGainsWithIdentMatrix( inputMc ); + } + else if ( outConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM || + inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_MONO || + inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + error = initMcPanGainsWithEfap( inputMc, outConfig ); + } + else if ( outConfig == IVAS_REND_AUDIO_CONFIG_MONO ) + { + error = initMcPanGainsWithMonoOut( inputMc ); + } + else if ( outConfig == IVAS_REND_AUDIO_CONFIG_STEREO ) + { + error = initMcPanGainsWithStereoLookup( inputMc ); + } + else /* default */ + { + error = initMcPanGainsWithConversionMapping( inputMc, outConfig ); + } + + /* check for errors from above block */ + if ( error != IVAS_ERR_OK ) + { + return error; + } + + /* update LFE panning */ + error = updateLfePanGainsForMcOut( inputMc, outConfig ); + + return error; +} + +static ivas_error updateMcPanGainsForAmbiOut( + input_mc *inputMc, + const IVAS_REND_AudioConfig outConfig ) +{ + int16_t ch_in, ch_out, lfeIdx; + int16_t numNonLfeInChannels, outAmbiOrder; + const float *spkAzi, *spkEle; + ivas_error error; + + if ( ( error = getAmbisonicsOrder( outConfig, &outAmbiOrder ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( inputMc->base.inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = getNumNonLfeChannelsInSpeakerLayout( inputMc->base.inConfig, &numNonLfeInChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getSpeakerAzimuths( inputMc->base.inConfig, &spkAzi ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getSpeakerElevations( inputMc->base.inConfig, &spkEle ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( ch_in = 0, ch_out = 0; ch_in < numNonLfeInChannels; ++ch_in, ++ch_out ) + { + if ( ch_in == LFE_CHANNEL ) + { + ++ch_out; + } + ivas_dirac_dec_get_response( (int16_t) spkAzi[ch_in], (int16_t) spkEle[ch_in], inputMc->panGains[ch_out], outAmbiOrder ); + } + } + else + { + numNonLfeInChannels = inputMc->customLsInput.num_spk; + spkAzi = inputMc->customLsInput.ls_azimuth; + spkEle = inputMc->customLsInput.ls_elevation; + + for ( ch_in = 0, ch_out = 0; ch_in < numNonLfeInChannels; ++ch_in, ++ch_out ) + { + for ( lfeIdx = 0; lfeIdx < inputMc->customLsInput.num_lfe; ++lfeIdx ) + { + if ( inputMc->customLsInput.lfe_idx[lfeIdx] == ch_in ) + { + ++ch_out; + break; + } + } + + ivas_dirac_dec_get_response( (int16_t) spkAzi[ch_in], (int16_t) spkEle[ch_in], inputMc->panGains[ch_out], outAmbiOrder ); + } + } + + /* update LFE panning */ + if ( ( error = updateLfePanGainsForAmbiOut( inputMc, outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static ivas_error updateMcPanGains( + input_mc *inputMc, + const IVAS_REND_AudioConfig outConfig ) +{ + int16_t i; + ivas_error error; + + /* Reset to all zeros - some functions below only write non-zero elements. */ + setZeroPanMatrix( inputMc->panGains ); + + error = IVAS_ERR_OK; + switch ( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + error = updateMcPanGainsForMcOut( inputMc, outConfig ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + error = updateMcPanGainsForAmbiOut( inputMc, outConfig ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + break; /* Do nothing */ + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + /* Prepare rendering to intermediate format */ + error = updateMcPanGainsForMcOut( inputMc, IVAS_REND_AUDIO_CONFIG_7_1_4 ); + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + /* Check error here to keep switch statement more compact */ + if ( error != IVAS_ERR_OK ) + { + return error; + } + + /* Copy LFE routing to pan gains array */ + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + for ( i = 0; i < inputMc->customLsInput.num_lfe; ++i ) + { + mvr2r( inputMc->lfeRouting.lfePanMtx[i], inputMc->panGains[inputMc->customLsInput.lfe_idx[i]], IVAS_MAX_OUTPUT_CHANNELS ); + } + } + else + { + /* For code simplicity, always copy LFE gains. If config has no LFE, gains will be zero anyway. */ + mvr2r( inputMc->lfeRouting.lfePanMtx[0], inputMc->panGains[LFE_CHANNEL], IVAS_MAX_OUTPUT_CHANNELS ); + } + + return IVAS_ERR_OK; +} + + +static ivas_error initMcBinauralRendering( + input_mc *inputMc, + const IVAS_REND_AudioConfig inConfig, + const IVAS_REND_AudioConfig outConfig, + RENDER_CONFIG_DATA *hRendCfg ) +{ + ivas_error error; + int32_t outSampleRate; + + /* check if re-initialization */ + if ( inputMc->tdRendWrapper.hBinRendererTd != NULL ) + { + ivas_td_binaural_close( &inputMc->tdRendWrapper.hBinRendererTd ); + inputMc->tdRendWrapper.hHrtfTD = NULL; + } + + ivas_rend_closeCrend( &inputMc->crendWrapper ); + + ivas_reverb_close( &inputMc->hReverb ); + + if ( inputMc->efapInWrapper.hEfap != NULL ) + { + efap_free_data( &inputMc->efapInWrapper.hEfap ); + } + + outSampleRate = *inputMc->base.ctx.pOutSampleRate; + + /* TODO tmu : needs review allocate both renderers; needed if headrotation is toggled so the renderer can be switched */ + // bool initTDRend; + // initTDRend = false; + // if ( outConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) + // { + // if ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + // { + // initTDRend = true; + // } + // else if ( ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) && + // ( inputMc->base.ctx.pHeadRotData->headRotEnabled ) ) + // { + // initTDRend = true; + // } + // } + + // if ( initTDRend ) + { + if ( ( error = ivas_td_binaural_open_ext( &inputMc->tdRendWrapper, inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( hRendCfg != NULL && hRendCfg->roomAcoustics.use_brir == 0 && hRendCfg->roomAcoustics.late_reverb_on ) + { + if ( ( error = ivas_reverb_open( &( inputMc->hReverb ), getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, hRendCfg, outSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + { + if ( ( error = ivas_rend_openCrend( &inputMc->crendWrapper, ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) ? AUDIO_CONFIG_7_1_4 : getIvasAudioConfigFromRendAudioConfig( inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), hRendCfg, + NULL, outSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Initialise the EFAP handle for rotation on input layout */ + if ( inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM && inputMc->base.ctx.pHeadRotData->headRotEnabled ) + { + if ( ( error = initEfap( &inputMc->efapInWrapper, inConfig, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +static lfe_routing defaultLfeRouting( + const IVAS_REND_AudioConfig inConfig, + const LSSETUP_CUSTOM_STRUCT customLsIn, + const IVAS_REND_AudioConfig outConfig, + const LSSETUP_CUSTOM_STRUCT customLsOut ) +{ + int16_t i; + lfe_routing routing; + + /* Set all output gains to zero, then route each input LFE consecutively to the next available output LFE. */ + + for ( i = 0; i < IVAS_MAX_INPUT_LFE_CHANNELS; ++i ) + { + set_zero( routing.lfePanMtx[i], IVAS_MAX_OUTPUT_CHANNELS ); + } + + routing.pan_lfe = false; + routing.lfeInputGain = 1.0f; + + switch ( inConfig ) + { + case IVAS_REND_AUDIO_CONFIG_5_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_5_1_4: + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_7_1_4: + routing.numLfeChannels = 1; + break; + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + routing.numLfeChannels = customLsIn.num_lfe; + break; + default: + routing.numLfeChannels = 0; + } + + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_5_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_5_1_4: + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_7_1_4: + routing.lfePanMtx[0][LFE_CHANNEL] = 1.0f; + break; + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + for ( i = 0; i < routing.numLfeChannels && i < customLsOut.num_lfe; ++i ) + { + routing.lfePanMtx[i][customLsOut.lfe_idx[i]] = 1.0f; + } + break; + default: + /* Do nothing */ + break; + } + + return routing; +} + +static ivas_error setRendInputActiveMc( + void *input, + const IVAS_REND_AudioConfig inConfig, + const IVAS_REND_InputId id, + RENDER_CONFIG_DATA *hRendCfg ) +{ + ivas_error error; + rendering_context rendCtx; + IVAS_REND_AudioConfig outConfig; + input_mc *inputMc; + + inputMc = (input_mc *) input; + rendCtx = inputMc->base.ctx; + outConfig = *rendCtx.pOutConfig; + + if ( !isIoConfigPairSupported( inConfig, outConfig ) ) + { + return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; + } + + initRendInputBase( &inputMc->base, inConfig, id, rendCtx ); + setZeroPanMatrix( inputMc->panGains ); + inputMc->customLsInput = defaultCustomLs(); + inputMc->tdRendWrapper = defaultTdRendWrapper(); + inputMc->crendWrapper = NULL; + inputMc->hReverb = NULL; + initRotGains( inputMc->rot_gains_prev ); + inputMc->lfeRouting = defaultLfeRouting( inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut ); + + if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL || outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) + { + if ( ( error = initMcBinauralRendering( inputMc, inConfig, outConfig, hRendCfg ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = updateMcPanGains( inputMc, outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static void clearInputMc( + input_mc *inputMc ) +{ + rendering_context rendCtx; + + rendCtx = inputMc->base.ctx; + + initRendInputBase( &inputMc->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx ); + + /* Free input's internal handles */ + if ( inputMc->efapInWrapper.hEfap != NULL ) + { + efap_free_data( &inputMc->efapInWrapper.hEfap ); + } + + ivas_rend_closeCrend( &inputMc->crendWrapper ); + + ivas_reverb_close( &inputMc->hReverb ); + + if ( inputMc->tdRendWrapper.hBinRendererTd != NULL ) + { + ivas_td_binaural_close( &inputMc->tdRendWrapper.hBinRendererTd ); + inputMc->tdRendWrapper.hHrtfTD = NULL; + } + + return; +} + +static ivas_error initSbaPanGainsForMcOut( + input_sba *inputSba, + const IVAS_REND_AudioConfig outConfig, + const LSSETUP_CUSTOM_STRUCT *outSetupCustom ) +{ + int16_t ambiOrderIn; + int16_t chInIdx, chOutIdx; + float *tmpDecMtx, *readPtr; + IVAS_OUTPUT_SETUP hOutSetup; + ivas_error error; + + if ( ( error = getAmbisonicsOrder( inputSba->base.inConfig, &ambiOrderIn ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( getAudioConfigType( outConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + assert( !"Invalid configuration" ); + return IVAS_ERR_WRONG_PARAMS; + } + + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_MONO: + hOutSetup.ls_azimuth = ls_azimuth_CICP1; + hOutSetup.ls_elevation = ls_elevation_CICP1; + ivas_output_init( &hOutSetup, getIvasAudioConfigFromRendAudioConfig( outConfig ) ); + break; + case IVAS_REND_AUDIO_CONFIG_STEREO: + case IVAS_REND_AUDIO_CONFIG_5_1: + case IVAS_REND_AUDIO_CONFIG_7_1: + case IVAS_REND_AUDIO_CONFIG_5_1_2: + case IVAS_REND_AUDIO_CONFIG_5_1_4: + case IVAS_REND_AUDIO_CONFIG_7_1_4: + ivas_output_init( &hOutSetup, getIvasAudioConfigFromRendAudioConfig( outConfig ) ); + break; + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + ivas_ls_custom_setup( &hOutSetup, outSetupCustom ); + break; + default: + assert( !"Invalid speaker config" ); + return IVAS_ERR_WRONG_PARAMS; + } + + /* obtain and copy over HOA decoding matrix */ + tmpDecMtx = NULL; + if ( ( error = ivas_sba_get_hoa_dec_matrix( hOutSetup, &tmpDecMtx, ambiOrderIn ) ) != IVAS_ERR_OK ) + { + return error; + } + + readPtr = &tmpDecMtx[0]; + for ( chOutIdx = 0; chOutIdx < hOutSetup.nchan_out_woLFE + hOutSetup.num_lfe; ++chOutIdx ) + { + for ( chInIdx = 0; chInIdx < SBA_NHARM_HOA3; ++chInIdx ) + { + if ( hOutSetup.num_lfe > 0 && chOutIdx == hOutSetup.index_lfe[0] ) + { + continue; /* nothing to be rendered to LFE */ + } + inputSba->hoaDecMtx[chInIdx][chOutIdx] = *readPtr++; + } + } + + free( tmpDecMtx ); + + return IVAS_ERR_OK; +} + +static ivas_error initSbaPanGainsForSbaOut( + input_sba *inputSba, + const IVAS_REND_AudioConfig outConfig ) +{ + ivas_error error; + error = IVAS_ERR_OK; + + if ( getAudioConfigType( outConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) + { + assert( !"Invalid configuration" ); + return IVAS_ERR_WRONG_PARAMS; + } + + fillIdentityPanMatrix( inputSba->hoaDecMtx ); + + return error; +} + +static ivas_error updateSbaPanGains( + input_sba *inputSba, + const IVAS_REND_AudioConfig outConfig, + RENDER_CONFIG_DATA *hRendCfg ) +{ + ivas_error error; + IVAS_REND_AudioConfig inConfig; + rendering_context rendCtx; + + /* Reset to all zeros - some functions below only write non-zero elements. */ + setZeroPanMatrix( inputSba->hoaDecMtx ); + + inConfig = inputSba->base.inConfig; + rendCtx = inputSba->base.ctx; + + switch ( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + error = initSbaPanGainsForMcOut( inputSba, outConfig, inputSba->base.ctx.pCustomLsOut ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + error = initSbaPanGainsForSbaOut( inputSba, outConfig ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + error = ivas_rend_openCrend( &inputSba->crendWrapper, + getIvasAudioConfigFromRendAudioConfig( inConfig ), + getIvasAudioConfigFromRendAudioConfig( outConfig ), + hRendCfg, + NULL, + *rendCtx.pOutSampleRate ); + break; + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + if ( ( error = initSbaPanGainsForMcOut( inputSba, IVAS_REND_AUDIO_CONFIG_7_1_4, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + + error = ivas_rend_openCrend( &inputSba->crendWrapper, + AUDIO_CONFIG_7_1_4, + getIvasAudioConfigFromRendAudioConfig( outConfig ), + hRendCfg, + NULL, + *rendCtx.pOutSampleRate ); + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + /* Check error here to keep switch statement more compact */ + if ( error != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static ivas_error setRendInputActiveSba( + void *input, + const IVAS_REND_AudioConfig inConfig, + const IVAS_REND_InputId id, + RENDER_CONFIG_DATA *hRendCfg ) +{ + ivas_error error; + rendering_context rendCtx; + IVAS_REND_AudioConfig outConfig; + input_sba *inputSba; + + inputSba = (input_sba *) input; + rendCtx = inputSba->base.ctx; + outConfig = *rendCtx.pOutConfig; + + if ( !isIoConfigPairSupported( inConfig, outConfig ) ) + { + return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; + } + + initRendInputBase( &inputSba->base, inConfig, id, rendCtx ); + setZeroPanMatrix( inputSba->hoaDecMtx ); + inputSba->crendWrapper = NULL; + initRotGains( inputSba->rot_gains_prev ); + + if ( ( error = updateSbaPanGains( inputSba, outConfig, hRendCfg ) ) != IVAS_ERR_OK ) + { + return error; + } + + return error; +} + +static void clearInputSba( + input_sba *inputSba ) +{ + rendering_context rendCtx; + + rendCtx = inputSba->base.ctx; + + initRendInputBase( &inputSba->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx ); + + /* Free input's internal handles */ + ivas_rend_closeCrend( &inputSba->crendWrapper ); + + return; +} + +static ivas_error initMasaDummyDecForMcOut( + input_masa *inputMasa, + const IVAS_REND_AudioConfig outConfig ) +{ + ivas_error error; + int16_t numCldfbAnalyses; + int16_t numCldfbSyntheses; + int16_t i; + AUDIO_CONFIG output_config; + DecoderDummy *decDummy; + decDummy = inputMasa->decDummy; + + output_config = getIvasAudioConfigFromRendAudioConfig( outConfig ); + decDummy->hDecoderConfig->output_config = output_config; + + decDummy->hDecoderConfig->ivas_total_brate = IVAS_512k; /* Todo Nokia: This is preventing initialization of 2TC as 1TC, should be fixed properly in ivas_dirac_dec_config() */ + decDummy->sba_mode = SBA_MODE_NONE; /* Todo Nokia: This is done to prevent ivas_dirac_dec_config() to not use uninitialized value. It could be considered if this should not be even accessed when not in SBA. */ + decDummy->mc_mode = MC_MODE_NONE; /* Todo Nokia: This should be also refactored in such way that it is not checked if not in MC mode */ + + ivas_output_init( &( decDummy->hOutSetup ), output_config ); + ivas_output_init( &( decDummy->hIntSetup ), output_config ); + + decDummy->renderer_type = RENDERER_DIRAC; + if ( output_config == AUDIO_CONFIG_STEREO ) + { + decDummy->renderer_type = RENDERER_STEREO_PARAMETRIC; + } + + decDummy->ivas_format = MASA_FORMAT; + decDummy->transport_config = AUDIO_CONFIG_INVALID; + + /* Todo refactor: Access to qmetadata is not required by the algorithm. */ + if ( ( error = ivas_qmetadata_open( &( decDummy->hQMetaData ) ) ) != IVAS_ERR_OK ) + { + return error; + } + decDummy->hQMetaData->coherence_flag = 1; + + if ( ( error = ivas_dirac_dec_open( decDummy ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef FIX_390_EXT_REND_MASA_META_COPY + decDummy->hDirAC->dirac_bs_md_write_idx = 0; +#endif + + if ( decDummy->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_init_binaural_data( decDummy, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + numCldfbAnalyses = decDummy->nchan_transport; + numCldfbSyntheses = decDummy->hDecoderConfig->nchan_out; + + for ( i = 0; i < numCldfbAnalyses; i++ ) + { + if ( ( error = openCldfb( &( decDummy->cldfbAnaDec[i] ), CLDFB_ANALYSIS, decDummy->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ; i < MAX_INTERN_CHANNELS; i++ ) + { + decDummy->cldfbAnaDec[i] = NULL; + } + + for ( i = 0; i < numCldfbSyntheses; i++ ) + { + if ( ( error = openCldfb( &( decDummy->cldfbSynDec[i] ), CLDFB_SYNTHESIS, decDummy->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ; i < MAX_OUTPUT_CHANNELS; i++ ) + { + decDummy->cldfbSynDec[i] = NULL; + } + + return IVAS_ERR_OK; +} + +static ivas_error initMasaDummyDecForSbaOut( + input_masa *inputMasa, + const IVAS_REND_AudioConfig outConfig ) +{ + ivas_error error; + int16_t numCldfbAnalyses; + int16_t numCldfbSyntheses; + int16_t i; + AUDIO_CONFIG output_config; + DecoderDummy *decDummy; + + decDummy = inputMasa->decDummy; + + output_config = getIvasAudioConfigFromRendAudioConfig( outConfig ); + decDummy->hDecoderConfig->output_config = output_config; + + decDummy->hDecoderConfig->ivas_total_brate = IVAS_512k; /* Todo Nokia: This is preventing initialization of 2TC as 1TC, should be fixed properly in ivas_dirac_dec_config() */ + decDummy->sba_mode = SBA_MODE_NONE; /* Todo Nokia: This is done to prevent ivas_dirac_dec_config() to not use uninitialized value. It could be considered if this should not be even accessed when not in SBA. */ + decDummy->mc_mode = MC_MODE_NONE; /* Todo Nokia: This should be also refactored in such way that it is not checked if not in MC mode */ + + ivas_output_init( &( decDummy->hOutSetup ), output_config ); + ivas_output_init( &( decDummy->hIntSetup ), output_config ); + decDummy->renderer_type = RENDERER_DIRAC; + decDummy->ivas_format = MASA_FORMAT; + decDummy->transport_config = AUDIO_CONFIG_INVALID; + + /* Todo refactor: Access to qmetadata is not required by the algorithm. */ + if ( ( error = ivas_qmetadata_open( &( decDummy->hQMetaData ) ) ) != IVAS_ERR_OK ) + { + return error; + } + decDummy->hQMetaData->coherence_flag = 1; + + if ( ( error = ivas_dirac_dec_open( decDummy ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef FIX_390_EXT_REND_MASA_META_COPY + decDummy->hDirAC->dirac_bs_md_write_idx = 0; +#endif + + numCldfbAnalyses = decDummy->nchan_transport; + numCldfbSyntheses = decDummy->hDecoderConfig->nchan_out; + + for ( i = 0; i < numCldfbAnalyses; i++ ) + { + if ( ( error = openCldfb( &( decDummy->cldfbAnaDec[i] ), CLDFB_ANALYSIS, decDummy->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ; i < MAX_INTERN_CHANNELS; i++ ) + { + decDummy->cldfbAnaDec[i] = NULL; + } + + for ( i = 0; i < numCldfbSyntheses; i++ ) + { + if ( ( error = openCldfb( &( decDummy->cldfbSynDec[i] ), CLDFB_SYNTHESIS, decDummy->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ; i < MAX_OUTPUT_CHANNELS; i++ ) + { + decDummy->cldfbSynDec[i] = NULL; + } + + return IVAS_ERR_OK; +} + +static ivas_error initMasaDummyDecForBinauralOut( + input_masa *inputMasa, + const IVAS_REND_AudioConfig outConfig ) +{ + ivas_error error; + + int16_t i; + AUDIO_CONFIG output_config; + DecoderDummy *decDummy; + + decDummy = inputMasa->decDummy; + + output_config = getIvasAudioConfigFromRendAudioConfig( outConfig ); + decDummy->hDecoderConfig->output_config = output_config; + + output_config = decDummy->hDecoderConfig->output_config; + + decDummy->hDecoderConfig->ivas_total_brate = IVAS_512k; /* Todo Nokia: This is preventing initialization of 2TC as 1TC, should be fixed properly in ivas_dirac_dec_config() */ + decDummy->sba_mode = SBA_MODE_NONE; /* Todo Nokia: This is done to prevent ivas_dirac_dec_config() to not use uninitialized value. It could be considered if this should not be even accessed when not in SBA. */ + decDummy->mc_mode = MC_MODE_NONE; /* Todo Nokia: This should be also refactored in such way that it is not checked if not in MC mode */ + + ivas_output_init( &( decDummy->hOutSetup ), output_config ); + if ( output_config == AUDIO_CONFIG_BINAURAL ) + { + decDummy->renderer_type = RENDERER_BINAURAL_PARAMETRIC; + } + else + { + decDummy->renderer_type = RENDERER_BINAURAL_PARAMETRIC_ROOM; + } + decDummy->ivas_format = MASA_FORMAT; + decDummy->transport_config = AUDIO_CONFIG_INVALID; + + if ( ( error = ivas_dirac_dec_open( decDummy ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef FIX_390_EXT_REND_MASA_META_COPY + decDummy->hDirAC->dirac_bs_md_write_idx = 0; +#endif + + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &decDummy->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( decDummy, decDummy->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + if ( ( error = openCldfb( &( decDummy->cldfbAnaDec[i] ), CLDFB_ANALYSIS, decDummy->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = openCldfb( &( decDummy->cldfbSynDec[i] ), CLDFB_SYNTHESIS, decDummy->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ; i < MAX_INTERN_CHANNELS; i++ ) + { + decDummy->cldfbAnaDec[i] = NULL; + decDummy->cldfbSynDec[i] = NULL; + } + + return IVAS_ERR_OK; +} + +static ivas_error updateMasaDummyDec( + input_masa *inputMasa, + const IVAS_REND_AudioConfig outConfig ) +{ + ivas_error error; + + switch ( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + error = initMasaDummyDecForMcOut( inputMasa, outConfig ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + error = initMasaDummyDecForSbaOut( inputMasa, outConfig ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + error = initMasaDummyDecForBinauralOut( inputMasa, outConfig ); + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + return error; +} + +static DecoderDummy *initDecoderDummy( + const int32_t sampleRate, + const int16_t numTransChannels, + const IVAS_REND_AudioConfig outConfig, + const uint8_t enableRenderConfig ) +{ + ivas_error error; + int16_t i; + int16_t numOutChannels; + DecoderDummy *decDummy; + + if ( ( error = getAudioConfigNumChannels( outConfig, &numOutChannels ) ) != IVAS_ERR_OK ) + { + /* Checking error with assert is enough, this function is only temporary anyway */ + assert( error == IVAS_ERR_OK ); + } + + decDummy = malloc( sizeof( DecoderDummy ) ); + decDummy->hDecoderConfig = malloc( sizeof( DECODER_CONFIG ) ); + decDummy->hDecoderConfig->output_Fs = sampleRate; + decDummy->hDecoderConfig->nchan_out = numOutChannels; + decDummy->hDecoderConfig->Opt_Headrotation = 0; + + decDummy->hBinRenderer = NULL; + decDummy->hEFAPdata = NULL; + decDummy->hCrendWrapper = NULL; + decDummy->hHrtfTD = NULL; + decDummy->hSpar = NULL; + decDummy->hoa_dec_mtx = NULL; + decDummy->hVBAPdata = NULL; // note: not used at the moment + decDummy->hMasa = NULL; + decDummy->hDiracDecBin = NULL; + decDummy->hQMetaData = NULL; + decDummy->hDecoderConfig->output_config = getIvasAudioConfigFromRendAudioConfig( outConfig ); + decDummy->nchan_transport = numTransChannels; + + if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM || outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) + { + decDummy->hHeadTrackData = malloc( sizeof( HEAD_TRACK_DATA ) ); + /* Initialise Rmat_prev to I, Rmat will be computed later */ + for ( i = 0; i < 3; i++ ) + { + set_zero( decDummy->hHeadTrackData->Rmat_prev[i], 3 ); + decDummy->hHeadTrackData->Rmat_prev[i][i] = 1.0f; + } + + decDummy->hHeadTrackData->num_quaternions = 0; + decDummy->hHeadTrackData->lrSwitchInterpVal = 0.0f; + decDummy->hHeadTrackData->lrSwitchedCurrent = 0; + decDummy->hHeadTrackData->lrSwitchedNext = 0; + decDummy->hHeadTrackData->OrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ); + ivas_orient_trk_Init( decDummy->hHeadTrackData->OrientationTracker ); + } + else + { + decDummy->hHeadTrackData = NULL; + } + + if ( enableRenderConfig ) + { + ivas_render_config_open( &decDummy->hRenderConfig ); + decDummy->hRenderConfig->roomAcoustics.late_reverb_on = 0; + decDummy->hRenderConfig->roomAcoustics.use_brir = 0; + } + else + { + decDummy->hRenderConfig = NULL; + } + + decDummy->renderer_type = RENDERER_DISABLE; + + return decDummy; +} + +static ivas_error setRendInputActiveMasa( + void *input, + const IVAS_REND_AudioConfig inConfig, + const IVAS_REND_InputId id, + RENDER_CONFIG_DATA *hRendCfg ) /* Todo: This is not used at all within MASA. Support might be better to do after refactoring. */ +{ + ivas_error error; + rendering_context rendCtx; + IVAS_REND_AudioConfig outConfig; + input_masa *inputMasa; + int16_t numInChannels; + + inputMasa = (input_masa *) input; + rendCtx = inputMasa->base.ctx; + outConfig = *rendCtx.pOutConfig; + (void) hRendCfg; /* Suppress warning */ + + if ( !isIoConfigPairSupported( inConfig, outConfig ) ) + { + return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; + } + + initRendInputBase( &inputMasa->base, inConfig, id, rendCtx ); + + if ( ( error = getAudioConfigNumChannels( inConfig, &numInChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + inputMasa->decDummy = initDecoderDummy( *rendCtx.pOutSampleRate, numInChannels, outConfig, 0 ); + inputMasa->metadataHasBeenFed = false; + + if ( ( error = updateMasaDummyDec( inputMasa, outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static void freeDecoderDummy( + DecoderDummy **ppDecDummy ) +{ + int16_t i; + DecoderDummy *pDecDummy; + + if ( ppDecDummy == NULL || *ppDecDummy == NULL ) + { + return; + } + pDecDummy = *ppDecDummy; + + if ( pDecDummy->hDecoderConfig != NULL ) + { + free( pDecDummy->hDecoderConfig ); + } + + if ( pDecDummy->hHeadTrackData != NULL ) + { + if ( pDecDummy->hHeadTrackData->OrientationTracker != NULL ) + { + free( pDecDummy->hHeadTrackData->OrientationTracker ); + } + free( pDecDummy->hHeadTrackData ); + } + ivas_render_config_close( &pDecDummy->hRenderConfig ); + + /* CLDFB handles */ + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + if ( pDecDummy->cldfbAnaDec[i] != NULL ) + { + deleteCldfb( &( pDecDummy->cldfbAnaDec[i] ) ); + } + } + + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + if ( pDecDummy->cldfbSynDec[i] != NULL ) + { + deleteCldfb( &( pDecDummy->cldfbSynDec[i] ) ); + } + } + + /* DirAC handle */ + ivas_dirac_dec_close( &( pDecDummy->hDirAC ) ); + + /* Qmetadata handle */ + ivas_qmetadata_close( &pDecDummy->hQMetaData ); + + /* VBAP handle */ + vbap_free_data( &( pDecDummy->hVBAPdata ) ); + + /* HOA decoder matrix */ + if ( pDecDummy->hoa_dec_mtx != NULL ) + { + free( pDecDummy->hoa_dec_mtx ); + pDecDummy->hoa_dec_mtx = NULL; + } + + /* Parametric binaural renderer handle */ + ivas_dirac_dec_close_binaural_data( &pDecDummy->hDiracDecBin ); + + free( pDecDummy ); + pDecDummy = NULL; + + return; +} + +static void clearInputMasa( + input_masa *inputMasa ) +{ + rendering_context rendCtx; + + rendCtx = inputMasa->base.ctx; + + initRendInputBase( &inputMasa->base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, rendCtx ); + freeDecoderDummy( &inputMasa->decDummy ); + + return; +} + +ivas_error IVAS_REND_Open( + IVAS_REND_HANDLE *phIvasRend, + const int32_t outputSampleRate, + const IVAS_REND_AudioConfig outConfig ) +{ + int16_t i; + IVAS_REND_HANDLE hIvasRend; + ivas_error error; + int16_t numOutChannels; + + /* Validate function arguments */ + if ( phIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = validateOutputAudioConfig( outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = validateOutputSampleRate( outputSampleRate, outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + *phIvasRend = (IVAS_REND_HANDLE) malloc( sizeof( struct IVAS_REND ) ); + if ( *phIvasRend == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + + hIvasRend = *phIvasRend; + hIvasRend->sampleRateOut = outputSampleRate; + hIvasRend->outputConfig = outConfig; + hIvasRend->customLsOut = defaultCustomLs(); + hIvasRend->hLimiter = NULL; + hIvasRend->efapOutWrapper.hEfap = NULL; + hIvasRend->efapOutWrapper.pCustomLsSetup = NULL; +#ifdef DEBUGGING + hIvasRend->numClipping = 0; +#endif + + /* Initialize limiter */ + if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = initLimiter( &hIvasRend->hLimiter, numOutChannels, outputSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Initialize headrotation data */ + if ( ( error = initHeadRotation( hIvasRend ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Initialize EFAP */ + if ( ( error = initEfap( &hIvasRend->efapOutWrapper, outConfig, &hIvasRend->customLsOut ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Initialize inputs */ + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + initRendInputBase( &hIvasRend->inputsIsm[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) ); + hIvasRend->inputsIsm[i].crendWrapper = NULL; + hIvasRend->inputsIsm[i].hReverb = NULL; + hIvasRend->inputsIsm[i].tdRendWrapper.hBinRendererTd = NULL; + } + + for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) + { + initRendInputBase( &hIvasRend->inputsMc[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) ); + hIvasRend->inputsMc[i].efapInWrapper.hEfap = NULL; + hIvasRend->inputsMc[i].crendWrapper = NULL; + hIvasRend->inputsMc[i].hReverb = NULL; + hIvasRend->inputsMc[i].tdRendWrapper.hBinRendererTd = NULL; + } + + for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i ) + { + initRendInputBase( &hIvasRend->inputsSba[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) ); + hIvasRend->inputsSba[i].crendWrapper = NULL; + } + + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) + { + initRendInputBase( &hIvasRend->inputsMasa[i].base, IVAS_REND_AUDIO_CONFIG_UNKNOWN, 0, getRendCtx( hIvasRend ) ); + hIvasRend->inputsMasa[i].decDummy = NULL; + hIvasRend->inputsMasa[i].metadataHasBeenFed = false; + } + + return IVAS_ERR_OK; +} + +static LSSETUP_CUSTOM_STRUCT makeCustomLsSetup( + const IVAS_CUSTOM_LS_DATA rendCustomLsLayout ) +{ + int16_t i; + LSSETUP_CUSTOM_STRUCT customLs; + + /* Copy layout description */ + customLs.num_spk = rendCustomLsLayout.num_spk; + mvr2r( rendCustomLsLayout.azimuth, customLs.ls_azimuth, rendCustomLsLayout.num_spk ); + mvr2r( rendCustomLsLayout.elevation, customLs.ls_elevation, rendCustomLsLayout.num_spk ); + + customLs.is_planar_setup = 1; + for ( i = 0; i < rendCustomLsLayout.num_spk; ++i ) + { + if ( fabsf( rendCustomLsLayout.elevation[i] ) > EPSILON ) + { + customLs.is_planar_setup = 0; + break; + } + } + + customLs.num_lfe = rendCustomLsLayout.num_lfe; + mvs2s( rendCustomLsLayout.lfe_idx, customLs.lfe_idx, rendCustomLsLayout.num_lfe ); + + return customLs; +} + +static ivas_error validateCustomLsLayout( + const IVAS_CUSTOM_LS_DATA layout ) +{ + int16_t i; + + /* Negative number of speakers or LFEs makes no sense */ + if ( layout.num_spk < 0 || layout.num_lfe < 0 ) + { + return IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT; + } + + /* There must be at least one speaker or LFE in the layout */ + if ( layout.num_spk + layout.num_lfe <= 0 ) + { + return IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT; + } + + /* LFE indices must be positive */ + for ( i = 0; i < layout.num_lfe; ++i ) + { + if ( layout.lfe_idx[i] < 0 ) + { + return IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT; + } + } + + return IVAS_ERR_OK; +} + +ivas_error IVAS_REND_ConfigureCustomOutputLoudspeakerLayout( + IVAS_REND_HANDLE hIvasRend, + const IVAS_CUSTOM_LS_DATA layout ) +{ + int16_t i, numOutChannels; + ivas_error error; + input_mc *inputMc; + input_sba *inputSba; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( hIvasRend->outputConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + /* Specifying details of custom speaker layout only makes sense if output config is set to custom speaker layout */ + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + if ( ( error = validateCustomLsLayout( layout ) ) != IVAS_ERR_OK ) + { + return error; + } + + hIvasRend->customLsOut = makeCustomLsSetup( layout ); + + /* Re-initialize limiter - number of output channels may have changed */ + if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = initLimiter( &hIvasRend->hLimiter, numOutChannels, hIvasRend->sampleRateOut ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Re-initialize EFAP - output layout has changed or has been fully defined for the first time */ + if ( ( error = initEfap( &hIvasRend->efapOutWrapper, hIvasRend->outputConfig, &hIvasRend->customLsOut ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Re-initialize panning gains for each active MC input, This includes re-initializing + * LFE handling for the new output layout, which means custom LFE handling is overwritten, + * if previously set for any MC input. */ + for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) + { + inputMc = &hIvasRend->inputsMc[i]; + if ( inputMc->base.inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + /* Input inactive, skip. */ + continue; + } + + inputMc->lfeRouting = defaultLfeRouting( inputMc->base.inConfig, inputMc->customLsInput, hIvasRend->outputConfig, *inputMc->base.ctx.pCustomLsOut ); + + if ( ( error = updateMcPanGains( inputMc, hIvasRend->outputConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Re-initialize panning gains for each active SBA input */ + for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i ) + { + inputSba = &hIvasRend->inputsSba[i]; + + if ( inputSba->base.inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + /* Input inactive, skip. */ + continue; + } + + if ( ( error = updateSbaPanGains( inputSba, hIvasRend->outputConfig, hIvasRend->hRendererConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +ivas_error IVAS_REND_NumOutChannels( + IVAS_REND_CONST_HANDLE hIvasRend, + int16_t *numOutChannels ) +{ + ivas_error error; + + /* Validate function arguments */ + if ( hIvasRend == NULL || numOutChannels == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + /* Handle special cases where additional info is needed from the renderer, otherwise use getAudioConfigNumChannels() */ + switch ( hIvasRend->outputConfig ) + { + case IVAS_REND_AUDIO_CONFIG_LS_CUSTOM: + *numOutChannels = hIvasRend->customLsOut.num_spk + hIvasRend->customLsOut.num_lfe; + break; + default: + if ( ( error = getAudioConfigNumChannels( hIvasRend->outputConfig, numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + break; + } + + return IVAS_ERR_OK; +} + +static IVAS_REND_InputId makeInputId( + IVAS_REND_AudioConfig config, + const int32_t inputIndex ) +{ + /* Put config type in second byte (from LSB), put index + 1 in first byte + * + * Index is incremented here so that a valid ID can never be 0. */ + return (IVAS_REND_InputId) ( ( ( (uint32_t) getAudioConfigType( config ) ) << 8 ) | ( inputIndex + 1 ) ); +} + +static ivas_error getInputById( + IVAS_REND_HANDLE hIvasRend, + IVAS_REND_InputId inputId, + void **ppInput ) +{ + int32_t inputIndex; + IVAS_REND_AudioConfigType configType; + input_base *pInputBase; + + /* Reverse makeInputId() */ + inputIndex = ( inputId & 0xFF ) - 1; + configType = ( inputId & 0xFF00 ) >> 8; + + /* Validate values derived from input ID */ + if ( inputIndex < 0 ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + switch ( configType ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED: + if ( inputIndex > RENDERER_MAX_ISM_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsIsm[inputIndex].base; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + if ( inputIndex > RENDERER_MAX_MC_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsMc[inputIndex].base; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + if ( inputIndex > RENDERER_MAX_SBA_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsSba[inputIndex].base; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_MASA: + if ( inputIndex > RENDERER_MAX_MASA_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsMasa[inputIndex].base; + break; + default: + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Ensure input ID matches and that input is active */ + if ( pInputBase->id != inputId || pInputBase->inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Validation done, set value via output parameter */ + *ppInput = pInputBase; + + return IVAS_ERR_OK; +} + +/* Unfortunately code duplication here is the only way to avoid warnings about const casting */ +static ivas_error getConstInputById( + IVAS_REND_CONST_HANDLE hIvasRend, + const IVAS_REND_InputId inputId, + const void **ppInput ) +{ + int32_t inputIndex; + IVAS_REND_AudioConfigType configType; + const input_base *pInputBase; + + /* Reverse makeInputId() */ + inputIndex = ( inputId & 0xFF ) - 1; + configType = ( inputId & 0xFF00 ) >> 8; + + /* Validate values derived from input ID */ + if ( inputIndex < 0 ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + switch ( configType ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED: + if ( inputIndex > RENDERER_MAX_ISM_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsIsm[inputIndex].base; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + if ( inputIndex > RENDERER_MAX_MC_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsMc[inputIndex].base; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + if ( inputIndex > RENDERER_MAX_SBA_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsSba[inputIndex].base; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_MASA: + if ( inputIndex > RENDERER_MAX_MASA_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsMasa[inputIndex].base; + break; + default: + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Ensure input ID matches and that input is active */ + if ( pInputBase->id != inputId || pInputBase->inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Validation done, set value via output parameter */ + *ppInput = pInputBase; + + return IVAS_ERR_OK; +} + +static ivas_error findFreeInputSlot( + const void *inputs, + const int32_t inputStructSize, + const int32_t maxInputs, + int32_t *inputIndex ) +{ + /* Using a void pointer and a separately provided size is a hack for this function + to be reusable for arrays of any input type (input_ism, input_mc, input_sba, input_masa). + Assumptions: + - input_base is always the first member in the input struct + - provided size is correct + */ + + int32_t i; + bool canAddInput; + const uint8_t *pByte; + const input_base *pInputBase; + + canAddInput = false; + + /* Find first unused input in array */ + for ( i = 0, pByte = inputs; i < maxInputs; ++i, pByte += inputStructSize ) + { + pInputBase = (const input_base *) pByte; + + if ( pInputBase->inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + *inputIndex = i; + canAddInput = true; + break; + } + } + + if ( !canAddInput ) + { + return IVAS_ERR_TOO_MANY_INPUTS; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_AddInput() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_AddInput( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_AudioConfig inConfig, /* i : audio config for a new input */ + IVAS_REND_InputId *inputId /* o : ID of the new input */ +) +{ + ivas_error error; + int32_t maxNumInputsOfType; + void *inputsArray; + int32_t inputStructSize; + ivas_error ( *activateInput )( void *, IVAS_REND_AudioConfig, IVAS_REND_InputId, RENDER_CONFIG_DATA * ); + int32_t inputIndex; + + /* Validate function arguments */ + if ( hIvasRend == NULL || inputId == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + switch ( getAudioConfigType( inConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED: + maxNumInputsOfType = RENDERER_MAX_ISM_INPUTS; + inputsArray = hIvasRend->inputsIsm; + inputStructSize = sizeof( *hIvasRend->inputsIsm ); + activateInput = setRendInputActiveIsm; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + maxNumInputsOfType = RENDERER_MAX_MC_INPUTS; + inputsArray = hIvasRend->inputsMc; + inputStructSize = sizeof( *hIvasRend->inputsMc ); + activateInput = setRendInputActiveMc; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + maxNumInputsOfType = RENDERER_MAX_SBA_INPUTS; + inputsArray = hIvasRend->inputsSba; + inputStructSize = sizeof( *hIvasRend->inputsSba ); + activateInput = setRendInputActiveSba; + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_MASA: + maxNumInputsOfType = RENDERER_MAX_MASA_INPUTS; + inputsArray = hIvasRend->inputsMasa; + inputStructSize = sizeof( *hIvasRend->inputsMasa ); + activateInput = setRendInputActiveMasa; + break; + default: + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + + /* Find first free input in array corresponding to input type */ + if ( ( error = findFreeInputSlot( inputsArray, inputStructSize, maxNumInputsOfType, &inputIndex ) ) != IVAS_ERR_OK ) + { + return error; + } + + *inputId = makeInputId( inConfig, inputIndex ); + + if ( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId, hIvasRend->hRendererConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_ConfigureCustomInputLoudspeakerLayout() + * + * + * Note: this will reset any custom LFE routing set for the input + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_ConfigureCustomInputLoudspeakerLayout( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_CUSTOM_LS_DATA layout /* i : custom loudspeaker layout for input */ +) +{ + input_mc *inputMc; + ivas_error error; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = validateCustomLsLayout( layout ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &inputMc ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( inputMc->base.inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + /* Specifying details of custom speaker layout only makes sense if input config is set to custom speaker layout */ + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + + /* Re-initialize panning gains for the MC input, This includes re-initializing LFE handling + * for the new input layout, which means custom LFE handling is overwritten, if previously + * set for the MC input. */ + inputMc->customLsInput = makeCustomLsSetup( layout ); + + inputMc->lfeRouting = defaultLfeRouting( inputMc->base.inConfig, inputMc->customLsInput, hIvasRend->outputConfig, *inputMc->base.ctx.pCustomLsOut ); + + if ( ( error = initEfap( &inputMc->efapInWrapper, inputMc->base.inConfig, &inputMc->customLsInput ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( hIvasRend->outputConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL || hIvasRend->outputConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) + { + if ( ( error = initMcBinauralRendering( inputMc, inputMc->base.inConfig, hIvasRend->outputConfig, hIvasRend->hRendererConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = updateMcPanGains( inputMc, hIvasRend->outputConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_SetInputGain() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_SetInputGain( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const float gain /* i : linear gain (not in dB) */ +) +{ + input_base *inputBase; + ivas_error error; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + inputBase->gain = gain; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_SetInputLfeMtx() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_SetInputLfeMtx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_LfePanMtx *lfePanMtx /* i : LFE panning matrix */ +) +{ + int16_t i; + input_base *pInputBase; + input_mc *pInputMc; + ivas_error error; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &pInputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( getAudioConfigType( pInputBase->inConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + /* Custom LFE panning matrix only makes sense with channel-based input */ + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + pInputMc = (input_mc *) pInputBase; + + /* copy LFE panning matrix */ + for ( i = 0; i < IVAS_MAX_INPUT_LFE_CHANNELS; i++ ) + { + mvr2r( ( *lfePanMtx )[i], pInputMc->lfeRouting.lfePanMtx[i], IVAS_MAX_OUTPUT_CHANNELS ); + } + + if ( ( error = updateMcPanGains( pInputMc, hIvasRend->outputConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_SetInputLfePos() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_SetInputLfePos( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const float inputGain, /* i : Input gain to be applied to the LFE channel(s) */ + const float outputAzimuth, /* i : Output azimuth position */ + const float outputElevation /* i : Output elevation position */ +) +{ + input_base *pInputBase; + input_mc *pInputMc; + ivas_error error; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &pInputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( getAudioConfigType( pInputBase->inConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + /* Custom LFE routing only makes sense with channel-based input */ + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + pInputMc = (input_mc *) pInputBase; + + pInputMc->lfeRouting.pan_lfe = true; + pInputMc->lfeRouting.lfeInputGain = inputGain; + pInputMc->lfeRouting.lfeOutputAzimuth = outputAzimuth; + pInputMc->lfeRouting.lfeOutputElevation = outputElevation; + + if ( ( error = updateMcPanGains( pInputMc, hIvasRend->outputConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_RemoveInput() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_RemoveInput( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId /* i : ID of the input */ +) +{ + ivas_error error; + input_base *inputBase; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + switch ( getAudioConfigType( inputBase->inConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED: + clearInputIsm( (input_ism *) inputBase ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + clearInputMc( (input_mc *) inputBase ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + clearInputSba( (input_sba *) inputBase ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_MASA: + clearInputMasa( (input_masa *) inputBase ); + break; + default: + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_GetInputNumChannels() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_GetInputNumChannels( + IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + int16_t *numChannels /* o : number of channels of the input */ +) +{ + ivas_error error; + const input_base *pInput; + + /* Validate function arguments */ + if ( hIvasRend == NULL || numChannels == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = getConstInputById( hIvasRend, inputId, (const void **) &pInput ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getRendInputNumChannels( pInput, numChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_GetDelay() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_GetDelay( + IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer state */ + int16_t *nSamples, /* o : Renderer delay in samples */ + int32_t *timeScale /* o : Time scale of the delay, equal to renderer output sampling rate */ +) +{ + /* TODO tmu : this function only returns the maximum delay across all inputs + * Ideally each input has its own delay buffer and everything is aligned (binaural and LFE filtering delays are nonuniform) + */ + int16_t i; + int32_t latency_ns; + int32_t max_latency_ns; + + /* Validate function arguments */ + if ( hIvasRend == NULL || nSamples == NULL || timeScale == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *timeScale = hIvasRend->sampleRateOut; + *nSamples = 0; + max_latency_ns = 0; + + /* Compute the maximum delay across all inputs */ + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) + { + if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + latency_ns = max( ( hIvasRend->inputsIsm[i].crendWrapper != NULL ) ? hIvasRend->inputsIsm[i].crendWrapper->binaural_latency_ns : 0, + hIvasRend->inputsIsm[i].tdRendWrapper.binaural_latency_ns ); + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + + for ( i = 0; i < RENDERER_MAX_MC_INPUTS; i++ ) + { + if ( hIvasRend->inputsMc[i].base.inConfig != IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + latency_ns = max( ( hIvasRend->inputsMc[i].crendWrapper != NULL ) ? hIvasRend->inputsMc[i].crendWrapper->binaural_latency_ns : 0, + hIvasRend->inputsMc[i].tdRendWrapper.binaural_latency_ns ); + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + + for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; i++ ) + { + if ( hIvasRend->inputsSba[i].base.inConfig != IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; i++ ) + { + if ( hIvasRend->inputsMasa[i].base.inConfig != IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + latency_ns = (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ); + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + + *nSamples = (int16_t) roundf( (float) max_latency_ns * *timeScale / 1000000000.f ); + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_FeedInputAudio() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_FeedInputAudio( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ +) +{ + ivas_error error; + input_base *inputBase; + int16_t numInputChannels; + + /* Validate function arguments */ + if ( hIvasRend == NULL || inputAudio.data == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( inputAudio.config.numSamplesPerChannel <= 0 || MAX_BUFFER_LENGTH_PER_CHANNEL < inputAudio.config.numSamplesPerChannel ) + { + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + + if ( inputAudio.config.numChannels <= 0 || MAX_INPUT_CHANNELS < inputAudio.config.numChannels ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && + inputAudio.config.numSamplesPerChannel * 1000 != BINAURAL_RENDERING_FRAME_SIZE_MS * hIvasRend->sampleRateOut ) + { + /* Binaural rendering requires specific frame size */ + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getRendInputNumChannels( inputBase, &numInputChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( numInputChannels != inputAudio.config.numChannels ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + inputBase->inputBuffer.config = inputAudio.config; + + mvr2r( inputAudio.data, inputBase->inputBuffer.data, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); + + inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_FeedInputObjectMetadata() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_FeedInputObjectMetadata( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_AudioObjectPosition objectPosition /* i : object position struct */ +) +{ + input_base *inputBase; + input_ism *inputIsm; + ivas_error error; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( inputBase->inConfig != IVAS_REND_AUDIO_CONFIG_OBJECT ) + { + /* Object metadata should only be fed for object inputs */ + return IVAS_ERR_METADATA_NOT_EXPECTED; + } + + inputIsm = (input_ism *) inputBase; + inputIsm->previousPos = inputIsm->currentPos; + inputIsm->currentPos = objectPosition; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_FeedInputMasaMetadata() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_FeedInputMasaMetadata( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + IVAS_MASA_METADATA_HANDLE masaMetadata /* i : MASA metadata frame */ +) +{ + ivas_error error; + input_base *inputBase; + input_masa *inputMasa; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( getAudioConfigType( inputBase->inConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) + { + /* MASA metadata should only be fed for MASA inputs */ + return IVAS_ERR_METADATA_NOT_EXPECTED; + } + + inputMasa = (input_masa *) inputBase; + inputMasa->masaMetadata = *masaMetadata; + inputMasa->metadataHasBeenFed = true; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_InitConfig() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_InitConfig( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ +#ifdef FIX_392_LATE_REVERB + const IVAS_REND_AudioConfig outAudioConfig /* i : output audioConfig */ +#else + const bool rendererConfigEnabled /* i : flag indicating if a renderer configuration file was supplied */ +#endif +) +{ + ivas_error error; +#ifdef FIX_392_LATE_REVERB + bool rendererConfigEnabled; + + rendererConfigEnabled = ( getAudioConfigType( outAudioConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ); +#endif + + if ( rendererConfigEnabled ) + { + hIvasRend->rendererConfigEnabled = 1; + } + else + { + hIvasRend->rendererConfigEnabled = 0; + } + + if ( rendererConfigEnabled ) + { + if ( ( error = ivas_render_config_open( &( hIvasRend->hRendererConfig ) ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef FIX_392_LATE_REVERB + if ( ( error = ivas_render_config_init_from_rom( &hIvasRend->hRendererConfig, outAudioConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_render_config_init_from_rom( &hIvasRend->hRendererConfig, hIvasRend->rendererConfigEnabled ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + } + else + { + hIvasRend->hRendererConfig = NULL; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_GetRenderConfig() + * + * + *-------------------------------------------------------------------*/ + +int16_t IVAS_REND_GetRenderConfig( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS decoder handle */ + const IVAS_RENDER_CONFIG_HANDLE hRCout /* o : Render configuration handle */ +) +{ + RENDER_CONFIG_HANDLE hRCin; + + if ( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL || hRCout == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hRCin = hIvasRend->hRendererConfig; +#ifdef DEBUGGING + switch ( hRCin->renderer_type_override ) + { + case RENDER_TYPE_OVERRIDE_CREND: + hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_CREND; + break; + case RENDER_TYPE_OVERRIDE_FASTCONV: + hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_FASTCONV; + break; + default: + hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE; + break; + } +#endif + hRCout->room_acoustics.override = hRCin->roomAcoustics.override; + hRCout->room_acoustics.use_brir = hRCin->roomAcoustics.use_brir; + hRCout->room_acoustics.late_reverb_on = hRCin->roomAcoustics.late_reverb_on; + hRCout->room_acoustics.nBands = hRCin->roomAcoustics.nBands; + hRCout->room_acoustics.acousticPreDelay = hRCin->roomAcoustics.acousticPreDelay; + hRCout->room_acoustics.inputPreDelay = hRCin->roomAcoustics.inputPreDelay; + + mvr2r( hRCin->roomAcoustics.pFc_input, hRCout->room_acoustics.pFc_input, CLDFB_NO_CHANNELS_MAX ); + mvr2r( hRCin->roomAcoustics.pAcoustic_rt60, hRCout->room_acoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); + mvr2r( hRCin->roomAcoustics.pAcoustic_dsr, hRCout->room_acoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_FeedRenderConfig() + * + * + *-------------------------------------------------------------------*/ + +int16_t IVAS_REND_FeedRenderConfig( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS decoder handle */ + const IVAS_RENDER_CONFIG_DATA renderConfig /* i : Render configuration struct */ +) +{ + RENDER_CONFIG_HANDLE hRenderConfig; + + if ( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hRenderConfig = hIvasRend->hRendererConfig; + mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 ); +#ifdef DEBUGGING + hRenderConfig->renderer_type_override = RENDER_TYPE_OVERRIDE_NONE; + if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_FASTCONV ) + { + hRenderConfig->renderer_type_override = RENDER_TYPE_OVERRIDE_FASTCONV; + } + if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_CREND ) + { + hRenderConfig->renderer_type_override = RENDER_TYPE_OVERRIDE_CREND; + } +#endif + hRenderConfig->roomAcoustics.override = renderConfig.room_acoustics.override; + hRenderConfig->roomAcoustics.use_brir = renderConfig.room_acoustics.use_brir; + hRenderConfig->roomAcoustics.late_reverb_on = renderConfig.room_acoustics.late_reverb_on; + hRenderConfig->roomAcoustics.nBands = renderConfig.room_acoustics.nBands; + hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.room_acoustics.acousticPreDelay; + hRenderConfig->roomAcoustics.inputPreDelay = renderConfig.room_acoustics.inputPreDelay; + mvr2r( renderConfig.room_acoustics.pFc_input, hRenderConfig->roomAcoustics.pFc_input, CLDFB_NO_CHANNELS_MAX ); + mvr2r( renderConfig.room_acoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); + mvr2r( renderConfig.room_acoustics.pAcoustic_dsr, hRenderConfig->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_SetHeadRotation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_SetHeadRotation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME], /* i : head orientations for next rendering call */ + const IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME] /* i : listener positions for next rendering call */ +) +{ + int16_t i; + IVAS_QUATERNION rotQuat; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( getAudioConfigType( hIvasRend->outputConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) + { + /* Head rotation can be set only with binaural output */ + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + if ( headRot == NULL ) + { + hIvasRend->headRotData.headRotEnabled = 0; + } + else + { + hIvasRend->headRotData.headRotEnabled = 1; + for ( i = 0; i < RENDERER_HEAD_POSITIONS_PER_FRAME; ++i ) + { + /* check for Euler angle signaling */ + if ( headRot[i].w == -3.0f ) + { + Euler2Quat( deg2rad( headRot[i].x ), deg2rad( headRot[i].y ), deg2rad( headRot[i].z ), &rotQuat ); + } + else + { + rotQuat = headRot[i]; + } + + ivas_orient_trk_Process( hIvasRend->headRotData.hOrientationTracker, rotQuat, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hIvasRend->headRotData.headPositions[i] ); + hIvasRend->headRotData.Pos[i] = Pos[i]; + } + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_SetOrientationTrackingMode() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_SetOrientationTrackingMode( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const uint8_t otrMode /* i : Orientation tracking mode */ +) +{ + OTR_TRACKING_T mode; + ivas_error error; + + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + switch ( otrMode ) + { + case IVAS_ORIENT_TRK_AVG: + mode = OTR_TRACKING_AVG_ORIENT; + break; + case IVAS_ORIENT_TRK_REF: + mode = OTR_TRACKING_REF_ORIENT; + break; + case IVAS_ORIENT_TRK_REF_VEC: + mode = OTR_TRACKING_REF_VEC; + break; + case IVAS_ORIENT_TRK_REF_VEC_LEV: + mode = OTR_TRACKING_REF_VEC_LEV; + break; + case IVAS_ORIENT_TRK_NONE: + default: + mode = OTR_TRACKING_NONE; + break; + } + + if ( ( error = ivas_orient_trk_SetTrackingType( hIvasRend->headRotData.hOrientationTracker, mode ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_SetReferenceRotation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_SetReferenceRotation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_QUATERNION refRot /* i : Reference rotation */ +) +{ + ivas_error error; + + /* Validate function arguments */ + if ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = ivas_orient_trk_SetReferenceRotation( hIvasRend->headRotData.hOrientationTracker, refRot ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_GetMainOrientation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_GetMainOrientation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_QUATERNION *pOrientation /* i/o: Quaternion pointer for main orientation */ +) +{ + ivas_error error; + + if ( hIvasRend == NULL || pOrientation == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = ivas_orient_trk_GetMainOrientation( hIvasRend->headRotData.hOrientationTracker, pOrientation ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_GetTrackedRotation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_GetTrackedRotation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_QUATERNION *pRotation /* i/o: Quaternion pointer processed rotation */ +) +{ + ivas_error error; + + if ( hIvasRend == NULL || pRotation == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( error = ivas_orient_trk_GetTrackedRotation( hIvasRend->headRotData.hOrientationTracker, pRotation ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * IVAS_REND_SetReferenceVector( ) + * + * Sets a reference vector spanning from listenerPos to refPos. Only + * available in OTR_TRACKING_REF_VEC and OTR_TRACKING_REF_VEC_LEV modes. + *---------------------------------------------------------------------*/ + +ivas_error IVAS_REND_SetReferenceVector( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_VECTOR3 listenerPos, /* i : Listener position */ + const IVAS_VECTOR3 refPos /* i : Reference position */ +) +{ + if ( hIvasRend == NULL || hIvasRend->headRotData.hOrientationTracker == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + return ivas_orient_trk_SetReferenceVector( hIvasRend->headRotData.hOrientationTracker, listenerPos, refPos ); +} + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +/* Take one channel from input buffer and copy it to each channel + in output buffer, with different gain applied per output channel. + This function takes 2 gain vectors - one for the beginning and one + for the end of the buffer. Gain values are lineraly interpolated + for all samples in between. */ +static void renderBufferChannelLerp( + const IVAS_REND_AudioBuffer inAudio, + const int32_t inChannelIdx, + const float *const gainsCurrent, + const float *const gainsPrev, + IVAS_REND_AudioBuffer outAudio ) +{ + const float *inSmpl; + float *outSmpl; + float fadeIn; + float fadeOut; + int32_t i; + const float *lastInSmpl; + int16_t outChnlIdx; + float currentGain; + float previousGain; + + /* Pointer to behind last input sample */ + lastInSmpl = getSmplPtr( inAudio, inChannelIdx, inAudio.config.numSamplesPerChannel ); + + for ( outChnlIdx = 0; outChnlIdx < outAudio.config.numChannels; ++outChnlIdx ) + { + currentGain = gainsCurrent[outChnlIdx]; + previousGain = gainsPrev == NULL ? 0.f : gainsPrev[outChnlIdx]; + + /* Process current output channel only if applying non-zero gains */ + if ( fabsf( currentGain ) > EPSILON || ( gainsPrev != NULL && fabsf( previousGain ) > EPSILON ) ) + { + /* Reset input pointer to the beginning of input channel */ + inSmpl = getSmplPtr( inAudio, inChannelIdx, 0 ); + + /* Set output pointer to first output channel sample */ + outSmpl = getSmplPtr( outAudio, outChnlIdx, 0 ); + + if ( gainsPrev == NULL || fabsf( previousGain - currentGain ) <= EPSILON ) + { + /* If no interpolation from previous frame, apply current gain */ + do + { + *outSmpl += currentGain * ( *inSmpl ); + ++outSmpl; + ++inSmpl; + + } while ( inSmpl != lastInSmpl ); + } + else + { + i = 0; + + /* Otherwise use weighted average between previous and current gain */ + do + { + /* TODO(sgi): This is calculated for each output channel - can be optimised */ + fadeIn = (float) i / ( outAudio.config.numSamplesPerChannel - 1 ); + fadeOut = 1.0f - fadeIn; + + *outSmpl += ( fadeIn * currentGain + fadeOut * previousGain ) * ( *inSmpl ); + ++outSmpl; + ++inSmpl; + ++i; + } while ( inSmpl != lastInSmpl ); + } + } + } + + return; +} + +/* Take one channel from input buffer and copy it to each channel + in output buffer, with different gain applied per output channel */ +static void renderBufferChannel( + const IVAS_REND_AudioBuffer inAudio, + const int32_t inChannelIdx, + const float *const outputGains, + IVAS_REND_AudioBuffer outAudio ) +{ + renderBufferChannelLerp( inAudio, inChannelIdx, outputGains, NULL, outAudio ); + + return; +} + +static ivas_error rotateFrameMc( + IVAS_REND_AudioBuffer inAudio, /* i : Input Audio buffer */ + IVAS_REND_AudioConfig inConfig, /* i : Input Audio config */ + LSSETUP_CUSTOM_STRUCT inCustomLs, /* i : Input Custom LS setup */ + const IVAS_REND_HeadRotData *headRotData, /* i : Head rotation data */ + rotation_gains gains_prev, /* i/o: Previous frame rotation gains */ + const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + IVAS_REND_AudioBuffer outAudio /* o : Output Audio buffer */ +) +{ + int16_t i; + int16_t subframe_idx, subframe_len; + int16_t azimuth, elevation; + int16_t is_planar_setup, lfe_idx; + int16_t nchan; + int16_t ch_in, ch_out; + int16_t ch_in_woLFE, ch_out_woLFE; + float *readPtr, *writePtr; + const float *ls_azimuth, *ls_elevation; + rotation_matrix Rmat; + rotation_gains gains; + float tmp_gains[MAX_INPUT_CHANNELS]; + ivas_error error; + + push_wmops( "rotateFrameMc" ); + + if ( inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + if ( ( error = getAudioConfigNumChannels( inConfig, &nchan ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + nchan = inCustomLs.num_spk + inCustomLs.num_lfe; + } + + if ( ( error = getMcConfigValues( inConfig, inCustomLs, &ls_azimuth, &ls_elevation, &lfe_idx, &is_planar_setup ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* initialize gains to passthrough */ + for ( ch_in = 0; ch_in < nchan; ch_in++ ) + { + set_zero( gains[ch_in], nchan ); + gains[ch_in][ch_in] = 1.f; + } + + /* subframe loop */ + subframe_len = inAudio.config.numSamplesPerChannel / RENDERER_HEAD_POSITIONS_PER_FRAME; + for ( subframe_idx = 0; subframe_idx < RENDERER_HEAD_POSITIONS_PER_FRAME; subframe_idx++ ) + { + /* Get next quaternion and calculate rotation matrix */ + QuatToRotMat( headRotData->headPositions[subframe_idx], Rmat ); + + for ( ch_in = 0; ch_in < nchan; ch_in++ ) + { + /* skip LFE */ + if ( ch_in == lfe_idx ) + { + continue; + } + + /* input channel index without LFE */ + ch_in_woLFE = ( ( lfe_idx > 0 ) && ( ch_in >= lfe_idx ) ) ? ch_in - 1 : ch_in; + + /* gains for current subframe rotation */ + rotateAziEle( ls_azimuth[ch_in_woLFE], ls_elevation[ch_in_woLFE], &azimuth, &elevation, Rmat, is_planar_setup ); + + if ( hEFAPdata != NULL && ( ls_azimuth[ch_in_woLFE] != azimuth || ls_elevation[ch_in_woLFE] != elevation ) ) + { + efap_determine_gains( hEFAPdata, tmp_gains, azimuth, elevation, EFAP_MODE_EFAP ); + + for ( ch_out = 0; ch_out < nchan; ch_out++ ) + { + /* skip LFE */ + if ( ch_out == lfe_idx ) + { + continue; + } + + /* output channel index without LFE */ + ch_out_woLFE = ( ( lfe_idx > 0 ) && ( ch_out >= lfe_idx ) ) ? ch_out - 1 : ch_out; + + gains[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; + } + } + } + + /* apply panning gains by mtx multiplication */ + for ( ch_out = 0; ch_out < nchan; ch_out++ ) + { + for ( ch_in = 0; ch_in < nchan; ch_in++ ) + { + writePtr = getSmplPtr( outAudio, ch_out, subframe_idx * subframe_len ); + readPtr = getSmplPtr( inAudio, ch_in, subframe_idx * subframe_len ); + /* crossfade with previous rotation gains */ + for ( i = 0; i < subframe_len; i++ ) + { + *writePtr++ += + ( *readPtr ) * ( ( 1 - headRotData->crossfade[i] ) * gains_prev[ch_in][ch_out] ) + + ( *readPtr ) * ( headRotData->crossfade[i] * gains[ch_in][ch_out] ); + readPtr++; + } + } + } + + /* move gains to gains_prev */ + for ( i = 0; i < nchan; i++ ) + { + mvr2r( gains[i], gains_prev[i], nchan ); + } + } + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error rotateFrameSba( + IVAS_REND_AudioBuffer inAudio, /* i : Input Audio buffer */ + IVAS_REND_AudioConfig inConfig, /* i : Input Audio config */ + const IVAS_REND_HeadRotData *headRotData, /* i : Head rotation data */ + rotation_gains gains_prev, /* i/o: Previous frame rotation gains */ + IVAS_REND_AudioBuffer outAudio /* o : Output Audio buffer */ +) +{ + int16_t i, l, n, m; + int16_t m1, m2; + int16_t shd_rot_max_order; + int16_t subframe_idx, subframe_len; + float *readPtr, *writePtr; + rotation_matrix Rmat; + float tmpRot[2 * HEADROT_ORDER + 1]; + rotation_gains gains; + ivas_error error; + + push_wmops( "rotateFrameSba" ); + + if ( ( error = getAmbisonicsOrder( inConfig, &shd_rot_max_order ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* subframe loop */ + subframe_len = inAudio.config.numSamplesPerChannel / RENDERER_HEAD_POSITIONS_PER_FRAME; + for ( subframe_idx = 0; subframe_idx < RENDERER_HEAD_POSITIONS_PER_FRAME; subframe_idx++ ) + { + /* initialize rotation matrices with zeros */ + for ( i = 0; i < HEADROT_SHMAT_DIM; i++ ) + { + set_zero( gains[i], HEADROT_SHMAT_DIM ); + } + + /* Get next quaternion and calculate rotation matrix */ + QuatToRotMat( headRotData->headPositions[subframe_idx], Rmat ); + + /* calculate ambisonics rotation matrices for the previous and current frames */ + SHrotmatgen( gains, Rmat, shd_rot_max_order ); + + for ( i = 0; i < subframe_len; i++ ) + { + /* As the rotation matrix becomes block diagonal in a SH basis, we can*/ + /* apply each angular-momentum block individually to save complexity. */ + + /* loop over l blocks */ + m1 = 1; + m2 = 4; + for ( l = 1; l <= shd_rot_max_order; l++ ) + { + /* compute mtx-vector product for this l */ + for ( n = m1; n < m2; n++ ) + { + tmpRot[n - m1] = 0.f; + + for ( m = m1; m < m2; m++ ) + { + readPtr = getSmplPtr( inAudio, m, subframe_idx * subframe_len + i ); + /* crossfade with previous rotation gains */ + tmpRot[n - m1] += headRotData->crossfade[i] * gains[n][m] * ( *readPtr ) + + ( 1 - headRotData->crossfade[i] ) * gains_prev[n][m] * ( *readPtr ); + } + } + /* write back the result */ + for ( n = m1; n < m2; n++ ) + { + writePtr = getSmplPtr( outAudio, n, subframe_idx * subframe_len + i ); + ( *writePtr ) = tmpRot[n - m1]; + } + m1 = m2; + m2 += 2 * ( l + 1 ) + 1; + } + } + + /*unoptimized code for reference (full matrix multiplication)*/ + // for ( n = 0; n < nchan; n++ ) + // { + // tmpRot[n] = 0.f; + // + // for ( m = 0; m < nchan; m++ ) + // { + // tmpRot[n] += SHrotmat[n][m] * output[m][i]; + // } + // } + // for ( n = 0; n < nchan; n++ ) + // { + // output[n][i] = tmpRot[n]; + // } + + /* move SHrotmat to SHrotmat_prev */ + for ( i = 0; i < HEADROT_SHMAT_DIM; i++ ) + { + mvr2r( gains[i], gains_prev[i], HEADROT_SHMAT_DIM ); + } + } + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderIsmToBinaural( + const input_ism *ismInput, + IVAS_REND_AudioBuffer outAudio ) +{ + float tmpTDRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + ivas_error error; + + push_wmops( "renderIsmToBinaural" ); + + copyBufferTo2dArray( ismInput->base.inputBuffer, tmpTDRendBuffer ); + + /* TODO tmu : missing: interpolation between positions, 5ms rendering */ + if ( ( error = ivas_td_binaural_renderer_ext( &ismInput->tdRendWrapper, + ismInput->base.inConfig, + NULL, + ismInput->base.ctx.pHeadRotData, + &ismInput->currentPos, + ismInput->hReverb, + outAudio.config.numSamplesPerChannel, + tmpTDRendBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulate2dArrayToBuffer( tmpTDRendBuffer, &outAudio ); + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderIsmToBinauralRoom( + input_ism *ismInput, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + int16_t azi_rot, ele_rot; + int16_t subframe_idx, subframe_len; + int16_t tmp; + rotation_matrix Rmat; + float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + IVAS_QUATERNION quat; + ivas_error error; + pan_vector currentPanGains; + pan_vector previousPanGains; + IVAS_REND_AudioBuffer tmpMcBuffer; + IVAS_REND_AudioObjectPosition rotatedPos; + const IVAS_REND_HeadRotData *headRotData; + + push_wmops( "renderIsmToBinauralRoom" ); + + headRotData = ismInput->base.ctx.pHeadRotData; + rotatedPos = defaultObjectPosition(); + + if ( ismInput->hReverb != NULL && ismInput->hReverb->pConfig.roomAcoustics.use_brir == 0 && ismInput->hReverb->pConfig.roomAcoustics.late_reverb_on == 1 && headRotData->headRotEnabled ) + { + copyBufferTo2dArray( ismInput->base.inputBuffer, tmpRendBuffer ); + + /* TODO tmu : missing: interpolation between positions, 5ms rendering */ + if ( ( error = ivas_td_binaural_renderer_ext( &ismInput->tdRendWrapper, + ismInput->base.inConfig, + NULL, + ismInput->base.ctx.pHeadRotData, + &ismInput->currentPos, + ismInput->hReverb, + outAudio.config.numSamplesPerChannel, + tmpRendBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + accumulate2dArrayToBuffer( tmpRendBuffer, &outAudio ); + } + else + { + + if ( headRotData->headRotEnabled ) + { + subframe_len = ismInput->base.inputBuffer.config.numSamplesPerChannel / RENDERER_HEAD_POSITIONS_PER_FRAME; + // for ( subframe_idx = 0; subframe_idx < RENDERER_HEAD_POSITIONS_PER_FRAME; subframe_idx++ ) + for ( subframe_idx = 0; subframe_idx < 1; subframe_idx++ ) + { + quat.w = headRotData->headPositions[subframe_idx].w; + quat.x = headRotData->headPositions[subframe_idx].x; + quat.y = headRotData->headPositions[subframe_idx].y; + quat.z = headRotData->headPositions[subframe_idx].z; + + QuatToRotMat( quat, Rmat ); + } + (void) subframe_len; // avoid warning + } + + /* TODO tmu : missing: interpolation between positions, 5ms rendering */ + /* TODO(sgi): Possible optimization: less processing needed if position didn't change */ + /* TODO tmu2sgi: needs a lot of cleanup, we could also add rot_gains_prev to ismInput and use that */ + /* previous position gains */ + if ( headRotData->headRotEnabled ) + { + rotateAziEle( ismInput->previousPos.azimuth, ismInput->previousPos.elevation, &azi_rot, &ele_rot, ismInput->rot_mat_prev, 0 ); + rotatedPos.azimuth = (float) azi_rot; + rotatedPos.elevation = (float) ele_rot; + } + + if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper, + ( headRotData->headRotEnabled ) ? rotatedPos.azimuth : ismInput->previousPos.azimuth, + ( headRotData->headRotEnabled ) ? rotatedPos.elevation : ismInput->previousPos.elevation, + previousPanGains ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* current position gains */ + if ( headRotData->headRotEnabled ) + { + rotateAziEle( ismInput->currentPos.azimuth, ismInput->currentPos.elevation, &azi_rot, &ele_rot, Rmat, 0 ); + rotatedPos.azimuth = (float) azi_rot; + rotatedPos.elevation = (float) ele_rot; + } + + if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper, + ( headRotData->headRotEnabled ) ? rotatedPos.azimuth : ismInput->currentPos.azimuth, + ( headRotData->headRotEnabled ) ? rotatedPos.elevation : ismInput->currentPos.elevation, + currentPanGains ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( i = 0; i < 3; i++ ) + { + mvr2r( Rmat[i], ismInput->rot_mat_prev[i], 3 ); + } + + /* intermediate rendering to 7_1_4 */ + tmpMcBuffer = ismInput->base.inputBuffer; + + if ( ( error = getAudioConfigNumChannels( IVAS_REND_AUDIO_CONFIG_7_1_4, &tmp ) ) != IVAS_ERR_OK ) + { + return error; + } + + tmpMcBuffer.config.numChannels = tmp; + tmpMcBuffer.data = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( float ) ); + set_zero( tmpMcBuffer.data, tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels ); + + renderBufferChannelLerp( ismInput->base.inputBuffer, 0, currentPanGains, previousPanGains, tmpMcBuffer ); + + copyBufferTo2dArray( tmpMcBuffer, tmpRendBuffer ); + + if ( ( error = ivas_rend_crendProcess( ismInput->crendWrapper, AUDIO_CONFIG_7_1_4, AUDIO_CONFIG_BINAURAL_ROOM, + NULL, NULL, NULL, NULL, tmpRendBuffer, *ismInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulate2dArrayToBuffer( tmpRendBuffer, &outAudio ); + + free( tmpMcBuffer.data ); + } + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderIsmToMc( + const input_ism *ismInput, + const IVAS_REND_AudioBuffer outAudio ) +{ + pan_vector currentPanGains; + pan_vector previousPanGains; + ivas_error error; + + push_wmops( "renderIsmToMc" ); + + /* TODO(sgi): Possible optimization: less processing needed if position didn't change */ + if ( *ismInput->base.ctx.pOutConfig == IVAS_REND_AUDIO_CONFIG_STEREO ) + { + set_zero( currentPanGains, 16 ); + ivas_ism_get_stereo_gains( ismInput->currentPos.azimuth, + ismInput->currentPos.elevation, + ¤tPanGains[0], + ¤tPanGains[1] ); + + set_zero( previousPanGains, 16 ); + ivas_ism_get_stereo_gains( ismInput->previousPos.azimuth, + ismInput->previousPos.elevation, + &previousPanGains[0], + &previousPanGains[1] ); + } + else + { + // TODO tmu review when #215 is resolved + if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper, + (int16_t) floorf( ismInput->currentPos.azimuth + 0.5f ), + (int16_t) floorf( ismInput->currentPos.elevation + 0.5f ), + currentPanGains ) ) != IVAS_ERR_OK ) + { + return error; + } + + // TODO tmu review when #215 is resolved + if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper, + (int16_t) floorf( ismInput->previousPos.azimuth + 0.5f ), + (int16_t) floorf( ismInput->previousPos.elevation + 0.5f ), + previousPanGains ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Assume num channels in audio buffer to be 1. + * This should have been validated in IVAS_REND_FeedInputAudio() */ + renderBufferChannelLerp( ismInput->base.inputBuffer, 0, currentPanGains, previousPanGains, outAudio ); + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderIsmToSba( + const input_ism *ismInput, + const IVAS_REND_AudioConfig outConfig, + const IVAS_REND_AudioBuffer outAudio ) +{ + int16_t ambiOrderOut; + int16_t numOutChannels; + pan_vector currentPanGains; + pan_vector previousPanGains; + ivas_error error; + error = IVAS_ERR_OK; + + push_wmops( "renderIsmToSba" ); + + if ( ( error = getAudioConfigNumChannels( outConfig, &numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getAmbisonicsOrder( outConfig, &ambiOrderOut ) ) != IVAS_ERR_OK ) + { + return error; + } + + // TODO tmu review when #215 is resolved + ivas_dirac_dec_get_response( (int16_t) floorf( ismInput->previousPos.azimuth + 0.5f ), + (int16_t) floorf( ismInput->previousPos.elevation + 0.5f ), + previousPanGains, + ambiOrderOut ); + + if ( ( ismInput->currentPos.azimuth == ismInput->previousPos.azimuth ) && + ( ismInput->currentPos.elevation == ismInput->previousPos.elevation ) ) + { + mvr2r( previousPanGains, currentPanGains, MAX_OUTPUT_CHANNELS ); + } + else + { + // TODO tmu review when #215 is resolved + ivas_dirac_dec_get_response( (int16_t) floorf( ismInput->currentPos.azimuth + 0.5f ), + (int16_t) floorf( ismInput->currentPos.elevation + 0.5f ), + currentPanGains, + ambiOrderOut ); + } + + /* Assume num channels in audio buffer to be 1. + * This should have been validated in IVAS_REND_FeedInputAudio() */ + renderBufferChannelLerp( ismInput->base.inputBuffer, 0, currentPanGains, previousPanGains, outAudio ); + + pop_wmops(); + + return error; +} + +static ivas_error renderInputIsm( + input_ism *ismInput, + const IVAS_REND_AudioConfig outConfig, + const IVAS_REND_AudioBuffer outAudio ) +{ + ivas_error error; + IVAS_REND_AudioBuffer inAudio; + + inAudio = ismInput->base.inputBuffer; + + if ( ismInput->base.numNewSamplesPerChannel != outAudio.config.numSamplesPerChannel ) + { + /* Mismatch between the number of input samples vs number of requested output samples - currently not allowed */ + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + ismInput->base.numNewSamplesPerChannel = 0; + + /* Apply input gain to new audio */ + v_multc( inAudio.data, ismInput->base.gain, inAudio.data, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); + + switch ( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + error = renderIsmToMc( ismInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + error = renderIsmToSba( ismInput, outConfig, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + error = renderIsmToBinaural( ismInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + error = renderIsmToBinauralRoom( ismInput, outAudio ); + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + /* Check error here to keep switch statement more compact */ + if ( error != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static ivas_error renderActiveInputsIsm( + IVAS_REND_HANDLE hIvasRend, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + input_ism *pCurrentInput; + ivas_error error; + + for ( i = 0, pCurrentInput = hIvasRend->inputsIsm; i < RENDERER_MAX_ISM_INPUTS; ++i, ++pCurrentInput ) + { + if ( pCurrentInput->base.inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +static ivas_error renderLfeToBinaural( + const input_mc *mcInput, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + int16_t lfe_idx; + float gain; + float *readPtr, *writePtr; + + assert( ( outAudio.config.numChannels == 2 ) && "Must be binaural output" ); + + push_wmops( "renderLfeToBinaural" ); + + gain = GAIN_LFE; + + if ( mcInput->base.inConfig != IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + lfe_idx = LFE_CHANNEL; + } + else if ( mcInput->customLsInput.num_lfe > 0 ) + { + lfe_idx = mcInput->customLsInput.lfe_idx[0]; + } + else + { + /* no LFE to render */ + return IVAS_ERR_OK; + } + + /* Copy LFE to left and right ears */ + readPtr = getSmplPtr( mcInput->base.inputBuffer, lfe_idx, 0 ); + writePtr = getSmplPtr( outAudio, 0, 0 ); + for ( i = 0; i < mcInput->base.inputBuffer.config.numSamplesPerChannel; i++ ) + { + *writePtr++ += gain * ( *readPtr++ ); + } + + readPtr = getSmplPtr( mcInput->base.inputBuffer, lfe_idx, 0 ); + writePtr = getSmplPtr( outAudio, 1, 0 ); + for ( i = 0; i < mcInput->base.inputBuffer.config.numSamplesPerChannel; i++ ) + { + *writePtr++ += gain * ( *readPtr++ ); + } + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderMcToBinaural( + input_mc *mcInput, + const IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + int8_t headRotEnabled; + float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + IVAS_REND_AudioConfig inConfig; + ivas_error error; + IVAS_REND_AudioBuffer tmpRotBuffer; + + push_wmops( "renderMcToBinaural" ); + + headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled; + inConfig = mcInput->base.inConfig; + + if ( ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) || ( headRotEnabled && ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) ) ) + { + copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); + + if ( ( error = ivas_td_binaural_renderer_ext( &mcInput->tdRendWrapper, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, NULL, + mcInput->hReverb, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + /* apply rotation */ + if ( headRotEnabled ) + { + tmpRotBuffer = mcInput->base.inputBuffer; + tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); + + if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, + mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + copyBufferTo2dArray( tmpRotBuffer, tmpRendBuffer ); + free( tmpRotBuffer.data ); + } + else + { + copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); + } + + /* call CREND */ + if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( mcInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + accumulate2dArrayToBuffer( tmpRendBuffer, &outAudio ); + + /* TODO tmu : needs delay compensation */ + if ( ( error = renderLfeToBinaural( mcInput, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderMcToBinauralRoom( + input_mc *mcInput, + const IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + int8_t headRotEnabled; + float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + IVAS_REND_AudioConfig inConfig; + ivas_error error; + IVAS_REND_AudioBuffer tmpRotBuffer; + + push_wmops( "renderMcToBinauralRoom" ); + + headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled; + inConfig = mcInput->base.inConfig; + + if ( ( mcInput->hReverb != NULL && mcInput->hReverb->pConfig.roomAcoustics.use_brir == 0 && mcInput->hReverb->pConfig.roomAcoustics.late_reverb_on == 1 ) && ( ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) || ( headRotEnabled && ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 || inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) ) ) ) + { + copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); + + if ( ( error = ivas_td_binaural_renderer_ext( &mcInput->tdRendWrapper, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, + NULL, mcInput->hReverb, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + /* apply rotation */ + if ( headRotEnabled ) + { + tmpRotBuffer = mcInput->base.inputBuffer; + tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); + + if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, + mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + copyBufferTo2dArray( tmpRotBuffer, tmpRendBuffer ); + free( tmpRotBuffer.data ); + } + else + { + copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); + } + + /* call CREND */ + if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( mcInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + accumulate2dArrayToBuffer( tmpRendBuffer, &outAudio ); + + /* TODO tmu : needs delay compensation */ + if ( ( error = renderLfeToBinaural( mcInput, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderMcCustomLsToBinauralRoom( + input_mc *mcInput, + const IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + int8_t headRotEnabled; + int16_t i; + int16_t tmp; + float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + ivas_error error; + IVAS_REND_AudioBuffer tmpRotBuffer; + IVAS_REND_AudioBuffer tmpMcBuffer; + IVAS_REND_AudioBuffer *tmpBufPtr; + + push_wmops( "renderMcCustomLsToBinauralRoom" ); + + tmpRotBuffer = outAudio; /* avoid compilation warning */ + + headRotEnabled = mcInput->base.ctx.pHeadRotData->headRotEnabled; + + /* apply rotation */ + if ( headRotEnabled ) + { + tmpRotBuffer = mcInput->base.inputBuffer; + tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); + + if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* intermediate conversion to 7_1_4 */ + tmpMcBuffer = mcInput->base.inputBuffer; + + if ( ( error = getAudioConfigNumChannels( IVAS_REND_AUDIO_CONFIG_7_1_4, &tmp ) ) != IVAS_ERR_OK ) + { + return error; + } + + tmpMcBuffer.config.numChannels = tmp; + tmpMcBuffer.data = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( float ) ); + set_zero( tmpMcBuffer.data, tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels ); + + tmpBufPtr = ( headRotEnabled ) ? &tmpRotBuffer : &mcInput->base.inputBuffer; + for ( i = 0; i < mcInput->base.inputBuffer.config.numChannels; i++ ) + { + renderBufferChannel( *tmpBufPtr, i, mcInput->panGains[i], tmpMcBuffer ); + } + copyBufferTo2dArray( tmpMcBuffer, tmpCrendBuffer ); + + /* call CREND */ + if ( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, AUDIO_CONFIG_7_1_4, getIvasAudioConfigFromRendAudioConfig( outConfig ), NULL, NULL, NULL, NULL, + tmpCrendBuffer, *mcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio ); + + /* TODO tmu : needs delay compensation */ + if ( ( error = renderLfeToBinaural( mcInput, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( headRotEnabled ) + { + free( tmpRotBuffer.data ); + } + free( tmpMcBuffer.data ); + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static void renderMcToMc( + const input_mc *mcInput, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + IVAS_REND_AudioBuffer inAudio; + + push_wmops( "renderMcToMc" ); + + inAudio = mcInput->base.inputBuffer; + + for ( i = 0; i < inAudio.config.numChannels; ++i ) + { + renderBufferChannel( inAudio, i, mcInput->panGains[i], outAudio ); + } + + pop_wmops(); + + return; +} + +static void renderMcToSba( + const input_mc *mcInput, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + IVAS_REND_AudioBuffer inAudio; + + push_wmops( "renderMcToSba" ); + + inAudio = mcInput->base.inputBuffer; + + for ( i = 0; i < inAudio.config.numChannels; ++i ) + { + renderBufferChannel( inAudio, i, mcInput->panGains[i], outAudio ); + } + + pop_wmops(); + + return; +} + +static ivas_error renderInputMc( + input_mc *mcInput, + IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + ivas_error error; + IVAS_REND_AudioBuffer inAudio; + + error = IVAS_ERR_OK; + + inAudio = mcInput->base.inputBuffer; + + if ( mcInput->base.numNewSamplesPerChannel != outAudio.config.numSamplesPerChannel ) + { + /* Mismatch between the number of input samples vs number of requested output samples - currently not allowed */ + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + mcInput->base.numNewSamplesPerChannel = 0; + + /* Apply input gain to new audio */ + v_multc( inAudio.data, + mcInput->base.gain, + inAudio.data, + inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); + + switch ( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + renderMcToMc( mcInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + renderMcToSba( mcInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + error = renderMcToBinaural( mcInput, outConfig, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + if ( mcInput->base.inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) + { + error = renderMcCustomLsToBinauralRoom( mcInput, outConfig, outAudio ); + } + else + { + error = renderMcToBinauralRoom( mcInput, outConfig, outAudio ); + } + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + return error; +} + +static ivas_error renderActiveInputsMc( + IVAS_REND_HANDLE hIvasRend, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + input_mc *pCurrentInput; + ivas_error error; + + for ( i = 0, pCurrentInput = hIvasRend->inputsMc; i < RENDERER_MAX_MC_INPUTS; ++i, ++pCurrentInput ) + { + if ( pCurrentInput->base.inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = renderInputMc( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +static void renderSbaToMc( + const input_sba *sbaInput, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + IVAS_REND_AudioBuffer inAudio; + + push_wmops( "renderSbaToMc" ); + + inAudio = sbaInput->base.inputBuffer; + + for ( i = 0; i < inAudio.config.numChannels; ++i ) + { + renderBufferChannel( inAudio, i, sbaInput->hoaDecMtx[i], outAudio ); + } + + pop_wmops(); + + return; +} + +static void renderSbaToSba( + const input_sba *sbaInput, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + IVAS_REND_AudioBuffer inAudio; + + push_wmops( "renderSbaToSba" ); + + inAudio = sbaInput->base.inputBuffer; + + for ( i = 0; i < inAudio.config.numChannels; ++i ) + { + renderBufferChannel( inAudio, i, sbaInput->hoaDecMtx[i], outAudio ); + } + + pop_wmops(); + + return; +} + +static ivas_error renderSbaToBinaural( + input_sba *sbaInput, + const IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + + ivas_error error; + IVAS_REND_AudioBuffer tmpRotBuffer; + + push_wmops( "renderSbaToBinaural" ); + + /* apply rotation */ + if ( sbaInput->base.ctx.pHeadRotData->headRotEnabled ) + { + tmpRotBuffer = sbaInput->base.inputBuffer; + tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + + /* copy input for in-place rotation */ + mvr2r( sbaInput->base.inputBuffer.data, tmpRotBuffer.data, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel ); + + if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->rot_gains_prev, tmpRotBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + copyBufferTo2dArray( tmpRotBuffer, tmpCrendBuffer ); + free( tmpRotBuffer.data ); + } + else + { + copyBufferTo2dArray( sbaInput->base.inputBuffer, tmpCrendBuffer ); + } + + /* call CREND */ + if ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, getIvasAudioConfigFromRendAudioConfig( sbaInput->base.inConfig ), getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio ); + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderSbaToBinauralRoom( + input_sba *sbaInput, + const IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + int8_t headRotEnabled; + int16_t i; + int16_t tmp; + float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + ivas_error error; + IVAS_REND_AudioBuffer tmpRotBuffer; + IVAS_REND_AudioBuffer tmpMcBuffer; + IVAS_REND_AudioBuffer *tmpBufPtr; + + tmpRotBuffer = outAudio; /* avoid compilation warning */ + + push_wmops( "renderSbaToBinauralRoom" ); + + headRotEnabled = sbaInput->base.ctx.pHeadRotData->headRotEnabled; + + /* apply rotation */ + if ( headRotEnabled ) + { + tmpRotBuffer = sbaInput->base.inputBuffer; + tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + + /* copy input for in-place rotation */ + mvr2r( sbaInput->base.inputBuffer.data, tmpRotBuffer.data, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel ); + + if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->rot_gains_prev, tmpRotBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* intermediate rendering to 7_1_4 */ + tmpMcBuffer = sbaInput->base.inputBuffer; + + if ( ( error = getAudioConfigNumChannels( IVAS_REND_AUDIO_CONFIG_7_1_4, &tmp ) ) != IVAS_ERR_OK ) + { + return error; + } + + tmpMcBuffer.config.numChannels = tmp; + tmpMcBuffer.data = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( float ) ); + set_zero( tmpMcBuffer.data, tmpMcBuffer.config.numChannels * tmpMcBuffer.config.numSamplesPerChannel ); + + tmpBufPtr = ( headRotEnabled ) ? &tmpRotBuffer : &sbaInput->base.inputBuffer; + for ( i = 0; i < sbaInput->base.inputBuffer.config.numChannels; i++ ) + { + renderBufferChannel( *tmpBufPtr, i, sbaInput->hoaDecMtx[i], tmpMcBuffer ); + } + + copyBufferTo2dArray( tmpMcBuffer, tmpCrendBuffer ); + + /* call CREND */ + if ( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, AUDIO_CONFIG_7_1_4, getIvasAudioConfigFromRendAudioConfig( outConfig ), + NULL, NULL, NULL, NULL, tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio ); + + if ( headRotEnabled ) + { + free( tmpRotBuffer.data ); + } + free( tmpMcBuffer.data ); + + pop_wmops(); + + return IVAS_ERR_OK; +} + +static ivas_error renderInputSba( + input_sba *sbaInput, + const IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + ivas_error error; + IVAS_REND_AudioBuffer inAudio; + + error = IVAS_ERR_OK; + + inAudio = sbaInput->base.inputBuffer; + + if ( sbaInput->base.numNewSamplesPerChannel != outAudio.config.numSamplesPerChannel ) + { + /* Mismatch between the number of input samples vs number of requested output samples - currently not allowed */ + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + sbaInput->base.numNewSamplesPerChannel = 0; + + /* Apply input gain to new audio */ + v_multc( inAudio.data, + sbaInput->base.gain, + inAudio.data, + inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); + + switch ( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + renderSbaToMc( sbaInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + renderSbaToSba( sbaInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + error = renderSbaToBinaural( sbaInput, outConfig, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + error = renderSbaToBinauralRoom( sbaInput, outConfig, outAudio ); + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + return error; +} + +static ivas_error renderActiveInputsSba( + IVAS_REND_HANDLE hIvasRend, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + input_sba *pCurrentInput; + ivas_error error; + + for ( i = 0, pCurrentInput = hIvasRend->inputsSba; i < RENDERER_MAX_SBA_INPUTS; ++i, ++pCurrentInput ) + { + if ( pCurrentInput->base.inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = renderInputSba( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + +static void copyMasaMetadataToDiracRenderer( + MASA_METADATA_FRAME *meta, + DIRAC_DEC_HANDLE hDirAC ) +{ + int16_t band, sf, bin; +#ifdef FIX_390_EXT_REND_MASA_META_COPY + int16_t meta_write_index; +#endif + + hDirAC->numSimultaneousDirections = meta->descriptive_meta.numberOfDirections + 1; + + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { +#ifdef FIX_390_EXT_REND_MASA_META_COPY + meta_write_index = ( hDirAC->dirac_bs_md_write_idx + sf ) % hDirAC->dirac_md_buffer_length; +#endif + + for ( band = 0; band < MASA_MAXIMUM_CODING_SUBBANDS; band++ ) + { + for ( bin = MASA_band_grouping_24[band]; bin < MASA_band_grouping_24[band + 1]; bin++ ) + { +#ifdef FIX_390_EXT_REND_MASA_META_COPY + hDirAC->azimuth[meta_write_index][bin] = (int16_t) meta->directional_meta[0].azimuth[sf][band]; + hDirAC->elevation[meta_write_index][bin] = (int16_t) meta->directional_meta[0].elevation[sf][band]; + hDirAC->energy_ratio1[meta_write_index][bin] = meta->directional_meta[0].energy_ratio[sf][band]; + hDirAC->diffuseness_vector[meta_write_index][bin] = 1.0f - meta->directional_meta[0].energy_ratio[sf][band]; + hDirAC->spreadCoherence[meta_write_index][bin] = meta->directional_meta[0].spread_coherence[sf][band]; + hDirAC->surroundingCoherence[meta_write_index][bin] = meta->common_meta.surround_coherence[sf][band]; +#else + hDirAC->azimuth[sf][bin] = (int16_t) meta->directional_meta[0].azimuth[sf][band]; + hDirAC->elevation[sf][bin] = (int16_t) meta->directional_meta[0].elevation[sf][band]; + hDirAC->energy_ratio1[sf][bin] = meta->directional_meta[0].energy_ratio[sf][band]; + hDirAC->diffuseness_vector[sf][bin] = 1.0f - meta->directional_meta[0].energy_ratio[sf][band]; + hDirAC->spreadCoherence[sf][bin] = meta->directional_meta[0].spread_coherence[sf][band]; + hDirAC->surroundingCoherence[sf][bin] = meta->common_meta.surround_coherence[sf][band]; +#endif + + if ( hDirAC->numSimultaneousDirections == 2 ) + { +#ifdef FIX_390_EXT_REND_MASA_META_COPY + hDirAC->azimuth2[meta_write_index][bin] = (int16_t) meta->directional_meta[1].azimuth[sf][band]; + hDirAC->elevation2[meta_write_index][bin] = (int16_t) meta->directional_meta[1].elevation[sf][band]; + hDirAC->energy_ratio2[meta_write_index][bin] = meta->directional_meta[1].energy_ratio[sf][band]; + hDirAC->diffuseness_vector[meta_write_index][bin] -= meta->directional_meta[1].energy_ratio[sf][band]; + hDirAC->spreadCoherence2[meta_write_index][bin] = meta->directional_meta[1].spread_coherence[sf][band]; +#else + hDirAC->azimuth2[sf][bin] = (int16_t) meta->directional_meta[1].azimuth[sf][band]; + hDirAC->elevation2[sf][bin] = (int16_t) meta->directional_meta[1].elevation[sf][band]; + hDirAC->energy_ratio2[sf][bin] = meta->directional_meta[1].energy_ratio[sf][band]; + hDirAC->diffuseness_vector[sf][bin] -= meta->directional_meta[1].energy_ratio[sf][band]; + hDirAC->spreadCoherence2[sf][bin] = meta->directional_meta[1].spread_coherence[sf][band]; +#endif + } + } + } + } +#ifdef FIX_390_EXT_REND_MASA_META_COPY + + hDirAC->dirac_bs_md_write_idx = ( hDirAC->dirac_bs_md_write_idx + MAX_PARAM_SPATIAL_SUBFRAMES ) % hDirAC->dirac_md_buffer_length; +#endif + + return; +} + +static void renderMasaToMc( + input_masa *masaInput, + IVAS_REND_AudioBuffer outAudio ) +{ + float tmpBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + + copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer ); + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC ); + + /* TODO(sgi): Remove code duplication w.r.t. MASA rendering to other output configs */ + if ( masaInput->decDummy->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + ivas_dirac_dec_binaural( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels ); + } + else + { + ivas_dirac_dec( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels, NULL, NULL, -1 ); + } + + accumulate2dArrayToBuffer( tmpBuffer, &outAudio ); + + return; +} + +static void renderMasaToSba( + input_masa *masaInput, + IVAS_REND_AudioBuffer outAudio ) +{ + float tmpBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + + copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer ); + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC ); + + ivas_dirac_dec( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels, NULL, NULL, -1 ); + + accumulate2dArrayToBuffer( tmpBuffer, &outAudio ); + + return; +} + +static void renderMasaToBinaural( + input_masa *masaInput, + IVAS_REND_AudioBuffer outAudio ) +{ + float tmpBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + + copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer ); + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->decDummy->hDirAC ); + + ivas_dirac_dec_binaural( masaInput->decDummy, tmpBuffer, masaInput->base.inputBuffer.config.numChannels ); + + accumulate2dArrayToBuffer( tmpBuffer, &outAudio ); + + return; +} + +static ivas_error renderInputMasa( + input_masa *masaInput, + const IVAS_REND_AudioConfig outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + IVAS_REND_AudioBuffer inAudio; + + if ( !masaInput->metadataHasBeenFed ) + { + return IVAS_ERR_MISSING_METADATA; + } + + inAudio = masaInput->base.inputBuffer; + + if ( masaInput->base.numNewSamplesPerChannel != outAudio.config.numSamplesPerChannel ) + { + /* Mismatch between the number of input samples vs number of requested output samples - currently not allowed */ + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + masaInput->base.numNewSamplesPerChannel = 0; + + /* Apply input gain to new audio */ + v_multc( inAudio.data, + masaInput->base.gain, + inAudio.data, + inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); + + switch ( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + renderMasaToMc( masaInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + renderMasaToSba( masaInput, outAudio ); + break; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + switch ( outConfig ) + { + case IVAS_REND_AUDIO_CONFIG_BINAURAL: + renderMasaToBinaural( masaInput, outAudio ); + break; + /* ToDo */ + // case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: + // renderMasaToBinauralRoom( masaInput, outConfig, outAudio ); + // break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + break; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + return IVAS_ERR_OK; +} + +static ivas_error renderActiveInputsMasa( + IVAS_REND_HANDLE hIvasRend, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + input_masa *pCurrentInput; + ivas_error error; + + for ( i = 0, pCurrentInput = hIvasRend->inputsMasa; i < RENDERER_MAX_MASA_INPUTS; ++i, ++pCurrentInput ) + { + if ( pCurrentInput->base.inConfig == IVAS_REND_AUDIO_CONFIG_UNKNOWN ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = renderInputMasa( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_GetSamples() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_REND_GetSamples( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ +) +{ + ivas_error error; + int16_t numOutChannels; + + /* Validate function arguments */ + if ( hIvasRend == NULL || outAudio.data == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( outAudio.config.numSamplesPerChannel <= 0 || MAX_BUFFER_LENGTH_PER_CHANNEL < outAudio.config.numSamplesPerChannel ) + { + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + + if ( outAudio.config.numChannels <= 0 || MAX_OUTPUT_CHANNELS < outAudio.config.numChannels ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && + outAudio.config.numSamplesPerChannel * 1000 != BINAURAL_RENDERING_FRAME_SIZE_MS * hIvasRend->sampleRateOut ) + { + /* Binaural rendering requires specific frame size */ + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + + if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( numOutChannels != outAudio.config.numChannels ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + /* Clear output buffer */ + set_zero( outAudio.data, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); + + if ( ( error = renderActiveInputsIsm( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = renderActiveInputsMc( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = renderActiveInputsSba( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = renderActiveInputsMasa( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + +#ifdef DEBUGGING + hIvasRend->numClipping += +#endif + limitRendererOutput( hIvasRend->hLimiter, outAudio.data, outAudio.config.numSamplesPerChannel, IVAS_LIMITER_THRESHOLD ); + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_Close() + * + * + *-------------------------------------------------------------------*/ + +void IVAS_REND_Close( + IVAS_REND_HANDLE *phIvasRend /* i/o: Pointer to renderer handle */ +) +{ + uint16_t i; + IVAS_REND_HANDLE hIvasRend; + + /* Validate function arguments */ + if ( phIvasRend == NULL || *phIvasRend == NULL ) + { + return; + } + hIvasRend = *phIvasRend; + + if ( hIvasRend->efapOutWrapper.hEfap != NULL ) + { + efap_free_data( &hIvasRend->efapOutWrapper.hEfap ); + } + + /* clear inputs */ + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + clearInputIsm( &hIvasRend->inputsIsm[i] ); + } + for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) + { + clearInputMc( &hIvasRend->inputsMc[i] ); + } + for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i ) + { + clearInputSba( &hIvasRend->inputsSba[i] ); + } + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) + { + clearInputMasa( &hIvasRend->inputsMasa[i] ); + } + + /* clear Config. Renderer */ + ivas_render_config_close( &( hIvasRend->hRendererConfig ) ); + + ivas_limiter_close( &hIvasRend->hLimiter ); + + closeHeadRotation( hIvasRend ); + + free( hIvasRend ); + *phIvasRend = NULL; + + return; +} + +#ifdef DEBUGGING +/*-------------------------------------------------------------------* + * IVAS_REND_GetNoCLipping() + * + * + *-------------------------------------------------------------------*/ + +int32_t IVAS_REND_GetNoCLipping( + IVAS_REND_CONST_HANDLE hIvasRend ) +{ + return hIvasRend->numClipping; +} + +int32_t IVAS_REND_GetCntFramesLimited( + IVAS_REND_CONST_HANDLE hIvasRend ) +{ + if ( hIvasRend->hLimiter == NULL ) + { + return 0; + } + + return hIvasRend->hLimiter->cnt_frames_limited; +} +#endif diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h new file mode 100644 index 0000000000000000000000000000000000000000..ec4c05a6d676aac8b1a0fb98d156ee8ef110de82 --- /dev/null +++ b/lib_rend/lib_rend.h @@ -0,0 +1,304 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#ifndef LIB_REND_H +#define LIB_REND_H + +#include "common_api_types.h" +#include + + +#define RENDERER_MAX_ISM_INPUTS 4 +#define RENDERER_MAX_MC_INPUTS 1 +#define RENDERER_MAX_SBA_INPUTS 1 +#define RENDERER_MAX_MASA_INPUTS 1 + + +typedef float IVAS_REND_LfePanMtx[IVAS_MAX_INPUT_LFE_CHANNELS][IVAS_MAX_OUTPUT_CHANNELS]; + +typedef struct +{ + int16_t numSamplesPerChannel; + int16_t numChannels; +} IVAS_REND_AudioBufferConfig; + +typedef struct +{ + IVAS_REND_AudioBufferConfig config; + float *data; +} IVAS_REND_AudioBuffer; + +typedef struct +{ + IVAS_REND_AudioBufferConfig config; + const float *data; +} IVAS_REND_ReadOnlyAudioBuffer; + +typedef struct IVAS_REND *IVAS_REND_HANDLE; +typedef struct IVAS_REND const *IVAS_REND_CONST_HANDLE; + +typedef enum +{ + IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED = 0, + IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS, + IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED, + IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL, + IVAS_REND_AUDIO_CONFIG_TYPE_MASA, + IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN, +} IVAS_REND_AudioConfigType; + +/* TODO(sgi): Harmonize with AUDIO_CONFIG */ +/* + Note: numerical values carry specific information here. + + MSB LSB + -------------------------------------------------------------------------------- + ... unused (assumed all 0) ... | config type (1 byte) | config variant (1 byte) | + -------------------------------------------------------------------------------- + + Where "config type" is the general type from the following list: + - unknown + - channel-based + - ambisonics + - object-based + - binaural + - MASA + + Config variants are concrete configs of each type. + */ +typedef enum +{ + IVAS_REND_AUDIO_CONFIG_MONO = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 0, + IVAS_REND_AUDIO_CONFIG_STEREO = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 1, + IVAS_REND_AUDIO_CONFIG_5_1 = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 2, + IVAS_REND_AUDIO_CONFIG_7_1 = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 3, + IVAS_REND_AUDIO_CONFIG_5_1_2 = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 4, + IVAS_REND_AUDIO_CONFIG_5_1_4 = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 5, + IVAS_REND_AUDIO_CONFIG_7_1_4 = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 6, + IVAS_REND_AUDIO_CONFIG_LS_CUSTOM = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED << 8 | 255, + + IVAS_REND_AUDIO_CONFIG_FOA = IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS << 8 | 0, + IVAS_REND_AUDIO_CONFIG_HOA2 = IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS << 8 | 1, + IVAS_REND_AUDIO_CONFIG_HOA3 = IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS << 8 | 2, + + IVAS_REND_AUDIO_CONFIG_OBJECT = IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED << 8 | 0, + + IVAS_REND_AUDIO_CONFIG_BINAURAL = IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL << 8 | 0, + IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM = IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL << 8 | 1, + + IVAS_REND_AUDIO_CONFIG_MASA1 = IVAS_REND_AUDIO_CONFIG_TYPE_MASA << 8 | 0, + IVAS_REND_AUDIO_CONFIG_MASA2 = IVAS_REND_AUDIO_CONFIG_TYPE_MASA << 8 | 1, + + IVAS_REND_AUDIO_CONFIG_UNKNOWN = IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN << 8 | 0, +} IVAS_REND_AudioConfig; + +typedef uint16_t IVAS_REND_InputId; + + +/* clang-format off */ +/*----------------------------------------------------------------------------------* + * Function prototypes + *----------------------------------------------------------------------------------*/ + +/* Functions to be called before rendering */ + +ivas_error IVAS_REND_Open( + IVAS_REND_HANDLE *phIvasRend, /* i/o: Pointer to renderer handle */ + const int32_t outputSampleRate, /* i : output sampling rate */ + const IVAS_REND_AudioConfig outConfig /* i : output audio config */ +); + +/* Note: this will reset custom LFE routings set for any MC input */ +ivas_error IVAS_REND_ConfigureCustomOutputLoudspeakerLayout( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_CUSTOM_LS_DATA layout /* i : custom loudspeaker layout for renderer output */ +); + +/* Support for custom HRTFs will be added in the future. */ +/* Note: this affects output delay */ +ivas_error IVAS_REND_SetCustomHrtf( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + void* TODO +); + +/* Functions to be called before/during rendering */ + +ivas_error IVAS_REND_NumOutChannels( + IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + int16_t *numOutChannels /* o : number of output channels */ +); + +ivas_error IVAS_REND_AddInput( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_AudioConfig inConfig, /* i : audio config for a new input */ + IVAS_REND_InputId *inputId /* o : ID of the new input */ +); + +/* Note: this will reset any custom LFE routing set for the input */ +ivas_error IVAS_REND_ConfigureCustomInputLoudspeakerLayout( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_CUSTOM_LS_DATA layout /* i : custom loudspeaker layout for input */ +); + +ivas_error IVAS_REND_SetInputGain( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const float gain /* i : linear gain (not in dB) */ +); + +ivas_error IVAS_REND_SetInputLfeMtx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_LfePanMtx *lfePanMtx /* i : LFE panning matrix */ +); + +ivas_error IVAS_REND_SetInputLfePos( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const float inputGain, /* i : Input gain to be applied to the LFE channel(s) */ + const float outputAzimuth, /* i : Output azimuth position */ + const float outputElevation /* i : Output elevation position */ +); + +ivas_error IVAS_REND_RemoveInput( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId /* i : ID of the input */ +); + +ivas_error IVAS_REND_GetInputNumChannels( + IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + int16_t *numChannels /* o : number of channels of the input */ +); + +ivas_error IVAS_REND_GetDelay( + IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + int16_t *nSamples, /* o : Renderer delay in samples */ + int32_t *timeScale /* o : Time scale of the delay, equal to renderer output sampling rate */ +); + +/* Functions to be called during rendering */ + +ivas_error IVAS_REND_FeedInputAudio( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ +); + +ivas_error IVAS_REND_FeedInputObjectMetadata( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_AudioObjectPosition objectPosition /* i : object position struct */ +); + +ivas_error IVAS_REND_FeedInputMasaMetadata( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + IVAS_MASA_METADATA_HANDLE masaMetadata /* i : MASA metadata frame */ +); + +ivas_error IVAS_REND_InitConfig( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ +#ifdef FIX_392_LATE_REVERB + const IVAS_REND_AudioConfig outAudioConfig /* i : output audioConfig */ +#else + const bool rendererConfigEnabled /* i : flag indicating if a renderer configuration file was supplied */ +#endif +); + +int16_t IVAS_REND_GetRenderConfig( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS decoder handle */ + const IVAS_RENDER_CONFIG_HANDLE hRCout /* o : Render configuration handle */ +); + +int16_t IVAS_REND_FeedRenderConfig( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS decoder handle */ + const IVAS_RENDER_CONFIG_DATA renderConfig /* i : Render configuration struct */ +); + +ivas_error IVAS_REND_SetHeadRotation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME], /* i : head orientations for next rendering call */ + const IVAS_POSITION Pos[RENDERER_HEAD_POSITIONS_PER_FRAME] /* i : listener positions for next rendering call */ +); + +ivas_error IVAS_REND_SetOrientationTrackingMode( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const uint8_t otrMode /* i : Orientation tracking mode */ +); + +ivas_error IVAS_REND_SetReferenceRotation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_QUATERNION refRot /* i : Reference rotation */ +); + +ivas_error IVAS_REND_GetMainOrientation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_QUATERNION *pOrientation /* i/o: Quaternion pointer for main orientation */ +); + +ivas_error IVAS_REND_GetTrackedRotation( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_QUATERNION *pRotation /* i/o: Quaternion pointer for processed rotation */ +); + +ivas_error IVAS_REND_SetReferenceVector( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_VECTOR3 listenerPos, /* i : Listener position */ + const IVAS_VECTOR3 refPos /* i : Reference position */ +); + +ivas_error IVAS_REND_GetSamples( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ +); + +/* Functions to be called after rendering */ + +void IVAS_REND_Close( + IVAS_REND_HANDLE* phIvasRend /* i/o: Pointer to renderer handle */ +); + +#ifdef DEBUGGING +int32_t IVAS_REND_GetNoCLipping( + IVAS_REND_CONST_HANDLE hIvasRend /* i : Renderer handle */ +); + +int32_t IVAS_REND_GetCntFramesLimited( + IVAS_REND_CONST_HANDLE hIvasRend /* i : Renderer handle */ +); +#endif + +/* clang-format on */ + +#endif diff --git a/lib_util/audio_file_reader.c b/lib_util/audio_file_reader.c index d391735a9457cdc3062b5da037172dd1c6be458c..4f6bd0c34d13fd62439775d31933f9d67a4197f4 100644 --- a/lib_util/audio_file_reader.c +++ b/lib_util/audio_file_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,13 +32,15 @@ #include "audio_file_reader.h" #include "tinywavein_c.h" +#include #include -#include "wmops.h" +#include "wmc_auto.h" struct AudioFileReader { FILE *rawFile; WAVEFILEIN *wavFile; + uint32_t samplingRate; int16_t numChannels; }; @@ -53,13 +55,12 @@ static int8_t AudioFileReader_open_raw( static int8_t AudioFileReader_open_wav( AudioFileReader *self, - const char *fileName, - uint32_t expSampleRate ) + const char *fileName ) { - uint32_t sampleRate, samplesInFile; + uint32_t samplesInFile; int16_t bps; - self->wavFile = OpenWav( fileName, &sampleRate, &self->numChannels, &samplesInFile, &bps ); + self->wavFile = OpenWav( fileName, &self->samplingRate, &self->numChannels, &samplesInFile, &bps ); if ( !self->wavFile ) { @@ -67,21 +68,14 @@ static int8_t AudioFileReader_open_wav( return -1; } - if ( sampleRate != expSampleRate ) - { - fprintf( stderr, "Input wav file has unexpected samplerate (should be %d): %s\n", expSampleRate, fileName ); - return -1; - } - return 0; } /*! r: AudioFileReader handle */ ivas_error AudioFileReader_open( - AudioFileReader **audioReader, /* o : AudioFileReader handle */ - const char *fileName, /* i : path to wav/raw pcm file */ - uint32_t expSampleRate /* i : expected sample rate */ + AudioFileReader **audioReader, /* o : AudioFileReader handle */ + const char *fileName /* i : path to wav/raw pcm file */ ) { AudioFileReader *self; @@ -104,11 +98,12 @@ ivas_error AudioFileReader_open( return IVAS_ERR_FAILED_FILE_OPEN; } self = calloc( sizeof( AudioFileReader ), 1 ); + self->samplingRate = 0; self->numChannels = 0; if ( fileNameLen > wavSuffixLen && strncmp( fileName + fileNameLen - wavSuffixLen, wavSuffix, wavSuffixLen ) == 0 ) { - retCode = AudioFileReader_open_wav( self, fileName, expSampleRate ); + retCode = AudioFileReader_open_wav( self, fileName ); } else { @@ -184,15 +179,53 @@ ivas_error AudioFileReader_read( return error; } -/*! r: number of channels of the opened file */ -int16_t AudioFileReader_getNumChannels( - AudioFileReader *self /* i/o: AudioFileReader handle */ -) +ivas_error AudioFileReader_getSamplingRate( + AudioFileReader *self, + int32_t *samplingRate ) { - if ( self != NULL ) + if ( self == NULL || samplingRate == NULL ) { - return self->numChannels; + return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - return 0; + if ( self->rawFile ) + { + return IVAS_ERR_SAMPLING_RATE_UNKNOWN; + } + else if ( self->wavFile ) + { + *samplingRate = self->samplingRate; + } + else + { + return IVAS_ERR_NO_FILE_OPEN; + } + + return IVAS_ERR_OK; +} + + +ivas_error AudioFileReader_getNumChannels( + AudioFileReader *self, + int16_t *numChannels ) +{ + if ( self == NULL || numChannels == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( self->rawFile ) + { + return IVAS_ERR_NUM_CHANNELS_UNKNOWN; + } + else if ( self->wavFile ) + { + *numChannels = self->numChannels; + } + else + { + return IVAS_ERR_NO_FILE_OPEN; + } + + return IVAS_ERR_OK; } diff --git a/lib_util/audio_file_reader.h b/lib_util/audio_file_reader.h index d878e3cab42cc4ac5e478bcc266f5784f2c7ecd7..0fd4da5ac76c25285d3b49d67166ce651a96eeb8 100644 --- a/lib_util/audio_file_reader.h +++ b/lib_util/audio_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,8 +33,7 @@ #ifndef IVAS_AUDIO_FILE_READER_H #define IVAS_AUDIO_FILE_READER_H -#include -#include "ivas_error.h" +#include "common_api_types.h" struct AudioFileReader; typedef struct AudioFileReader AudioFileReader; @@ -42,12 +41,10 @@ typedef struct AudioFileReader AudioFileReader; /* clang-format off */ ivas_error AudioFileReader_open( - AudioFileReader **audioReader, /* o : AudioFileReader handle */ - const char *fileName, /* i : path to wav/raw pcm file */ - uint32_t expSampleRate /* i : expected sample rate */ + AudioFileReader **audioReader, /* o : AudioFileReader handle */ + const char *fileName /* i : path to wav/raw pcm file */ ); -/*! r: number of read samples */ ivas_error AudioFileReader_read( AudioFileReader *self, /* i/o: AudioFileReader handle */ int16_t *samples, /* o : samples read from the opened file */ @@ -55,9 +52,16 @@ ivas_error AudioFileReader_read( int16_t *numSamplesRead /* i : number of samples actualy read */ ); -/*! r: number of channels of the opened file */ -int16_t AudioFileReader_getNumChannels( - AudioFileReader *self /* i/o: AudioFileReader handle */ +/*! r: ivas error - in particular, IVAS_ERR_SAMPLING_RATE_UNKNOWN if the opened file has no sampling rate metadata */ +ivas_error AudioFileReader_getSamplingRate( + AudioFileReader *self, /* i/o: AudioFileReader handle */ + int32_t* samplingRate /* o : sampling rate of opened audio file */ +); + +/*! r: ivas error - in particular, IVAS_ERR_NUM_CHANNELS_UNKNOWN if the opened file has no metadata specifying number of channels */ +ivas_error AudioFileReader_getNumChannels( + AudioFileReader *self, /* i/o: AudioFileReader handle */ + int16_t * numChannels /* o : number fo channels in opened audio file */ ); void AudioFileReader_close( diff --git a/lib_util/audio_file_writer.c b/lib_util/audio_file_writer.c index af9c6ee0e610b85de52574410593524e53d9e7f9..81084dbd95b686d52477327b948ada136225f42f 100644 --- a/lib_util/audio_file_writer.c +++ b/lib_util/audio_file_writer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,7 +34,7 @@ #include "tinywaveout_c.h" #include #include -#include "wmops.h" +#include "wmc_auto.h" struct AudioFileWriter { @@ -98,7 +98,7 @@ ivas_error AudioFileWriter_open( int8_t retCode; - if ( fileNameLen > wavSuffixLen && strncmp( fileName + fileNameLen - wavSuffixLen, wavSuffix, wavSuffixLen ) == 0 ) + if ( ( fileNameLen > wavSuffixLen ) && ( strncmp( fileName + fileNameLen - wavSuffixLen, wavSuffix, wavSuffixLen ) == 0 ) ) { retCode = AudioFileWriter_open_wav( self, fileName, sampleRate, numChannels ); } diff --git a/lib_util/audio_file_writer.h b/lib_util/audio_file_writer.h index cd7d2ce5d2d1f2e21b685680d2e6d407f7b9ecaf..b5157ffde43f74a15803ec132814992a4fb8ce8f 100644 --- a/lib_util/audio_file_writer.h +++ b/lib_util/audio_file_writer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,8 +33,7 @@ #ifndef IVAS_AUDIO_FILE_WRITER_H #define IVAS_AUDIO_FILE_WRITER_H -#include -#include "ivas_error.h" +#include "common_api_types.h" struct AudioFileWriter; typedef struct AudioFileWriter AudioFileWriter; diff --git a/lib_util/bitstream_reader.c b/lib_util/bitstream_reader.c index caa8b52c59f5e97f0d72667c14dad7a4a3da5113..999332e863dcb9584e557ba3375a91b541a398f7 100644 --- a/lib_util/bitstream_reader.c +++ b/lib_util/bitstream_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_util/bitstream_reader.h b/lib_util/bitstream_reader.h index 2b750566eb6632143975ff5ff152b5fba6b7a23d..2accbbd242670d69f612780ce4b46018a5b05e72 100644 --- a/lib_util/bitstream_reader.h +++ b/lib_util/bitstream_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,9 +33,7 @@ #ifndef BITSTREAM_READER_H #define BITSTREAM_READER_H -#include "options.h" -#include "ivas_error.h" -#include +#include "common_api_types.h" /*-----------------------------------------------------------------------* diff --git a/lib_util/bitstream_writer.c b/lib_util/bitstream_writer.c index c133ceba254b20550435348b4eda91bd74770209..7862ff1977c840601d39065c173eecf32674d290 100644 --- a/lib_util/bitstream_writer.c +++ b/lib_util/bitstream_writer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,7 +33,6 @@ #include "bitstream_writer.h" #include "g192.h" #include "mime_io.h" -#include "ivas_error.h" #include "ivas_error_utils.h" #include #include diff --git a/lib_util/bitstream_writer.h b/lib_util/bitstream_writer.h index 9a8acc8106a24d54d14aaa4e6da1c05a5003cdd8..a855f347d272e09d8996e4540154c580ba29cefb 100644 --- a/lib_util/bitstream_writer.h +++ b/lib_util/bitstream_writer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,8 +33,7 @@ #ifndef BITSTREAM_WRITER_H #define BITSTREAM_WRITER_H -#include -#include "ivas_error.h" +#include "common_api_types.h" /*-----------------------------------------------------------------------* diff --git a/lib_util/cmdl_tools.c b/lib_util/cmdl_tools.c index aee640a17ed12523e40b705194f14b445ee6284d..b0b7e906cca95b1bb64e66a62677ec1ef1eb21e9 100644 --- a/lib_util/cmdl_tools.c +++ b/lib_util/cmdl_tools.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,6 +31,7 @@ *******************************************************************************************************/ #include "cmdl_tools.h" +#include /*---------------------------------------------------------------------* * to_upper() @@ -62,7 +63,7 @@ char *to_upper( char *str ) * Check if a string contains only digits. *---------------------------------------------------------------------*/ -bool is_digits_only( char *str ) +bool is_digits_only( const char *str ) { int16_t i; @@ -78,3 +79,149 @@ bool is_digits_only( char *str ) return true; } + + +/*---------------------------------------------------------------------* + * is_number() + * + * Check if a string is a number. + *---------------------------------------------------------------------*/ + +bool is_number( const char *str ) +{ + bool decimal_separator_found; + int16_t i; + int16_t numeric_len; + + decimal_separator_found = false; + i = 0; + numeric_len = 0; + + /* Check for null string or sign character */ + if ( str[i] == '\0' ) + { + return false; + } + else if ( str[i] == '+' || str[i] == '-' ) + { + i++; + } + + /* Ensure rest of string is numeric and only one decimal separator is present */ + while ( str[i] != 0 ) + { + if ( str[i] < '0' || str[i] > '9' ) + { + if ( str[i] == '.' ) + { + if ( decimal_separator_found ) + { + return false; + } + else + { + decimal_separator_found = true; + } + } + else if ( str[i] != '\r' && str[i] != '\n' ) + { + return false; + } + } + else + { + numeric_len++; + } + i++; + } + + if ( numeric_len == 0 ) + { + return false; + } + + return true; +} + + +/*---------------------------------------------------------------------* + * convert_backslash() + * + * + *---------------------------------------------------------------------*/ + +void convert_backslash( + char *str ) +{ + int16_t i, len; + + /* check that all backslashes are correct on the given platform */ + len = (int16_t) strlen( str ); + + for ( i = 0; i < len; i++ ) + { +#ifdef _WIN32 + if ( str[i] == '/' ) + { + str[i] = '\\'; + } +#else + if ( str[i] == '\\' ) + { + str[i] = '/'; + } +#endif + } + + return; +} + +/*---------------------------------------------------------------------* + * remove_cr() + * + * + *---------------------------------------------------------------------*/ + +void remove_cr( + char *str ) +{ + char *pos; + + /* remove all \r characters from the string */ + pos = strchr( str, '\r' ); + while ( pos != NULL ) + { + strcpy( pos, pos + 1 ); + pos = strchr( pos, '\r' ); + } + + return; +} + + +/*---------------------------------------------------------------------* + * clearString() + * + * + *---------------------------------------------------------------------*/ + +void clearString( + char *str ) +{ + str[0] = '\0'; + + return; +} + + +/*---------------------------------------------------------------------* + * isEmptyString() + * + * + *---------------------------------------------------------------------*/ + +bool isEmptyString( + const char *str ) +{ + return str[0] == '\0'; +} diff --git a/lib_util/cmdl_tools.h b/lib_util/cmdl_tools.h index 3bc9cb81f73bd726cfc73e829859489edd1bcae6..b160473002930dd2c980d9bfbdcfb8e1bad3722a 100644 --- a/lib_util/cmdl_tools.h +++ b/lib_util/cmdl_tools.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,9 +36,18 @@ #include #include -bool is_digits_only( char *str ); +bool is_digits_only( const char *str ); + +bool is_number( const char *str ); char *to_upper( char *str ); +void convert_backslash( char *str ); + +void remove_cr( char *str ); + +void clearString( char *str ); + +bool isEmptyString( const char *str ); #endif /* CMDL_TOOLS_H */ diff --git a/lib_util/cmdln_parser.c b/lib_util/cmdln_parser.c new file mode 100644 index 0000000000000000000000000000000000000000..200b8c86e9bf77bf6c38f39b0f444e4da097e59b --- /dev/null +++ b/lib_util/cmdln_parser.c @@ -0,0 +1,388 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "cmdln_parser.h" +#include +#include +#include +#include + +#define MAX_SUPPORTED_OPTS ( 1024 ) +#define MAX_OPTION_LENGTH ( 1024 ) + +typedef CmdLnParser_Option OptionProps; + +typedef struct +{ + OptionProps props; + int8_t hasBeenParsed; +} Option; + +static int16_t validateNoDuplicateIds( + const OptionProps *props, + int32_t numOpts ) +{ + for ( int32_t i = 0; i < numOpts; ++i ) + { + for ( int32_t j = i + 1; j < numOpts; ++j ) + { + if ( props[i].id == props[j].id ) + { + fprintf( stderr, "[dev] Duplicate ID == %d between options %s and %s\n", props[i].id, props[i].match, props[j].match ); + return -1; + } + } + } + + return 0; +} + +static int16_t validateOptionProps( + OptionProps props ) +{ + /* Check required properties */ + if ( props.match == NULL ) + { + /* TODO(sgi): Don't print out usage after this - props.match is used there */ + fprintf( stderr, "[dev] Option with ID == %d - missing required property \"match\"\n", props.id ); + return -1; + } + + if ( props.id == 0 ) + { + fprintf( stderr, "[dev] Invalid ID for option %s. ID == %d is reserved.\n", props.match, props.id ); + return -1; + } + + return 0; +} + +/* Validate given OptionProps and use them to initialize array of Options */ +static int16_t initOpts( + const OptionProps *options, + const int32_t numOpts, + Option *opts ) +{ + for ( int32_t i = 0; i < numOpts; ++i ) + { + if ( validateOptionProps( options[i] ) != 0 ) + { + return -1; + } + + Option tmp = { + .hasBeenParsed = 0 + }; + tmp.props = options[i]; /* Cannot assign in aggregate initializer above - causes Visual Studio warning */ + + opts[i] = tmp; + } + + /* Check for duplicate IDs */ + if ( validateNoDuplicateIds( options, numOpts ) != 0 ) + { + return -1; + } + + return 0; +} + +static int8_t stringLooksLikeOption( + const char *str ) +{ + if ( str[0] == '-' ) + { + return 1; + } + + return 0; +} + +static const char *stringToOptionName( + const char *str ) +{ + while ( *str == '-' ) + { + ++str; + } + + return str; +} + +static int8_t optionMatchesString( + Option opt, + const char *str ) +{ + if ( !stringLooksLikeOption( str ) ) + { + return 0; + } + + const char *optionName = stringToOptionName( str ); + + if ( strncmp( optionName, opt.props.match, MAX_OPTION_LENGTH ) == 0 || strncmp( optionName, opt.props.matchShort, MAX_OPTION_LENGTH ) == 0 ) + { + return 1; + } + + return 0; +} + +static int16_t parseOpts( + int32_t argc, + char **argv, + Option *opts, + const int32_t numOpts, + void *pOutputStruct, + CmdLnParser_FnPtr_ParseOption parseOption ) +{ + Option *currOpt = NULL; + int32_t currOptIdx = 1; + Option *nextOpt = NULL; + int32_t nextOptIdx = 0; + int16_t numValues = 0; + + /* Go through all given argv */ + for ( int32_t argIdx = 1; argIdx < argc; ++argIdx ) + { + /* For current argument from argv go through all options and try to match */ + for ( int32_t optIdx = 0; optIdx < numOpts; ++optIdx ) + { + Option *optToMatch = &opts[optIdx]; + if ( optionMatchesString( *optToMatch, argv[argIdx] ) ) + { + nextOpt = optToMatch; + nextOptIdx = argIdx; + + /* Check if already parsed */ + if ( optToMatch->hasBeenParsed ) + { + fprintf( stderr, "Duplicate option: %s (%s)\n", optToMatch->props.match, optToMatch->props.matchShort ); + return -1; + } + + break; + } + } + + /* If no option matched, it is either a value belonging to current option or an invalid option */ + if ( nextOpt == NULL ) + { + /* Invalid option */ + if ( stringLooksLikeOption( argv[argIdx] ) ) + { + fprintf( stderr, "Unknown option `%s`\n", stringToOptionName( argv[argIdx] ) ); + return -1; + } + + /* Otherwise, value following current option. + * Exception: at the beginning of parsing (when current option is NULL) no values are allowed, throw error*/ + if ( currOpt != NULL ) + { + ++numValues; + } + else + { + fprintf( stderr, "Unexpected token `%s`\n", argv[argIdx] ); + return -1; + } + } + + /* If current argument is a recognized option or no more arguments left, parse current option into output struct*/ + if ( nextOpt != NULL ) + { + if ( currOpt != NULL ) + { + parseOption( currOpt->props.id, &argv[currOptIdx + 1], numValues, pOutputStruct ); + currOpt->hasBeenParsed = 1; + } + + currOpt = nextOpt; + currOptIdx = nextOptIdx; + nextOpt = NULL; + nextOptIdx = 0; + numValues = 0; + } + } + + /* Parse last option */ + if ( currOpt != NULL ) + { + parseOption( currOpt->props.id, &argv[currOptIdx + 1], numValues, pOutputStruct ); + currOpt->hasBeenParsed = 1; + } + + return 0; +} + +static const char *getBasename( + const char *path ) +{ + /* Find last forward slash in path */ + const char *namePtr = strrchr( path, '/' ); + if ( namePtr != NULL ) + { + return namePtr + 1; + } + + /* If not found, try to find last backslash in path */ + namePtr = strrchr( path, '\\' ); + if ( namePtr != NULL ) + { + return namePtr + 1; + } + + /* If also not found, return full path, which implictly should be the basename */ + return path; +} + +static int32_t totalOptionNameLength( + const OptionProps opt ) +{ + return strlen( opt.match ) + strlen( opt.matchShort ); +} + +static void printWhitespace( + const int32_t n ) +{ + for ( int32_t i = 0; i < n; ++i ) + { + fprintf( stderr, " " ); + } +} + +static void printOptDescriptionAligned( + const char *descPtr, + int32_t descriptionColumnIdx ) +{ + if ( descPtr == NULL ) + { + fprintf( stderr, "\n" ); + return; + } + + while ( 1 ) + { + if ( *descPtr == '\0' ) + { + fprintf( stderr, "\n" ); + break; + } + + fprintf( stderr, "%c", *descPtr ); + if ( *descPtr == '\n' ) + { + printWhitespace( descriptionColumnIdx ); + } + ++descPtr; + } + + return; +} + +static void printUsage( + const char *argv0, + const OptionProps *optionProps, + const int32_t numOptions ) +{ + fprintf( stderr, "\n" ); + fprintf( stderr, "Usage: %s [options]\n", getBasename( argv0 ) ); + fprintf( stderr, "\n" ); + fprintf( stderr, "Valid options:\n" ); + + /* Find option with longest name, used for pretty formatting */ + int32_t maxOptNameLength = 0; + for ( int32_t i = 0; i < numOptions; ++i ) + { + const int32_t optNameLength = totalOptionNameLength( optionProps[i] ); + if ( maxOptNameLength < optNameLength ) + { + maxOptNameLength = optNameLength; + } + } + + const int32_t preDescriptionWhitespace = 8; + const int32_t leftColumnAdditionalChars = 7; + for ( int32_t i = 0; i < numOptions; ++i ) + { + OptionProps opt = optionProps[i]; + const int32_t optNameLength = totalOptionNameLength( optionProps[i] ); + + /* TODO(sgi): make matchShort optional */ + fprintf( stderr, " --%s, -%s", opt.match, opt.matchShort ); + + printWhitespace( maxOptNameLength - optNameLength + preDescriptionWhitespace ); + printOptDescriptionAligned( opt.description, maxOptNameLength + preDescriptionWhitespace + leftColumnAdditionalChars ); + } + + return; +} + +int16_t CmdLnParser_parseArgs( + int32_t argc, + char **argv, + const OptionProps *optionProps, + const int32_t numOptions, + void *pOutputStruct, + CmdLnParser_FnPtr_ParseOption parseOption ) +{ + assert( numOptions <= MAX_SUPPORTED_OPTS ); + + /* Prepare option array */ + Option opts[MAX_SUPPORTED_OPTS]; + if ( initOpts( optionProps, numOptions, opts ) != 0 ) + { + goto fail; + } + + /* Iterate over argv and parse */ + if ( parseOpts( argc, argv, opts, numOptions, pOutputStruct, parseOption ) != 0 ) + { + goto fail; + } + + return 0; + +fail: + printUsage( argv[0], optionProps, numOptions ); + return -1; +} + +void CmdLnParser_printUsage( + char *executableName, + const CmdLnParser_Option *options, + const int32_t numOptions ) +{ + printUsage( executableName, options, numOptions ); + + return; +} diff --git a/scripts/ivas_pytests/tests/unit_tests/crend/ivas_crend_unit_test.h b/lib_util/cmdln_parser.h similarity index 71% rename from scripts/ivas_pytests/tests/unit_tests/crend/ivas_crend_unit_test.h rename to lib_util/cmdln_parser.h index c26134aba1fb810968e6bc9622670718a2a893cd..b8c8370eb4e7efbfa3c6da5a1c2c661510bb1a89 100644 --- a/scripts/ivas_pytests/tests/unit_tests/crend/ivas_crend_unit_test.h +++ b/lib_util/cmdln_parser.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,28 +30,25 @@ *******************************************************************************************************/ -/**************************************************************************** -* File description - -* This source file contains definitions specific to IVAS common renderer -****************************************************************************/ +#ifndef CMDLN_PARSER_H +#define CMDLN_PARSER_H -#ifndef IVAS_CREND_UNIT_TEST_H -#define IVAS_CREND_UNIT_TEST_H +#include "common_api_types.h" +#include -#include "stdio.h" -#include "stdlib.h" -#include "string.h" -#include -#include "ivas_stat_dec.h" -#include "ivas_result_t.h" +typedef struct +{ + int32_t id; + const char *match; + const char *matchShort; + const char *description; +} CmdLnParser_Option; +/* Function for parsing option values into an output struct, to be implemented by the user */ +typedef void ( *CmdLnParser_FnPtr_ParseOption )( int32_t optionId, char **optionValues, int16_t numOptionValues, void *pOutputStruct ); -/* Tables */ +int16_t CmdLnParser_parseArgs( int32_t argc, char **argv, const CmdLnParser_Option *options, const int32_t numOptions, void *pOutputStruct, CmdLnParser_FnPtr_ParseOption parseOption ); -extern float ivas_mixer_510_to_510_tc_gain[]; -extern float ivas_mixer_710_to_710_tc_gain[]; -extern float ivas_mixer_510_LFE_to_BIN_tc_gain[]; -extern float ivas_mixer_710_LFE_to_BIN_tc_gain[]; +void CmdLnParser_printUsage( char *executableName, const CmdLnParser_Option *options, const int32_t numOptions ); - -#endif /* IVAS_CREND_UNIT_TEST_H */ +#endif /* CMDLN_PARSER_H */ diff --git a/lib_util/evs_rtp_payload.c b/lib_util/evs_rtp_payload.c index 67dcaa6f36c3bd781aec81dc3e7827fa55276eed..d67aebd4c0f4312f523e17cb74d1549fe5148bb6 100644 --- a/lib_util/evs_rtp_payload.c +++ b/lib_util/evs_rtp_payload.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -141,36 +141,6 @@ static void evsHeaderFullPayload_parseToc( uint8_t toc, bool *isAMRWB_IOmode, bo } } -bool evsPayload_getFrameTypeFromSize( int16_t frameSizeBits, bool *isAMRWB_IOmode, uint16_t *frameTypeIndex ) -{ - int16_t i; - int32_t rate; - rate = frameSizeBits * 50; - if ( rate == 0 ) - { - assert( 0 ); /* VOIP_G192_RTP should not transmit empty frames */ - return false; /* no information available */ - } - for ( i = 0; i <= 9; ++i ) - { - if ( rate == AMRWB_IOmode2rate[i] ) - { - *isAMRWB_IOmode = true; - *frameTypeIndex = i; - return true; - } - } - for ( i = 0; i <= 12; ++i ) - { - if ( rate == PRIMARYmode2rate[i] ) - { - *isAMRWB_IOmode = false; - *frameTypeIndex = i; - return true; - } - } - return false; -} bool evsHeaderFullPayload_unpackFrame( char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, unsigned char **frame, uint16_t *frameSizeInBits ) { diff --git a/lib_util/evs_rtp_payload.h b/lib_util/evs_rtp_payload.h index 55073a7fa5d779b19375525256fbbdb5072715cb..dac5fb0e35cfee6fca7fc2402b75bf6ae94c0f42 100644 --- a/lib_util/evs_rtp_payload.h +++ b/lib_util/evs_rtp_payload.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -160,7 +160,6 @@ extern "C" bool evsPayload_unpackFrame( bool hf_only, char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, unsigned char **framePtr, uint16_t *frameSizeBits ); - bool evsPayload_getFrameTypeFromSize( int16_t frameSizeBits, bool *isAMRWB_IOmode, uint16_t *frameTypeIndex ); bool evsHeaderFullPayload_unpackFrame( char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, unsigned char **frame, uint16_t *frameSizeBits ); diff --git a/lib_util/g192.c b/lib_util/g192.c index 26b3aae578289a6f02ce3cc423fe841587b97272..04ba16c369a2d556562544186b70cc23ddab3b27 100644 --- a/lib_util/g192.c +++ b/lib_util/g192.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,14 +34,8 @@ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 ====================================================================================*/ -/* WMC_TOOL_SKIP_FILE (basic ops file) */ - -#include "options.h" #include "g192.h" -#include "cnst.h" #include -#include -#include #include #include #ifndef _WIN32 @@ -124,7 +118,7 @@ G192_ERROR G192_ReadFrame_compact( int16_t *const num_bits, int16_t *const bfi ) { - uint16_t short_serial[MAX_BITS_PER_FRAME]; + uint16_t short_serial[IVAS_MAX_BITS_PER_FRAME]; G192_ERROR err; int16_t i; @@ -153,7 +147,7 @@ G192_ERROR G192_ReadVoipFrame_compact( uint32_t *const rtpTimeStamp, uint32_t *const rcvTime_ms ) { - int16_t short_serial[MAX_BITS_PER_FRAME]; + int16_t short_serial[IVAS_MAX_BITS_PER_FRAME]; G192_ERROR err; int16_t i; @@ -223,7 +217,7 @@ G192_ERROR G192_ReadFrame_short( return G192_READ_ERROR; } - if ( *num_bits > MAX_BITS_PER_FRAME ) + if ( *num_bits > IVAS_MAX_BITS_PER_FRAME ) { fprintf( stderr, "\n Frame is too large " ); return G192_READ_ERROR; @@ -386,7 +380,7 @@ G192_ERROR G192_ReadVoipFrame_short( } *num_bits = rtpPayloadG192[1]; - if ( *num_bits == 0u || *num_bits + 2u != rtpPayloadSize || *num_bits > MAX_BITS_PER_FRAME ) + if ( *num_bits == 0u || *num_bits + 2u != rtpPayloadSize || *num_bits > IVAS_MAX_BITS_PER_FRAME ) { fprintf( stderr, "error in parsing RTP payload: rtpPayloadSize=%u nBits=%d", rtpPayloadSize, *num_bits ); return G192_INVALID_DATA; @@ -453,10 +447,10 @@ G192_ERROR G192_WriteFrame( const uint16_t *serial, const int16_t numBits ) { - uint16_t G192_HEADER[2], G192_DATA[MAX_BITS_PER_FRAME]; + uint16_t G192_HEADER[2], G192_DATA[IVAS_MAX_BITS_PER_FRAME]; uint16_t i, bit; - assert( numBits <= MAX_BITS_PER_FRAME ); + assert( numBits <= IVAS_MAX_BITS_PER_FRAME ); G192_HEADER[0] = G192_SYNC_GOOD_FRAME; G192_HEADER[1] = numBits; /* Frame Length */ @@ -492,7 +486,7 @@ G192_ERROR G192_WriteVoipFrame_short( uint16_t const rtpTimeStamp, uint32_t const rcvTime_ms ) { - int16_t G192_HEADER[2], G192_DATA[MAX_BITS_PER_FRAME]; + int16_t G192_HEADER[2], G192_DATA[IVAS_MAX_BITS_PER_FRAME]; int16_t i, bit; uint32_t rtpPacketSize = numBits + 12 + 2; @@ -502,7 +496,7 @@ G192_ERROR G192_WriteVoipFrame_short( uint32_t rtpTimeStamp_2 = htonl( rtpTimeStamp ); uint16_t ssrc_2 = (uint16_t) htonl( ssrc ); - assert( numBits <= MAX_BITS_PER_FRAME ); + assert( numBits <= IVAS_MAX_BITS_PER_FRAME ); fwrite( &rtpPacketSize, sizeof( rtpPacketSize ), 1, hG192->file ); fwrite( &rcvTime_ms, sizeof( rcvTime_ms ), 1, hG192->file ); diff --git a/lib_util/g192.h b/lib_util/g192.h index c96b5bf7565c384617b212e29fb80407e2194988..2dfd34b9e547a3acf40a40617ebb4d84b5997457 100644 --- a/lib_util/g192.h +++ b/lib_util/g192.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -37,8 +37,9 @@ #ifndef G192_H #define G192_H G192_H +#include "common_api_types.h" #include -#include + /*-----------------------------------------------------------------------* * Enums diff --git a/lib_util/head_rotation_file_reader.c b/lib_util/head_rotation_file_reader.c index 1cf27cbfdbfe59079a96835e7e059b28fbb38474..02f14be9247c62fb5ba80701fab7de6d96a49c84 100644 --- a/lib_util/head_rotation_file_reader.c +++ b/lib_util/head_rotation_file_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,7 +31,6 @@ *******************************************************************************************************/ #include "head_rotation_file_reader.h" -#include #include #include #include @@ -46,28 +45,6 @@ struct HeadRotFileReader }; -/*-----------------------------------------------------------------------* - * HeadRotationFrameCheck() - * - * Check if the read frame number corresponds to the decoder frame - *-----------------------------------------------------------------------*/ - -static ivas_error HeadRotationFrameCheck( - HeadRotFileReader *headRotReader, /* i/o: HeadRotFileReader handle */ - const int32_t frame_dec ) -{ - if ( headRotReader->fileRewind == false ) - { - if ( headRotReader->frameCounter / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES != frame_dec + 1 ) - { - return IVAS_ERR_FILE_READER_TIMESTAMP_MISMATCH; - } - } - - return IVAS_ERR_OK; -} - - /*-----------------------------------------------------------------------* * HeadRotationFileReader_open() * @@ -116,53 +93,41 @@ ivas_error HeadRotationFileReader_open( ivas_error HeadRotationFileReading( HeadRotFileReader *headRotReader, /* i/o: HeadRotFileReader handle */ - IVAS_QUATERNION *Quaternions, /* o : head-tracking data */ - const int32_t frame_dec /* i : decoded frame number */ + IVAS_QUATERNION *pQuaternion, /* o : head-tracking data */ + IVAS_POSITION *pPos /* o : listener position */ ) { - uint16_t i; - int32_t time_stamp = 0; float w, x, y, z; + float posx, posy, posz; + int32_t read_values; - for ( i = 0; i < IVAS_MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) - { - if ( 5 != fscanf( headRotReader->trajFile, "%d,%f,%f,%f,%f", &time_stamp, &w, &x, &y, &z ) ) - { - if ( feof( headRotReader->trajFile ) ) - { - rewind( headRotReader->trajFile ); - headRotReader->fileRewind = true; - return HeadRotationFileReading( headRotReader, Quaternions, frame_dec ); - } - return IVAS_ERR_FAILED_FILE_PARSE; - } + posx = 0.0f; + posy = 0.0f; + posz = 0.0f; - - if ( headRotReader->fileRewind == false && headRotReader->frameCounter != time_stamp ) - { - return IVAS_ERR_FILE_READER_TIMESTAMP_MISMATCH; - } - - - ( headRotReader->frameCounter )++; - - Quaternions[i].w = w; - Quaternions[i].x = x; - Quaternions[i].y = y; - Quaternions[i].z = z; - } - - if ( headRotReader->fileRewind == false ) + read_values = fscanf( headRotReader->trajFile, "%f,%f,%f,%f,%f,%f,%f", &w, &x, &y, &z, &posx, &posy, &posz ); + if ( ( read_values != 4 ) && ( read_values != 7 ) ) /* Allow either orientation (4) or orientation+position (4+3) */ { - if ( ( time_stamp + 1 ) % IVAS_MAX_PARAM_SPATIAL_SUBFRAMES != 0 ) + if ( feof( headRotReader->trajFile ) ) { - return IVAS_ERR_FILE_READER_TIMESTAMP_MISMATCH; + rewind( headRotReader->trajFile ); + headRotReader->fileRewind = true; + return HeadRotationFileReading( headRotReader, pQuaternion, pPos ); } + return IVAS_ERR_FAILED_FILE_PARSE; } - if ( HeadRotationFrameCheck( headRotReader, frame_dec ) != IVAS_ERR_OK ) + ( headRotReader->frameCounter )++; + + pQuaternion->w = w; + pQuaternion->x = x; + pQuaternion->y = y; + pQuaternion->z = z; + if ( pPos != NULL ) { - return IVAS_ERR_FILE_READER_TIMESTAMP_MISMATCH; + pPos->x = posx; + pPos->y = posy; + pPos->z = posz; } return IVAS_ERR_OK; diff --git a/lib_util/head_rotation_file_reader.h b/lib_util/head_rotation_file_reader.h index 6664908b007804df41e74d1f73e7f6e8e3955453..4794aeba45b2d17e2c7552112ff292741ca9655d 100644 --- a/lib_util/head_rotation_file_reader.h +++ b/lib_util/head_rotation_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,7 +34,6 @@ #define IVAS_HR_FILE_READER_H #include "common_api_types.h" -#include "ivas_error.h" #define IVAS_MAX_PARAM_SPATIAL_SUBFRAMES 4 @@ -60,8 +59,8 @@ ivas_error HeadRotationFileReader_open( ivas_error HeadRotationFileReading( HeadRotFileReader *headRotReader, /* i/o: HeadRotFileReader handle */ - IVAS_QUATERNION *Quaternions, /* o : head-tracking data */ - const int32_t frame_dec /* i : decoded frame number */ + IVAS_QUATERNION *pQuaternion, /* o : head-tracking data */ + IVAS_POSITION *pPos /* o : listener position */ ); /*-----------------------------------------------------------------------* diff --git a/lib_util/hrtf_file_reader.c b/lib_util/hrtf_file_reader.c index 1dc481c84efa42a62dc5f979c335890c4b607495..b7ffe8168201577d495040cf84e2e20ac6b51add 100644 --- a/lib_util/hrtf_file_reader.c +++ b/lib_util/hrtf_file_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,18 +31,31 @@ *******************************************************************************************************/ #include "hrtf_file_reader.h" -#include #include #include "prot.h" -#include "ivas_prot.h" +#include "ivas_prot_rend.h" +/*---------------------------------------------------------------------* + * Local structures + *---------------------------------------------------------------------*/ + struct hrtfFileReader { FILE *file; char *file_path; }; +typedef struct ivas_hrtfs_file_header_t +{ + char identifier[8]; + int32_t file_size; + int16_t nb_hrtf; + int32_t max_data_size; + +} ivas_hrtfs_file_header_t; + + /*---------------------------------------------------------------------* * Local constants *---------------------------------------------------------------------*/ @@ -50,6 +63,12 @@ struct hrtfFileReader #define RESAMPLE_FACTOR_16_48 ( 16.0f / 48.0f ) #define RESAMPLE_FACTOR_32_48 ( 32.0f / 48.0f ) +/*---------------------------------------------------------------------* + * Local function declarations + *---------------------------------------------------------------------*/ + +static void HRTF_energy_sections_precalc( ModelParams_t *model ); + /*---------------------------------------------------------------------* * hrtfFileReader_open() * @@ -111,6 +130,111 @@ void hrtfFileReader_close( } +/*-------------------------------------------------------------------* + * read_and_check_hrtf_binary_file_header() + * + * Check the HRTF file header read from binary file + --------------------------------------------------------------------*/ + +static ivas_error read_and_check_hrtf_binary_file_header( + ivas_hrtfs_file_header_t *hrtf_file_header, + FILE *f_hrtf ) +{ + int32_t file_size; + + /* [Declaration of the binary file] */ + /* File Identifier (8 bytes) */ + /* Size of file in bytes (4 bytes) */ + /* Number of HRTF (2 bytes) */ + /* Max length of HRTF data (4 bytes) */ + + fseek( f_hrtf, 0, SEEK_END ); + file_size = ftell( f_hrtf ); + fseek( f_hrtf, 0, SEEK_SET ); + + if ( file_size < (int32_t) sizeof( ivas_hrtfs_file_header_t ) ) + { + return IVAS_ERROR( IVAS_ERR_END_OF_FILE, "HRTF binary file not compliant (size of file header)" ); + } + + fread( &( hrtf_file_header->identifier ), 8, 1, f_hrtf ); + if ( strncmp( hrtf_file_header->identifier, "IVASHRTF", 8 ) != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (identifier)" ); + } + + fread( &( hrtf_file_header->file_size ), 4, 1, f_hrtf ); + if ( hrtf_file_header->file_size != file_size ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (file size)" ); + } + + fread( &( hrtf_file_header->nb_hrtf ), 2, 1, f_hrtf ); + fread( &( hrtf_file_header->max_data_size ), 4, 1, f_hrtf ); + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * check_hrtf_binary_header() + * + * Check the HRTF section header - read from binary file + --------------------------------------------------------------------*/ + +static ivas_error check_hrtf_binary_header( + ivas_hrtfs_header_t *hrtf_header ) +{ + /* Check the renderer type */ + if ( ( hrtf_header->rend_type != RENDERER_BINAURAL_MIXER_CONV ) && ( hrtf_header->rend_type != RENDERER_BINAURAL_MIXER_CONV_ROOM ) && + ( hrtf_header->rend_type != RENDERER_BINAURAL_FASTCONV ) && ( hrtf_header->rend_type != RENDERER_BINAURAL_FASTCONV_ROOM ) && + ( hrtf_header->rend_type != RENDERER_BINAURAL_PARAMETRIC ) && ( hrtf_header->rend_type != RENDERER_BINAURAL_PARAMETRIC_ROOM ) && + ( hrtf_header->rend_type != RENDERER_BINAURAL_OBJECTS_TD ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (renderer type)" ); + } + + /* Check the output format of the decoder */ + if ( ( hrtf_header->input_cfg != BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) && ( hrtf_header->input_cfg != BINAURAL_INPUT_AUDIO_CONFIG_HOA ) && ( hrtf_header->input_cfg != BINAURAL_INPUT_AUDIO_CONFIG_UNDEFINED ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (input audio configuration)" ); + } + + /* Check the sampling frequency */ + if ( ( hrtf_header->frequency != 48000 ) && ( hrtf_header->frequency != 32000 ) && ( hrtf_header->frequency != 16000 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Header of HRTF binary file not compliant (sampling frequency)" ); + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * read_hrtf_binary_header() + * + * Read the HRTF header from binary file + --------------------------------------------------------------------*/ + +static ivas_error read_hrtf_binary_header( + ivas_hrtfs_header_t *hrtf_header, + FILE *f_hrtf ) +{ + /* HRTF Header */ + /* Renderer type (4 bytes) : See "RENDERER_TYPE" */ + /* Input configuration (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" */ + /* Sampling Frequency (4 bytes) */ + /* Raw data size (4 bytes) */ + + if ( ( fread( &( hrtf_header->rend_type ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) && ( fread( &( hrtf_header->input_cfg ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) && ( fread( &( hrtf_header->frequency ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) && ( fread( &( hrtf_header->data_size ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) ) + { + return IVAS_ERR_OK; + } + + return IVAS_ERR_END_OF_FILE; +} + + /*-------------------------------------------------------------------* * LoadBSplineBinaryITD() * @@ -126,16 +250,16 @@ static void LoadBSplineBinaryITD( fread( &modelITD->N, sizeof( int16_t ), 1, f_hrtf ); fread( &modelITD->elevDim2, sizeof( int16_t ), 1, f_hrtf ); fread( &modelITD->elevDim3, sizeof( int16_t ), 1, f_hrtf ); - modelITD->elevKSeq_dyn = (float *) count_malloc( ( modelITD->elevDim3 - 2 ) * sizeof( float ) ); + modelITD->elevKSeq_dyn = (float *) malloc( ( modelITD->elevDim3 - 2 ) * sizeof( float ) ); fread( modelITD->elevKSeq_dyn, sizeof( float ), modelITD->elevDim3 - 2, f_hrtf ); fread( &modelITD->azimDim2, sizeof( int16_t ), 1, f_hrtf ); fread( &modelITD->azimDim3, sizeof( int16_t ), 1, f_hrtf ); - modelITD->azimKSeq_dyn = (float *) count_malloc( ( ( modelITD->azimDim3 + 1 ) / 2 - 2 ) * sizeof( float ) ); /* basis functions are flipped around 180 deg, number of basis functions above/below is (N+1)/2 */ + modelITD->azimKSeq_dyn = (float *) malloc( ( ( modelITD->azimDim3 + 1 ) / 2 - 2 ) * sizeof( float ) ); /* basis functions are flipped around 180 deg, number of basis functions above/below is (N+1)/2 */ fread( modelITD->azimKSeq_dyn, sizeof( float ), ( modelITD->azimDim3 + 1 ) / 2 - 2, f_hrtf ); fread( &tmp, sizeof( int16_t ), 1, f_hrtf ); - modelITD->W_dyn = (float *) count_malloc( tmp * sizeof( float ) ); + modelITD->W_dyn = (float *) malloc( tmp * sizeof( float ) ); fread( modelITD->W_dyn, sizeof( float ), tmp, f_hrtf ); /* azimuth */ @@ -144,7 +268,7 @@ static void LoadBSplineBinaryITD( fread( &tmp, sizeof( int16_t ), 1, f_hrtf ); - modelITD->azimBsShape_dyn = (float *) count_malloc( tmp * sizeof( float ) ); + modelITD->azimBsShape_dyn = (float *) malloc( tmp * sizeof( float ) ); fread( modelITD->azimBsShape_dyn, sizeof( float ), tmp, f_hrtf ); fread( &modelITD->azimSegSamples, sizeof( int16_t ), 1, f_hrtf ); @@ -155,7 +279,7 @@ static void LoadBSplineBinaryITD( fread( &tmp, sizeof( int16_t ), 1, f_hrtf ); - modelITD->elevBsShape_dyn = (float *) count_malloc( tmp * sizeof( float ) ); + modelITD->elevBsShape_dyn = (float *) malloc( tmp * sizeof( float ) ); fread( modelITD->elevBsShape_dyn, sizeof( float ), tmp, f_hrtf ); fread( &modelITD->elevSegSamples, sizeof( int16_t ), 1, f_hrtf ); @@ -165,6 +289,7 @@ static void LoadBSplineBinaryITD( modelITD->W = (const float *) modelITD->W_dyn; modelITD->azimBsShape = (const float *) modelITD->azimBsShape_dyn; modelITD->elevBsShape = (const float *) modelITD->elevBsShape_dyn; + return; } @@ -183,6 +308,8 @@ static ivas_error LoadBSplineBinary( ModelParams_t *model; int16_t i, tmp; + fread( &HrFiltSet_p->latency_s, sizeof( float ), 1, f_hrtf ); + model = &( HrFiltSet_p->ModelParams ); /* Set ROM flag for correct deallocation */ @@ -223,51 +350,51 @@ static ivas_error LoadBSplineBinary( fread( &model->elevDim2, sizeof( int16_t ), 1, f_hrtf ); fread( &model->elevDim3, sizeof( int16_t ), 1, f_hrtf ); - model->elevKSeq_dyn = (float *) count_malloc( ( model->elevDim3 - 2 ) * sizeof( float ) ); + model->elevKSeq_dyn = (float *) malloc( ( model->elevDim3 - 2 ) * sizeof( float ) ); fread( model->elevKSeq_dyn, sizeof( float ), model->elevDim3 - 2, f_hrtf ); - model->azimDim2_dyn = (int16_t *) count_malloc( model->elevDim3 * sizeof( int16_t ) ); - model->azimDim3_dyn = (int16_t *) count_malloc( model->elevDim3 * sizeof( int16_t ) ); - model->azim_start_idx_dyn = (int16_t *) count_malloc( model->elevDim3 * sizeof( int16_t ) ); - model->azimKSeq = (float **) count_malloc( model->elevDim3 * sizeof( float * ) ); + model->azimDim2_dyn = (int16_t *) malloc( model->elevDim3 * sizeof( int16_t ) ); + model->azimDim3_dyn = (int16_t *) malloc( model->elevDim3 * sizeof( int16_t ) ); + model->azim_start_idx_dyn = (int16_t *) malloc( model->elevDim3 * sizeof( int16_t ) ); + model->azimKSeq = (float **) malloc( model->elevDim3 * sizeof( float * ) ); for ( i = 0; i < model->elevDim3; i++ ) { fread( &model->azimDim2_dyn[i], sizeof( int16_t ), 1, f_hrtf ); fread( &model->azimDim3_dyn[i], sizeof( int16_t ), 1, f_hrtf ); fread( &model->azim_start_idx_dyn[i], sizeof( int16_t ), 1, f_hrtf ); - model->azimKSeq[i] = (float *) count_malloc( ( model->azimDim3_dyn[i] + 1 ) * sizeof( float ) ); + model->azimKSeq[i] = (float *) malloc( ( model->azimDim3_dyn[i] + 1 ) * sizeof( float ) ); fread( model->azimKSeq[i], sizeof( float ), ( model->azimDim3_dyn[i] + 1 ), f_hrtf ); } fread( &model->AlphaN, sizeof( int16_t ), 1, f_hrtf ); - model->AlphaL_dyn = (float *) count_malloc( model->AlphaN * model->K * sizeof( float ) ); + model->AlphaL_dyn = (float *) malloc( model->AlphaN * model->K * sizeof( float ) ); fread( model->AlphaL_dyn, sizeof( float ), model->AlphaN * model->K, f_hrtf ); - model->AlphaR_dyn = (float *) count_malloc( model->AlphaN * model->K * sizeof( float ) ); + model->AlphaR_dyn = (float *) malloc( model->AlphaN * model->K * sizeof( float ) ); fread( model->AlphaR_dyn, sizeof( float ), model->AlphaN * model->K, f_hrtf ); /* azimuth */ fread( &model->num_unique_azim_splines, sizeof( int16_t ), 1, f_hrtf ); - model->azimBsShape = (const float **) count_malloc( model->num_unique_azim_splines * sizeof( float * ) ); - model->azimBsShape_dyn = (float **) count_malloc( model->num_unique_azim_splines * sizeof( float * ) ); - model->azimSegSamples_dyn = (int16_t *) count_malloc( model->num_unique_azim_splines * sizeof( int16_t ) ); + model->azimBsShape = (const float **) malloc( model->num_unique_azim_splines * sizeof( float * ) ); + model->azimBsShape_dyn = (float **) malloc( model->num_unique_azim_splines * sizeof( float * ) ); + model->azimSegSamples_dyn = (int16_t *) malloc( model->num_unique_azim_splines * sizeof( int16_t ) ); for ( i = 0; i < model->num_unique_azim_splines; i++ ) { fread( &tmp, sizeof( int16_t ), 1, f_hrtf ); - model->azimBsShape_dyn[i] = (float *) count_malloc( tmp * sizeof( float ) ); + model->azimBsShape_dyn[i] = (float *) malloc( tmp * sizeof( float ) ); fread( model->azimBsShape_dyn[i], sizeof( float ), tmp, f_hrtf ); fread( &model->azimSegSamples_dyn[i], sizeof( int16_t ), 1, f_hrtf ); } - model->azimShapeIdx_dyn = (int16_t *) count_malloc( model->elevDim3 * sizeof( int16_t ) ); + model->azimShapeIdx_dyn = (int16_t *) malloc( model->elevDim3 * sizeof( int16_t ) ); fread( model->azimShapeIdx_dyn, sizeof( int16_t ), model->elevDim3, f_hrtf ); - model->azimShapeSampFactor_dyn = (int16_t *) count_malloc( model->elevDim3 * sizeof( int16_t ) ); + model->azimShapeSampFactor_dyn = (int16_t *) malloc( model->elevDim3 * sizeof( int16_t ) ); fread( model->azimShapeSampFactor_dyn, sizeof( int16_t ), model->elevDim3, f_hrtf ); /* elevation */ fread( model->elevBsLen, sizeof( int16_t ), HRTF_MODEL_BSPLINE_NUM_COEFFS, f_hrtf ); fread( model->elevBsStart, sizeof( int16_t ), HRTF_MODEL_BSPLINE_NUM_COEFFS, f_hrtf ); fread( &tmp, sizeof( int16_t ), 1, f_hrtf ); - model->elevBsShape_dyn = (float *) count_malloc( tmp * sizeof( float ) ); + model->elevBsShape_dyn = (float *) malloc( tmp * sizeof( float ) ); fread( model->elevBsShape_dyn, sizeof( float ), tmp, f_hrtf ); fread( &model->elevSegSamples, sizeof( int16_t ), 1, f_hrtf ); @@ -292,9 +419,11 @@ static ivas_error LoadBSplineBinary( } HRTF_model_precalc( model ); + HRTF_energy_sections_precalc( model ); HrFiltSet_p->FiltLength = HrFiltSet_p->ModelParams.K; - BSplineModelEvalAlloc( &HrFiltSet_p->ModelParams, &HrFiltSet_p->ModelEval ); + HrFiltSet_p->ModelEval.hrfModL = (float *) malloc( model->K * sizeof( float ) ); + HrFiltSet_p->ModelEval.hrfModR = (float *) malloc( model->K * sizeof( float ) ); if ( HrFiltSet_p->ModelParams.UseItdModel ) { @@ -310,7 +439,7 @@ static ivas_error LoadBSplineBinary( * * Load HRTF model or table from file --------------------------------------------------------------------*/ -/*! r: TD Renderer result code. */ + static ivas_error TDREND_MIX_LoadHRTF( FILE *f_hrtf, /* i/o: File pointer to HRTF file */ IVAS_DEC_HRTF_HANDLE HrFiltSet_p /* o : Loaded HR filter set */ @@ -318,39 +447,84 @@ static ivas_error TDREND_MIX_LoadHRTF( { int16_t tmp; ivas_error error; + bool is_tdrend; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + ivas_hrtfs_header_t hrtf_header; + int32_t hrtf_data_size_max; + char *hrtf_data; error = IVAS_ERR_OK; - if ( fread( &tmp, sizeof( int16_t ), 1, f_hrtf ) == 0 ) + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) { - return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + return header_check_result; } - HrFiltSet_p->FilterMethod = (TDREND_HRFILT_Method_t) tmp; + is_tdrend = FALSE; + hrtf_data_size_max = hrtfs_file_header.max_data_size; -#ifdef TDREND_HRTF_TABLE_METHODS - switch ( HrFiltSet_p->FilterMethod ) + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) { - case TDREND_HRFILT_Method_BSplineModel: - error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); - break; - case TDREND_HRFILT_Method_Table_F: - case TDREND_HRFILT_Method_Table_S: - TDREND_HRFILT_SetFiltSet( HrFiltSet_p, f_hrtf ); - break; - default: - error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); } -#else - if ( HrFiltSet_p->FilterMethod != TDREND_HRFILT_Method_BSplineModel ) + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + for ( hrtf_id = 0; ( hrtf_id < hrtfs_file_header.nb_hrtf ) && ( !is_tdrend ); hrtf_id++ ) { - error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "HRTF binary file not compliant (number of HRTF)" ); + } + + if ( ( header_check_result = check_hrtf_binary_header( &hrtf_header ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + is_tdrend = ( hrtf_header.rend_type == RENDERER_BINAURAL_OBJECTS_TD ); + if ( !is_tdrend ) + { + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + } + } + + free( hrtf_data ); + + if ( is_tdrend ) + { + if ( fread( &tmp, 1, sizeof( int16_t ), f_hrtf ) == 0 ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + HrFiltSet_p->FilterMethod = (TDREND_HRFILT_Method_t) tmp; + + if ( HrFiltSet_p->FilterMethod != TDREND_HRFILT_Method_BSplineModel ) + { + error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); + } + else + { + error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); + } } else { - error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); + return IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "HR filter not found in binary file." ); } -#endif return error; } @@ -369,7 +543,1063 @@ ivas_error load_HRTF_binary( { ivas_error error; + fseek( hrtfReader->file, 0, SEEK_SET ); + error = TDREND_MIX_LoadHRTF( hrtfReader->file, hHrtf ); return error; } + +/*---------------------------------------------------------------------* + * HRTF_energy_sections_precalc() + * + * Calculate energies of each section and store in model->EL/model->ER + *---------------------------------------------------------------------*/ + +static void HRTF_energy_sections_precalc( + ModelParams_t *model /* i/o: HRTF model parameters */ +) +{ + int16_t i, k, j; + float *pEL; + float *pER; + const float *pAlphaL; + const float *pAlphaR; + float tmp; + int16_t AlphaN; + + if ( !model->modelROM ) + { + AlphaN = model->AlphaN; + + /* Precalculated energies for each section and each row of the alpha matrices */ + model->EL_dyn = (float *) malloc( HRTF_MODEL_N_SECTIONS * AlphaN * sizeof( float ) ); + model->ER_dyn = (float *) malloc( HRTF_MODEL_N_SECTIONS * AlphaN * sizeof( float ) ); + pEL = model->EL_dyn; + pER = model->ER_dyn; + for ( i = 0; i < HRTF_MODEL_N_SECTIONS; i++ ) + { + for ( j = 0; j < AlphaN; j++ ) /* rows of Alpha matrices */ + { + *pEL = 0.0f; + *pER = 0.0f; + + pAlphaL = &model->AlphaL[model->iSecFirst[i] * AlphaN + j]; + pAlphaR = &model->AlphaR[model->iSecFirst[i] * AlphaN + j]; + + for ( k = model->iSecFirst[i]; k < model->iSecLast[i]; k++ ) /* k within the sections */ + { + /* Energy calculation */ + tmp = *pAlphaL; + *pEL += tmp * tmp; + tmp = *pAlphaR; + *pER += tmp * tmp; + pAlphaL += AlphaN; + pAlphaR += AlphaN; + } + pEL++; + pER++; + } + } + model->EL = (const float *) model->EL_dyn; + model->ER = (const float *) model->ER_dyn; + } + + return; +} + + +/*---------------------------------------------------------------------* + * dealloc_HRTF_binary() + * + * Deallocated memory allocated by load_HRTF_binary + *---------------------------------------------------------------------*/ + +ivas_error dealloc_HRTF_binary( + IVAS_DEC_HRTF_HANDLE hHrtf /* i/o: HRTF handle */ +) +{ + int16_t i; + ivas_error error; + error = IVAS_ERR_OK; + + if ( hHrtf == NULL ) + { + return error; + } + + if ( !hHrtf->ModelParams.modelROM ) + { + if ( hHrtf->ModelParams.UseItdModel ) + { + free( hHrtf->ModelParamsITD.elevKSeq_dyn ); + free( hHrtf->ModelParamsITD.azimKSeq_dyn ); + free( hHrtf->ModelParamsITD.W_dyn ); + free( hHrtf->ModelParamsITD.azimBsShape_dyn ); + free( hHrtf->ModelParamsITD.elevBsShape_dyn ); + } + free( hHrtf->ModelParams.elevKSeq_dyn ); + free( hHrtf->ModelParams.azim_start_idx_dyn ); + free( hHrtf->ModelParams.azimDim2_dyn ); + free( hHrtf->ModelParams.azimDim3_dyn ); + free( hHrtf->ModelParams.AlphaL_dyn ); + free( hHrtf->ModelParams.AlphaR_dyn ); + free( hHrtf->ModelParams.azimSegSamples_dyn ); + + free( hHrtf->ModelParams.azimShapeIdx_dyn ); + free( hHrtf->ModelParams.azimShapeSampFactor_dyn ); + free( hHrtf->ModelParams.elevBsShape_dyn ); + + for ( i = 0; i < hHrtf->ModelParams.num_unique_azim_splines; i++ ) + { + free( hHrtf->ModelParams.azimBsShape_dyn[i] ); + free( &hHrtf->ModelParams.azimBsShape_dyn[i] ); + } + + free( (void *) hHrtf->ModelParams.azimBsShape ); /* void* cast needed to please both gcc and Visual studio compilers. Deallocating const float** should be fine and gcc agrees, but Visual studio complains. */ + for ( i = 0; i < hHrtf->ModelParams.elevDim3; i++ ) + { + free( hHrtf->ModelParams.azimKSeq[i] ); + } + free( hHrtf->ModelParams.azimKSeq ); + + free( hHrtf->ModelParams.EL_dyn ); + free( hHrtf->ModelParams.ER_dyn ); + + free( hHrtf->ModelEval.hrfModL ); + free( hHrtf->ModelEval.hrfModR ); + } + + return error; +} + + +/*------------------------------------------------------------------------- + * ivas_hrtf_init() + * + * Initialize hHRTF handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_hrtf_init( + HRTFS_DATA *hHRTF /* i/o: HRTF handle */ +) +{ + int16_t i, j; + + if ( hHRTF == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hHRTF->latency_s = 0; + hHRTF->max_num_ir = 0; + hHRTF->max_num_iterations = 0; + hHRTF->index_frequency_max_diffuse = 0; + + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + hHRTF->inv_diffuse_weight[i] = 0; + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHRTF->num_iterations[i][j] = 0; + hHRTF->pIndex_frequency_max[i][j] = NULL; + hHRTF->pOut_to_bin_re[i][j] = NULL; + hHRTF->pOut_to_bin_im[i][j] = NULL; + } + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHRTF->num_iterations_diffuse[j] = 0; + hHRTF->pIndex_frequency_max_diffuse[j] = NULL; + hHRTF->pOut_to_bin_diffuse_re[j] = NULL; + hHRTF->pOut_to_bin_diffuse_im[j] = NULL; + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * create_HRTF_from_rawdata() + * + * Create HRTF from the raw data (to the HRTF CRend handle) + *---------------------------------------------------------------------*/ + +static ivas_error create_HRTF_from_rawdata( + HRTFS_HANDLE *hHRTF, /* i/o: HRTF CRend handle */ + char *hrtf_data /* i: pointer to binary file */ +) +{ + int16_t i, j, k; + int16_t max_num_iterations_diffuse; + uint16_t max_total_num_fsamp_per_iteration, max_total_num_fsamp_per_iteration_diff; + uint32_t mem_size; + char *hrtf_data_rptr; + float *pOut_to_bin_wptr; + + if ( *hHRTF == NULL ) + { + if ( ( ( *hHRTF ) = (HRTFS_HANDLE) malloc( sizeof( HRTFS_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "Can not allocate memory for HRTF binary data\n" ); + } + + ivas_hrtf_init( *hHRTF ); + } + else + { + return IVAS_ERR_INTERNAL; + } + + hrtf_data_rptr = hrtf_data; + + /* latency_s */ + ( *hHRTF )->latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + /* max_num_ir */ + ( *hHRTF )->max_num_ir = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + /* BINAURAL_CHANNELS */ + if ( BINAURAL_CHANNELS != *( (int16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file format not compliant (BINAURAL_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + /* max_num_iterations */ + ( *hHRTF )->max_num_iterations = *( (int16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( int16_t ); + + /* num_iterations */ + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + ( *hHRTF )->num_iterations[i][j] = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + } + } + + /* pIndex_frequency_max */ + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = ( *hHRTF )->max_num_iterations * sizeof( uint16_t ); + ( *hHRTF )->pIndex_frequency_max[i][j] = (uint16_t *) malloc( mem_size ); + if ( ( *hHRTF )->pIndex_frequency_max[i][j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pIndex_frequency_max" ); + } + memcpy( ( *hHRTF )->pIndex_frequency_max[i][j], hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + } + } + + /* max_num_iterations_diffuse */ + max_num_iterations_diffuse = *( (int16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( int16_t ); + + if ( max_num_iterations_diffuse != 0 ) + { + /* num_iterations_diffuse */ + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + ( *hHRTF )->num_iterations_diffuse[j] = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + } + + /* pIndex_frequency_max_diffuse (the size depends on num_iterations_diffuse) */ + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = ( *hHRTF )->num_iterations_diffuse[j] * sizeof( uint16_t ); + ( *hHRTF )->pIndex_frequency_max_diffuse[j] = (uint16_t *) malloc( mem_size ); + if ( ( *hHRTF )->pIndex_frequency_max_diffuse[j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pIndex_frequency_max_diffuse" ); + } + memcpy( ( *hHRTF )->pIndex_frequency_max_diffuse[j], hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + } + } + + /* index_frequency_max_diffuse */ + ( *hHRTF )->index_frequency_max_diffuse = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + /* inv_diffuse_weight */ + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + ( *hHRTF )->inv_diffuse_weight[i] = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + } + + /* max_total_num_fsamp_per_iteration */ + max_total_num_fsamp_per_iteration = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + /* coeff_re (the size depends on pIndex_frequency_max) */ + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration * sizeof( float ); + ( *hHRTF )->pOut_to_bin_re[i][j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_re[i][j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for Out_to_bin_re" ); + } + memset( ( *hHRTF )->pOut_to_bin_re[i][j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_re[i][j]; + for ( k = 0; k < ( *hHRTF )->num_iterations[i][j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max[i][j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max[i][j][k]; + } + } + } + + /* coeff_im (the size depends on pIndex_frequency_max) */ + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration * sizeof( float ); + ( *hHRTF )->pOut_to_bin_im[i][j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_im[i][j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for Out_to_bin_im" ); + } + memset( ( *hHRTF )->pOut_to_bin_im[i][j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_im[i][j]; + for ( k = 0; k < ( *hHRTF )->num_iterations[i][j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max[i][j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max[i][j][k]; + } + } + } + + /* max_total_num_fsamp_per_iteration_diff */ + max_total_num_fsamp_per_iteration_diff = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + if ( max_total_num_fsamp_per_iteration_diff != 0 ) + { + /* coeff_diffuse_re : The size depends on pIndex_frequency_max_diffuse */ + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration_diff * sizeof( float ); + ( *hHRTF )->pOut_to_bin_diffuse_re[j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_diffuse_re[j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pOut_to_bin_diffuse_re" ); + } + memset( ( *hHRTF )->pOut_to_bin_diffuse_re[j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_diffuse_re[j]; + for ( k = 0; k < ( *hHRTF )->num_iterations_diffuse[j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max_diffuse[j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max_diffuse[j][k]; + } + } + + /* coeff_diffuse_im : The size depends on pIndex_frequency_max_diffuse */ + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration_diff * sizeof( float ); + ( *hHRTF )->pOut_to_bin_diffuse_im[j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_diffuse_im[j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pOut_to_bin_diffuse_im" ); + } + memset( ( *hHRTF )->pOut_to_bin_diffuse_im[j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_diffuse_im[j]; + for ( k = 0; k < ( *hHRTF )->num_iterations_diffuse[j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max_diffuse[j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max_diffuse[j][k]; + } + } + } + + return IVAS_ERR_OK; +} + +static ivas_error init_fastconv_HRTF_handle( + HRTFS_FASTCONV *hHrtf /* i/o: HRTF FastConv handle */ +) +{ + int16_t i, j; + + if ( hHrtf == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hHrtf->FASTCONV_HRIR_latency_s = 0; + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + set_zero( hHrtf->leftHRIRReal[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->leftHRIRImag[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRReal[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRImag[i][j], BINAURAL_NTAPS ); + } + } + + hHrtf->FASTCONV_HOA3_latency_s = 0; + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + set_zero( hHrtf->leftHRIRReal_HOA3[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->leftHRIRImag_HOA3[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRReal_HOA3[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRImag_HOA3[i][j], BINAURAL_NTAPS ); + } + } + + hHrtf->FASTCONV_BRIR_latency_s = 0; + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + set_zero( hHrtf->leftBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + set_zero( hHrtf->leftBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + set_zero( hHrtf->rightBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + set_zero( hHrtf->rightBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + } + } + + set_zero( hHrtf->fastconvReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + set_zero( hHrtf->fastconvReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + + return IVAS_ERR_OK; +} + + +static ivas_error create_fastconv_HRTF_from_rawdata( + HRTFS_FASTCONV_HANDLE *hHRTF, /* i/o: HRTF FastConv handle */ + char *hrtf_data, /* i : pointer to binary file */ + RENDERER_TYPE rend_type, /* i : Renderer type */ + BINAURAL_INPUT_AUDIO_CONFIG input_cfg /* i : Input binaural config */ +) +{ + int16_t i, j; + char *hrtf_data_rptr; + + // if ( hHRTF == NULL ) + // { + // if ( ( ( *hHRTF ) = (HRTFS_FASTCONV_HANDLE) count_malloc( sizeof( HRTFS_FASTCONV ) ) ) == NULL ) + // { + // return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "Can not allocate memory for Fastconv HRTF binary\n" ); + // } + + // init_fastconv_HRTF_handle( *hHRTF ); + // } + // else + // { + // return IVAS_ERR_INTERNAL; + // } + + hrtf_data_rptr = hrtf_data; + + /* BINAURAL_CONVBANDS */ + if ( BINAURAL_CONVBANDS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_CONVBANDS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + /* HRIR */ + if ( rend_type == RENDERER_BINAURAL_FASTCONV && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + ( *hHRTF )->FASTCONV_HRIR_latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + if ( HRTF_LS_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_LS_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + if ( BINAURAL_NTAPS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_NTAPS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + } + if ( rend_type == RENDERER_BINAURAL_FASTCONV && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + /* HRIR_HOA3 */ + ( *hHRTF )->FASTCONV_HOA3_latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + if ( HRTF_SH_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_SH_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + if ( BINAURAL_NTAPS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_NTAPS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRReal_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRImag_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRReal_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRImag_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + } + /* BRIR */ + if ( rend_type == RENDERER_BINAURAL_FASTCONV_ROOM && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + ( *hHRTF )->FASTCONV_BRIR_latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + if ( HRTF_LS_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_LS_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + if ( BINAURAL_NTAPS_MAX != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_NTAPS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftBRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftBRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightBRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightBRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + + /* Reverb Parameters */ + if ( CLDFB_NO_CHANNELS_MAX != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (CLDFB_NO_CHANNELS_MAX)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + memcpy( ( *hHRTF )->fastconvReverberationTimes, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->fastconvReverberationEneCorrections, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * load_fastconv_HRTF_from_binary() + * + * Load FastConv HRTF binary data into the handle + *---------------------------------------------------------------------*/ + +ivas_error load_fastconv_HRTF_from_binary( + IVAS_DEC_HRTF_FASTCONV_HANDLE hHrtfFastConv, /* i/o: FastConv HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +) +{ + FILE *f_hrtf; + int32_t hrtf_data_size_max; + char *hrtf_data; + ivas_hrtfs_header_t hrtf_header; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + + f_hrtf = hrtfReader->file; + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + hrtf_data_size_max = hrtfs_file_header.max_data_size; + + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); + } + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + /* Read & load */ + + memset( hHrtfFastConv, 0x00, sizeof( HRTFS_FASTCONV ) ); + + for ( hrtf_id = 0; hrtf_id < hrtfs_file_header.nb_hrtf; hrtf_id++ ) + { + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "HRTF binary file not compliant (number of HRTF)" ); + } + + if ( ( hrtf_header.frequency == 48000 ) && + ( ( hrtf_header.rend_type == RENDERER_BINAURAL_FASTCONV ) || ( hrtf_header.rend_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) ) + { + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + /* Create the HRTF reading the raw data from the binary file */ + if ( ( create_fastconv_HRTF_from_rawdata( &hHrtfFastConv, hrtf_data, hrtf_header.rend_type, hrtf_header.input_cfg ) ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create HRTF from binary file" ); + } + } + else + { + fseek( f_hrtf, hrtf_header.data_size, SEEK_CUR ); + } + } + free( hrtf_data ); + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * create_parambin_HRTF_from_rawdata() + * + * + *---------------------------------------------------------------------*/ + +static ivas_error create_parambin_HRTF_from_rawdata( + HRTFS_PARAMBIN_HANDLE *hHRTF, /* i/o: Parametric binauralizer HRTF handle */ + char *hrtf_data /* i : pointer to binary file */ +) +{ + int16_t i, j; + char *hrtf_data_rptr; + uint32_t data_size_tmp; + + hrtf_data_rptr = hrtf_data; + + /* HRTF_SH_CHANNELS */ + if ( HRTF_SH_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_SH_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + /* HRTF_NUM_BINS */ + if ( HRTF_NUM_BINS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_NUM_BINS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + /* HRTF */ + data_size_tmp = HRTF_NUM_BINS * sizeof( float ); + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->hrtfShCoeffsRe[i][j], hrtf_data_rptr, data_size_tmp ); + hrtf_data_rptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->hrtfShCoeffsIm[i][j], hrtf_data_rptr, data_size_tmp ); + hrtf_data_rptr += data_size_tmp; + } + } + + /* Reverb Parameters */ + if ( CLDFB_NO_CHANNELS_MAX != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (CLDFB_NO_CHANNELS_MAX)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + memcpy( ( *hHRTF )->parametricReverberationTimes, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->parametricReverberationEneCorrections, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->parametricEarlyPartEneCorrection, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * load_parambin_HRTF_from_binary() + * + * Load parametric binauralizer HRTF binary data into the handle + *---------------------------------------------------------------------*/ + +ivas_error load_parambin_HRTF_from_binary( + IVAS_DEC_HRTF_PARAMBIN_HANDLE hHrtfParamBin, /* i/o: Parametric binauralizer HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +) +{ + FILE *f_hrtf; + int32_t hrtf_data_size_max; + char *hrtf_data; + ivas_hrtfs_header_t hrtf_header; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + + f_hrtf = hrtfReader->file; + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + hrtf_data_size_max = hrtfs_file_header.max_data_size; + + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); + } + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + /* Read & load */ + memset( hHrtfParamBin, 0x00, sizeof( HRTFS_PARAMBIN ) ); + + for ( hrtf_id = 0; hrtf_id < hrtfs_file_header.nb_hrtf; hrtf_id++ ) + { + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "HRTF binary file not compliant (number of HRTF)" ); + } + + if ( hrtf_header.rend_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Parametric binauralizer data is represented as single entity */ + { + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + /* Create the HRTF reading the raw data from the binary file */ + if ( ( create_parambin_HRTF_from_rawdata( &hHrtfParamBin, hrtf_data ) ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create HRTF from binary file" ); + } + } + else + { + fseek( f_hrtf, hrtf_header.data_size, SEEK_CUR ); + } + } + free( hrtf_data ); + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * create_SetOfHRTF_from_binary() + * + * Create the HRTF data set from the binary file + *---------------------------------------------------------------------*/ + +ivas_error create_SetOfHRTF_from_binary( + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF, /* i/o: HRTF CRend handle */ + const hrtfFileReader *hrtfReader, /* i : pointer to hrtfFileReader handle */ + int32_t output_Fs ) /* i : Output sampling frequency */ +{ + FILE *f_hrtf; + int32_t hrtf_data_size_max; + char *hrtf_data; + ivas_hrtfs_header_t hrtf_header; + HRTFS_DATA **hHRTF; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + + f_hrtf = hrtfReader->file; + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + hrtf_data_size_max = hrtfs_file_header.max_data_size; + + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); + } + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + /* Read & load */ + + memset( hSetOfHRTF, 0x00, sizeof( HRTFS_CREND ) ); + + for ( hrtf_id = 0; hrtf_id < hrtfs_file_header.nb_hrtf; hrtf_id++ ) + { + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "HRTF binary file not compliant (number of HRTF)" ); + } + + hHRTF = NULL; + if ( hrtf_header.frequency == output_Fs ) + { + if ( hrtf_header.rend_type == RENDERER_BINAURAL_MIXER_CONV ) + { + if ( hrtf_header.input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + hHRTF = &( ( *hSetOfHRTF ).hHRTF_hrir_combined ); + } + else if ( hrtf_header.input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + hHRTF = &( ( *hSetOfHRTF ).hHRTF_hrir_hoa3 ); + } + } + else if ( hrtf_header.rend_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + if ( hrtf_header.input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + hHRTF = &( ( *hSetOfHRTF ).hHRTF_brir_combined ); + } + } + } + + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + if ( hHRTF != NULL ) + { + /* Create the HRTF reading the raw data from the binary file */ + if ( ( create_HRTF_from_rawdata( hHRTF, hrtf_data ) ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create HRTF from binary file" ); + } + } + } + + free( hrtf_data ); + + if ( ( ( *hSetOfHRTF ).hHRTF_hrir_combined == NULL ) || ( ( *hSetOfHRTF ).hHRTF_brir_combined == NULL ) || ( ( *hSetOfHRTF ).hHRTF_hrir_hoa3 == NULL ) ) + { + destroy_SetOfHRTF( hSetOfHRTF ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create all the HRTF from binary file" ); + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * destroy_HRTF() + * + * Destroy the HRTF CRend handle + *---------------------------------------------------------------------*/ + +static ivas_error destroy_HRTF( + HRTFS_HANDLE *hHRTF /* i/o: HRTF CRend handle */ +) +{ + uint16_t i, j; + + if ( *hHRTF != NULL && hHRTF != NULL ) + { + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( ( *hHRTF )->pIndex_frequency_max[i][j] != NULL ) + { + free( ( *hHRTF )->pIndex_frequency_max[i][j] ); + } + if ( ( *hHRTF )->pOut_to_bin_re[i][j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_re[i][j] ); + } + if ( ( *hHRTF )->pOut_to_bin_im[i][j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_im[i][j] ); + } + } + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( ( *hHRTF )->pIndex_frequency_max_diffuse[j] != NULL ) + { + free( ( *hHRTF )->pIndex_frequency_max_diffuse[j] ); + } + if ( ( *hHRTF )->pOut_to_bin_diffuse_re[j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_diffuse_re[j] ); + } + if ( ( *hHRTF )->pOut_to_bin_diffuse_im[j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_diffuse_im[j] ); + } + } + + free( *hHRTF ); + *hHRTF = NULL; + } + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * destroy_SetOfHRTF() + * + * Destroy the HRTF data set. + *---------------------------------------------------------------------*/ + +ivas_error destroy_SetOfHRTF( + HRTFS_CREND_HANDLE hSetOfHRTF /* i/o: Set of HRTF CRend handle */ +) +{ + if ( hSetOfHRTF != NULL ) + { + destroy_HRTF( &( hSetOfHRTF->hHRTF_hrir_combined ) ); + destroy_HRTF( &( hSetOfHRTF->hHRTF_hrir_hoa3 ) ); + destroy_HRTF( &( hSetOfHRTF->hHRTF_brir_combined ) ); + } + + return IVAS_ERR_OK; +} diff --git a/lib_util/hrtf_file_reader.h b/lib_util/hrtf_file_reader.h index ed3d572d56047e36cd629de40f40ec21b8755f15..2b59c3150b25c054aaaece41fc1829a8fc781f84 100644 --- a/lib_util/hrtf_file_reader.h +++ b/lib_util/hrtf_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,13 +33,20 @@ #ifndef IVAS_HRTF_FILE_READER_H #define IVAS_HRTF_FILE_READER_H -#include #include "common_api_types.h" -#include "ivas_error.h" typedef struct hrtfFileReader hrtfFileReader; +typedef struct ivas_hrtfs_header_t +{ + int32_t rend_type; + int32_t input_cfg; + int32_t frequency; + uint32_t data_size; + +} ivas_hrtfs_header_t; + /*---------------------------------------------------------------------* * hrtfFileReader_open() * @@ -72,4 +79,62 @@ ivas_error load_HRTF_binary( const hrtfFileReader *hrtfReader /* i/o: pointer to hrtfFileReader handle */ ); +/*---------------------------------------------------------------------* + * create_SetOfHRTF_from_binary() + * + * Create the HRTF data set from the binary file + *---------------------------------------------------------------------*/ + +ivas_error create_SetOfHRTF_from_binary( + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF, /* i/o: Set of HRTF CRend handle */ + const hrtfFileReader *hrtfReader, /* i: pointer to hrtfFileReader handle */ + int32_t output_Fs /* i: Output sampling frequency */ +); + + +/*---------------------------------------------------------------------* + * destroy_SetOfHRTF() + * + * Destroy the HRTF data set. + *---------------------------------------------------------------------*/ + +ivas_error destroy_SetOfHRTF( + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF /* i/o: Set of HRTF CRend handle */ +); + + +/*---------------------------------------------------------------------* + * load_fastconv_HRTF_from_binary() + * + * Load FastConv HRTF binary data into the handle + *---------------------------------------------------------------------*/ + +ivas_error load_fastconv_HRTF_from_binary( + IVAS_DEC_HRTF_FASTCONV_HANDLE hHrtfFastConv, /* i/o: FastConv HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +); + + +/*---------------------------------------------------------------------* + * load_parambin_HRTF_from_binary() + * + * Load parametric binauralizer HRTF binary data into the handle + *---------------------------------------------------------------------*/ + +ivas_error load_parambin_HRTF_from_binary( + IVAS_DEC_HRTF_PARAMBIN_HANDLE hHrtfParambin, /* i/o: Parambin HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +); + + +/*---------------------------------------------------------------------* + * dealloc_HRTF_binary() + * + * Deallocated memory allocated by load_HRTF_binary + *---------------------------------------------------------------------*/ + +ivas_error dealloc_HRTF_binary( + IVAS_DEC_HRTF_HANDLE hHrtf /* i/o: HRTF handle */ +); + #endif /* IVAS_HRTF_FILE_READER_H */ diff --git a/lib_util/ism_file_reader.c b/lib_util/ism_file_reader.c index c3e45fa44661b938a7fb85437003395f262143f5..0aeca6d6a06e36cdf8df76f6971670d356fb0923 100644 --- a/lib_util/ism_file_reader.c +++ b/lib_util/ism_file_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,24 +31,31 @@ *******************************************************************************************************/ #include "ism_file_reader.h" -#include +#include "cmdl_tools.h" #include #include #define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ -#define NUM_ISM_METADATA_PER_LINE 5 /* Number of ISM metadata per line in a metadata file */ +#define NUM_ISM_METADATA_PER_LINE 7 /* Number of ISM metadata per line in a metadata file */ +#define NUM_MIN_ISM_METADATA 2 /* Minimum number of metadata parameters (azimuth and elevation) */ struct IsmFileReader { FILE *file; - int32_t frameCounter; char *file_path; }; + +/*---------------------------------------------------------------------* + * IsmFileReader_open() + * + * Allocates memory for an IsmFileReader and opens the file at given path for reading. + *---------------------------------------------------------------------*/ + IsmFileReader *IsmFileReader_open( - const char *filePath /* i : path to ism metadata file */ + const char *filePath /* i : path to ISM metadata file */ ) { IsmFileReader *self; @@ -68,26 +75,38 @@ IsmFileReader *IsmFileReader_open( self = calloc( sizeof( IsmFileReader ), 1 ); self->file = file; - self->frameCounter = 0; self->file_path = calloc( sizeof( char ), strlen( filePath ) + 1 ); strcpy( self->file_path, filePath ); return self; } + +/*---------------------------------------------------------------------* + * IsmFileReader_readNextFrame() + * + * Reads ISM metadata from a previously opened file into the provided struct. + *---------------------------------------------------------------------*/ + /*! r: error code */ ivas_error IsmFileReader_readNextFrame( IsmFileReader *self, /* i/o: IsmFileReader handle */ - IVAS_ISM_METADATA *ismMetadata /* o ISM : metadata read from the opened file */ + IVAS_ISM_METADATA *ismMetadata /* o : ISM metadata read from the opened file */ ) { char char_buff[META_LINE_LENGTH]; float meta_prm[NUM_ISM_METADATA_PER_LINE]; + const float meta_prm_default[NUM_ISM_METADATA_PER_LINE] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; char *char_ptr; int16_t i; - int32_t time_stamp; FILE *file; + /* Set default metadata parameters */ + for ( i = 0; i < NUM_ISM_METADATA_PER_LINE; i++ ) + { + meta_prm[i] = meta_prm_default[i]; + } + if ( ismMetadata == NULL || self->file == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; @@ -101,36 +120,95 @@ ivas_error IsmFileReader_readNextFrame( } char_ptr = strtok( char_buff, "," ); - time_stamp = (int32_t) atoi( char_ptr ); - - if ( time_stamp != self->frameCounter ) + i = 0; + meta_prm[i++] = (float) atof( char_ptr ); + if ( is_number( char_ptr ) == false ) { - return IVAS_ERR_FILE_READER_TIMESTAMP_MISMATCH; + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; } - - i = 0; while ( ( char_ptr = strtok( NULL, "," ) ) != NULL && i < NUM_ISM_METADATA_PER_LINE ) { + if ( is_number( char_ptr ) == false ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } + meta_prm[i++] = (float) atof( char_ptr ); } - - if ( i != NUM_ISM_METADATA_PER_LINE ) +#ifdef FIX_379_EXT_METADATA + /* Verify the number of metadata values. */ + if ( i < NUM_MIN_ISM_METADATA || char_ptr != NULL ) + { + /* Invalid number of metadata parameters (2-7 supported) */ + return IVAS_ERR_ISM_FILE_READER_INVALID_METADATA_FORMAT; + } +#else + /* Check if minimum number of metadata values were read. Additional values are ignored. */ + if ( i < NUM_MIN_ISM_METADATA ) { /* Not enough values provided in one line */ return IVAS_ERR_ISM_FILE_READER_INVALID_METADATA_FORMAT; } +#endif + ismMetadata->azimuth = meta_prm[0]; ismMetadata->elevation = meta_prm[1]; ismMetadata->radius = meta_prm[2]; ismMetadata->spread = meta_prm[3]; ismMetadata->gainFactor = meta_prm[4]; + ismMetadata->yaw = meta_prm[5]; + ismMetadata->pitch = meta_prm[6]; + + /* verify whether the read metadata values are in an expected range */ + if ( ismMetadata->azimuth > 180 || ismMetadata->azimuth < -180 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } - ++self->frameCounter; + if ( ismMetadata->elevation > 90 || ismMetadata->elevation < -90 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } + +#ifdef FIX_379_EXT_METADATA + if ( ismMetadata->radius < 0 ) /* Negative radius not supported. Max quantized radius = (2^ISM_RADIUS_NBITS-1)*0.25 = 15.75 */ +#else + if ( ismMetadata->radius < 0 ) // Ivas_fmToDo: to be reviewed +#endif + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } + + if ( ismMetadata->spread > 360 || ismMetadata->spread < 0 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } + + if ( ismMetadata->gainFactor > 1 || ismMetadata->gainFactor < 0 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } + if ( ismMetadata->yaw > 180 || ismMetadata->yaw < -180 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } + + if ( ismMetadata->pitch > 90 || ismMetadata->pitch < -90 ) + { + return IVAS_ERR_ISM_INVALID_METADATA_VALUE; + } return IVAS_ERR_OK; } + +/*---------------------------------------------------------------------* + * IsmFileReader_close() + * + * De-allocates all underlying memory of an IsmFileReader. + *---------------------------------------------------------------------*/ + void IsmFileReader_close( IsmFileReader **selfPtr /* i/o: pointer to IsmFileReader handle */ ) @@ -148,6 +226,12 @@ void IsmFileReader_close( return; } + +/*---------------------------------------------------------------------* + * IsmFileReader_getFilePath() + * + *---------------------------------------------------------------------*/ + const char *IsmFileReader_getFilePath( IsmFileReader *self /* i/o: IsmFileReader handle */ ) diff --git a/lib_util/ism_file_reader.h b/lib_util/ism_file_reader.h index 294b26260e0cb5c2665e47554a2eb7cad65e9ab6..8ddb67704e4db1c30bddb2e3dd207a226b6de90e 100644 --- a/lib_util/ism_file_reader.h +++ b/lib_util/ism_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,49 +33,28 @@ #ifndef IVAS_ISM_FILE_READER_H #define IVAS_ISM_FILE_READER_H -#include #include "common_api_types.h" -#include "ivas_error.h" +/* clang-format off */ typedef struct IsmFileReader IsmFileReader; -/* clang-format off */ -/*---------------------------------------------------------------------* - * IsmFileReader_open() - * - * Allocates memory for an IsmFileReader and opens the file at given path for reading. - *---------------------------------------------------------------------*/ /*! r: IsmFileReader handle */ IsmFileReader *IsmFileReader_open( const char *filePath /* i : path to ISM metadata file */ ); -/*---------------------------------------------------------------------* - * IsmFileReader_readNextFrame() - * - * Reads ISM metadata from a previously opened file into the provided struct. - *---------------------------------------------------------------------*/ /*! r: error code */ ivas_error IsmFileReader_readNextFrame( IsmFileReader *self, /* i/o: IsmFileReader handle */ IVAS_ISM_METADATA *ismMetadata /* o : ISM metadata read from the opened file */ ); -/*---------------------------------------------------------------------* - * IsmFileReader_close() - * - * De-allocates all underlying memory of an IsmFileReader. - *---------------------------------------------------------------------*/ void IsmFileReader_close( IsmFileReader **selfPtr /* i/o: pointer to IsmFileReader handle */ ); -/*---------------------------------------------------------------------* - * IsmFileReader_getFilePath() - * - *---------------------------------------------------------------------*/ /*! r: path to the currently opened file or NULL if `self` is NULL */ const char *IsmFileReader_getFilePath( IsmFileReader* self /* i/o: IsmFileReader handle */ diff --git a/lib_util/ism_file_writer.c b/lib_util/ism_file_writer.c index 64f04f7b02d0d0052f47a446c7ba3a7260fe6099..b29386282b016342c147f0c60775a8b9eb314ba4 100644 --- a/lib_util/ism_file_writer.c +++ b/lib_util/ism_file_writer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,19 +31,16 @@ *******************************************************************************************************/ #include "ism_file_writer.h" -#include #include #include -#define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ -#define NUM_ISM_METADATA_PER_LINE 5 /* Number of ISM metadata per line in a metadata file */ +#define META_LINE_LENGTH 200 /* max number of characters at one line of metadata input/output file */ struct IsmFileWriter { FILE *file; - int32_t frameCounter; char *file_path; }; @@ -56,7 +53,7 @@ struct IsmFileWriter /*! r: error code */ ivas_error IsmFileWriter_open( const char *filePathWav, /* i : path to output file */ - const int16_t obj_num, /* i : ISm number */ + const int16_t obj_num, /* i : number of ISM channels */ IsmFileWriter **ismWriter /* o : IsmFileWriter handle */ ) { @@ -65,7 +62,7 @@ ivas_error IsmFileWriter_open( FILE *file; strncpy( metadata_filename_loc, filePathWav, sizeof( metadata_filename_loc ) - 1 ); - sprintf( ext_meta, ".%d.csv", obj_num ); + snprintf( ext_meta, sizeof( ext_meta ), ".%d.csv", obj_num ); const int32_t maxNumCharactersToAppend = (int32_t) sizeof( metadata_filename_loc ) - strlen( metadata_filename_loc ) - 1; strncat( metadata_filename_loc, ext_meta, maxNumCharactersToAppend ); @@ -86,7 +83,6 @@ ivas_error IsmFileWriter_open( self = calloc( sizeof( IsmFileWriter ), 1 ); self->file = file; - self->frameCounter = 0; self->file_path = calloc( sizeof( char ), strlen( filePath ) + 1 ); strcpy( self->file_path, filePath ); @@ -118,7 +114,10 @@ ivas_error IsmFileWriter_writeFrame( file = ismWriter->file; /* IVAS_fmToDo: work in progress; currently position_azimuth, position_elevation, position_radius, spread, gain_factor */ - sprintf( char_buff, "%04d,%+07.2f,%+06.2f,%05.2f,%06.2f,%04.2f\n", ismWriter->frameCounter, ismMetadata.azimuth, ismMetadata.elevation, ismMetadata.radius, ismMetadata.spread, ismMetadata.gainFactor ); +#ifdef FIX_293_EXT_RENDERER_CLI + sprintf( char_buff, "%+07.2f,%+06.2f,%05.2f,%06.2f,%04.2f,%+07.2f,%+06.2f\n", ismMetadata.azimuth, ismMetadata.elevation, ismMetadata.radius, ismMetadata.spread, ismMetadata.gainFactor, ismMetadata.yaw, ismMetadata.pitch ); +#endif + snprintf( char_buff, sizeof( char_buff ), "%+07.2f,%+06.2f,%05.2f,%06.2f,%04.2f,%+07.2f,%+06.2f\n", ismMetadata.azimuth, ismMetadata.elevation, ismMetadata.radius, ismMetadata.spread, ismMetadata.gainFactor, ismMetadata.yaw, ismMetadata.pitch ); if ( file ) { @@ -129,8 +128,6 @@ ivas_error IsmFileWriter_writeFrame( return IVAS_ERR_FAILED_FILE_WRITE; } - ++ismWriter->frameCounter; - return IVAS_ERR_OK; } diff --git a/lib_util/ism_file_writer.h b/lib_util/ism_file_writer.h index 1624eddd1aa7888427dc528192ea4c7e126982d6..d9f731e87e56b8f0b333d725d813047320d82a39 100644 --- a/lib_util/ism_file_writer.h +++ b/lib_util/ism_file_writer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,9 +33,7 @@ #ifndef IVAS_ISM_FILE_WRITER_H #define IVAS_ISM_FILE_WRITER_H -#include #include "common_api_types.h" -#include "ivas_error.h" typedef struct IsmFileWriter IsmFileWriter; @@ -45,7 +43,7 @@ typedef struct IsmFileWriter IsmFileWriter; /*! r: error code */ ivas_error IsmFileWriter_open( const char *filePathWav, /* i : path to output file */ - const int16_t obj_num, /* i : ISm number */ + const int16_t obj_num, /* i : number of ISM channels */ IsmFileWriter **ismWriter /* o : IsmFileReader handle */ ); diff --git a/lib_util/ivas_prerenderer.c b/lib_util/ivas_prerenderer.c deleted file mode 100644 index a2c0b4c7104d40f44f9986ff3a944264cd9ff30d..0000000000000000000000000000000000000000 --- a/lib_util/ivas_prerenderer.c +++ /dev/null @@ -1,1733 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#include "options.h" -#include "ivas_prerenderer.h" -#include "ivas_prot.h" -#include "ivas_rom_com.h" -#include "ivas_rom_dec.h" -#include "ivas_rom_prerenderer.h" -#include "prot.h" -#include "wmops.h" - -#include -#include -#include -#include -#include - -#define LIMITER_THRESHOLD 0.9988493699f /* -0.01 dBFS */ - -struct Prndr_Prerenderer -{ - uint32_t sampleRate; - - int8_t isConfigured; /* flag */ - int8_t firstFrame; /* flag */ - - /* I/O */ - Prndr_InputConfig inConfig; - Prndr_OutputConfig outConfig; - - /* =========== Panning =========== */ - EFAP_HANDLE efapRenderer; - - Prndr_ObjPanInfo *objPanInfo; /* size: [numInObjects] */ - - float ***speakerPanGains; /* size: [numInMc][numSpeakers][numOutChannels] */ - - float *tmpGainBuffer; /* size: [numOutChannels] */ - float *noLfePanBuffer; /* size: [numOutChannels] */ - float *crossfade; /* size: [frameSize] */ - /* =============================== */ - - /* Helpers */ - int16_t numOutChannels; /* Total number of output channels */ - int16_t numInChannels; /* Total number of input channels */ - int16_t numInChannelsObj; /* Total number of input channels of object inputs */ - int16_t numInChannelsAmbi; /* Total number of input channels of ambisonics inputs */ - int16_t numInChannelsMc; /* Total number of input channels of multichannel inputs */ - - /* For each channel of MC inputs mcPassThrough contains the corresponding - * output channel index if a passthrough is possible, otherwise contains -1 */ - int32_t *mcPassthrough; /* size: [numInChannelsMc] */ - - /* =========== LFE Handling =========== */ - /* Do not drop LFE when rendering to a layout that does not have - * an LFE channel - render LFE into other channels*/ - int8_t neverDropLfe; /* flag */ - float *lfePanGains; - - /* =========== limiter handle =========== */ - IVAS_LIMITER_HANDLE hLimiter; - - /* Ambisonics decoding matrix */ - float *ambi_dec_mtx; -}; - -/*---------------------------------------------------------------------* - * Prototypes - *---------------------------------------------------------------------*/ -/* clang-off */ -static void renderAmbiToAmbi( - const Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ); - -static void renderChannelsToAmbi( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ); - -static void renderObjectsToAmbi( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const Prndr_AudioObjectMetadataBuffer metadataBuffer, - Prndr_AudioBuffer outAudio ); - -static void renderAmbiToChannels( - const Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ); - -static void renderChannelsToChannels( - const Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ); - -static void renderObjectsToChannels( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const Prndr_AudioObjectMetadataBuffer metadataBuffer, - Prndr_AudioBuffer outAudio ); - -static void renderSingleObjectToAmbi( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const uint32_t itemChnlIdx, /* Index of the item within input audio buffer */ - Prndr_ObjPanInfo *prevPanInfo, - const Prndr_AudioObjectPosition curFrmPos, - const float gain_lin, - Prndr_AudioBuffer outAudio ); - -static void renderSingleObjectToChannels( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const uint32_t itemChnlIdx, /* Index of the item within input audio buffer */ - Prndr_ObjPanInfo *prevPanInfo, - const Prndr_AudioObjectPosition curFrmPos, - const float gain_lin, - Prndr_AudioBuffer outAudio ); - -/* Multiply a single channel by a vector of gains and add result to corresponding output channels */ -static void applyChannelGainsAndAddToOutput( - const Prndr_AudioBuffer inAudio, - const uint32_t itemChnlIdx, /* Index of the item within input audio buffer */ - const float *const gainsCurrent, /* Vector of gains for current frame, corresponding to output channels */ - const float *const gainsPrev, /* Vector of previously applied gains, used for interpolation. Set to NULL for no interpolation */ - const float gain_lin, /* Additional linear gain to be applied when mixing with output buffer */ - const float *const crossfade, - Prndr_AudioBuffer outAudio ); - -static void prepareMcPanGains( - Prndr_Prerenderer *const st ); - -static void prepareLfeHandling( - Prndr_Prerenderer *const st ); - -static void prepareMcPassthrough( - Prndr_Prerenderer *const st ); - -static void passthroughChannel( - const Prndr_AudioBuffer inAudio, - const uint32_t srcChnlIdx, - const uint32_t dstChnlIdx, - const float gain_lin, - Prndr_AudioBuffer outAudio ); - -static void getSpeakerGains( - const Prndr_Prerenderer *const st, - const float azi, - const float ele, - float *const spkGains ); - -static int16_t Prndr_getNumChannelsAmbisonics( - Prndr_Ambisonics ambisonics ); - -static int16_t Prndr_getAmbisonicsOrder( - Prndr_Ambisonics ambisonics ); - -static int16_t Prndr_getNumChannelsInSpeakerLayout( - Prndr_SpeakerLayout layout ); - -static int16_t Prndr_getNumNonLfeChannelsInSpeakerLayout( - Prndr_SpeakerLayout layout ); - -static const float *Prndr_getSpeakerAzimuths( - Prndr_SpeakerLayout layout ); - -static const float *Prndr_getSpeakerElevations( - Prndr_SpeakerLayout layout ); - -static const uint32_t *Prndr_getReorderedChannelIndices( - Prndr_SpeakerLayout layout ); - -static ivas_error Prndr_getHoaRenderMtx( - const Prndr_OutputConfig outConfig, - float **decMtx, - uint32_t ambiOrder ); - -static void Prndr_getHoaDecVecForAmbiChnl( - uint32_t ambiChnnlIdx, - const Prndr_OutputConfig outConfig, - const float *decMtx, - float *decCoeffs ); - -static void ivas_limiter_prerenderer( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - float *output, /* i/o: I/O buffer */ - const int16_t output_frame, /* i : number of samples per channel in the buffer */ - const float threshold /* i : signal amplitude above which limiting starts to be applied */ -); - -static float dBToLin( const float gain_dB ); -/* clang-on */ -/* ========================================================================== */ - -Prndr_Prerenderer *Prndr_Prerenderer_open() -{ - Prndr_Prerenderer *st; - st = (Prndr_Prerenderer *) count_malloc( sizeof( Prndr_Prerenderer ) ); - st->isConfigured = 0; - st->efapRenderer = NULL; - - st->objPanInfo = NULL; - st->speakerPanGains = NULL; - st->tmpGainBuffer = NULL; - st->noLfePanBuffer = NULL; - st->crossfade = NULL; - st->mcPassthrough = NULL; - st->neverDropLfe = 0; - st->lfePanGains = NULL; - st->hLimiter = NULL; - st->ambi_dec_mtx = NULL; - - return st; -} - -ivas_error Prndr_Prerenderer_configure( Prndr_Prerenderer *const st, - const Prndr_InputConfig inConfig, - const Prndr_OutputConfig outConfig, - int32_t frameSize, - uint32_t sampleRate ) -{ - uint32_t i; - int32_t j; - ivas_error error; - - error = IVAS_ERR_OK; - - /* ============================= Error checks ============================= */ - assert( st != NULL && "Can't configure prerenderer - pointer is NULL" ); - assert( !st->isConfigured && "Re-configuring a prerenderer is not supported" ); - assert( !( outConfig.ambisonics != prndr_ambisonics_none && outConfig.speakerLayout != prndr_speaker_layout_none ) && "Multiple outputs not supported" ); - assert( !( outConfig.ambisonics == prndr_ambisonics_none && outConfig.speakerLayout == prndr_speaker_layout_none ) && "At least one output must be selected" ); - assert( !( inConfig.numAudioObjects == 0 && inConfig.numMultiChannelBuses == 0 && inConfig.numAmbisonicsBuses == 0 ) && "At least one input must be active" ); - - /* ========================== Store useful values ========================= */ - st->sampleRate = sampleRate; - st->isConfigured = 1; - st->firstFrame = 1; - st->inConfig = inConfig; - st->outConfig = outConfig; - - /* Save total number of channels in ambisonics inputs */ - st->numInChannelsAmbi = 0; - for ( i = 0; i < inConfig.numAmbisonicsBuses; ++i ) - { - st->numInChannelsAmbi += Prndr_getNumChannelsAmbisonics( inConfig.ambisonicsBuses[i].ambisonicsConfig ); - } - - /* Save total number of channels in MC input */ - st->numInChannelsMc = 0; - for ( i = 0; i < inConfig.numMultiChannelBuses; ++i ) - { - st->numInChannelsMc += Prndr_getNumChannelsInSpeakerLayout( inConfig.multiChannelBuses[i].speakerLayout ); - } - - /* Save total number of channels of audio object inputs */ - st->numInChannelsObj = st->inConfig.numAudioObjects; - - /* Save total number of input channels */ - st->numInChannels = st->numInChannelsObj + st->numInChannelsAmbi + st->numInChannelsMc; - - if ( st->outConfig.ambisonics != prndr_ambisonics_none ) - { - /* Save number of output channels */ - st->numOutChannels = Prndr_getNumChannelsAmbisonics( st->outConfig.ambisonics ); - } - - /* ============================ Prepare panning and ambisonics =========================== */ - if ( st->outConfig.speakerLayout != prndr_speaker_layout_none ) - { - if ( st->outConfig.speakerLayout == prndr_speaker_layout_custom ) - { - /* Save number of output channels */ - st->numOutChannels = st->outConfig.outSetupCustom->num_spk + st->outConfig.outSetupCustom->num_lfe; - - /* Open and initialize EFAP struct */ - if ( ( error = efap_init_data( &st->efapRenderer, st->outConfig.outSetupCustom->ls_azimuth, st->outConfig.outSetupCustom->ls_elevation, st->outConfig.outSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - /* Save number of output channels */ - st->numOutChannels = Prndr_getNumChannelsInSpeakerLayout( st->outConfig.speakerLayout ); - - /* Open and initialize EFAP struct */ - if ( ( error = efap_init_data( &st->efapRenderer, Prndr_getSpeakerAzimuths( st->outConfig.speakerLayout ), Prndr_getSpeakerElevations( st->outConfig.speakerLayout ), Prndr_getNumNonLfeChannelsInSpeakerLayout( st->outConfig.speakerLayout ), EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - - assert( st->efapRenderer != NULL && "Could not init EFAP" ); - - /* Compute Ambisonics to loudspeaker decoding matrix */ - if ( ( error = Prndr_getHoaRenderMtx( st->outConfig, &st->ambi_dec_mtx, 3 ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - /* Allocate temporary pan/enc buffer to avoid allocations during rendering */ - st->tmpGainBuffer = count_calloc( st->numOutChannels, sizeof( float ) ); - - /* Allocate temporary buffer for panning gains with lfe omitted */ - if ( st->outConfig.speakerLayout != prndr_speaker_layout_none ) - { - if ( st->outConfig.speakerLayout == prndr_speaker_layout_custom ) - { - st->noLfePanBuffer = count_calloc( st->outConfig.outSetupCustom->num_spk, sizeof( float ) ); - } - else - { - st->noLfePanBuffer = count_calloc( Prndr_getNumNonLfeChannelsInSpeakerLayout( st->outConfig.speakerLayout ), sizeof( float ) ); - } - } - - /* Create lookup tables for panning/encoding speaker signals */ - if ( st->inConfig.numMultiChannelBuses != 0 ) - { - prepareMcPanGains( st ); - prepareLfeHandling( st ); - } - - /* Allocate structs for interpolation of object pan/enc gains between frames */ - if ( st->inConfig.numAudioObjects != 0 ) - { - st->objPanInfo = count_calloc( st->inConfig.numAudioObjects, sizeof( Prndr_ObjPanInfo ) ); - - for ( i = 0; i < st->inConfig.numAudioObjects; ++i ) - { - st->objPanInfo[i].panGains = count_calloc( st->numOutChannels, sizeof( float ) ); - } - } - - /* =========================== Prepare crossfades ========================= */ - st->crossfade = count_calloc( frameSize, sizeof( float ) ); - - for ( j = 0; j < frameSize; ++j ) - { - st->crossfade[j] = (float) j / ( frameSize - 1 ); - } - - /* ========================= Prepare optimizations ======================== */ - /* Make note of possible processing shortcuts in cases where input and output - * config is the same or similar. This only needs to be done for MC I/O, since - * Ambisonics I/O can always be passed through and objects can never be passed - * through */ - if ( st->inConfig.numMultiChannelBuses > 0 && st->outConfig.speakerLayout != prndr_speaker_layout_none ) - { - prepareMcPassthrough( st ); - } - - /* ============================ Configure limiter =========================== */ - st->hLimiter = ivas_limiter_open( st->numOutChannels, st->sampleRate ); - - return error; -} - -void Prndr_Prerenderer_render( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const Prndr_AudioObjectMetadataBuffer metadataBuffer, - Prndr_AudioBuffer outAudio ) -{ -#ifdef WMOPS - wmops_sub_start( "Prndr_Prerenderer_render" ); -#endif - - /* ============================= Error checks ============================= */ - assert( st != NULL && "Can't render - prerenderer pointer is NULL" ); - assert( st->isConfigured && "Can't render - prerenderer pointer is not configured" ); - assert( inAudio.config.sampleRate == outAudio.config.sampleRate && "Input and output sample rate must be the same" ); - assert( inAudio.config.bufferSize == outAudio.config.bufferSize && "Input and output frame size must be the same" ); - assert( inAudio.config.numChannels == st->numInChannels && "Number of input channels does not match between prerenderer and input config" ); - assert( outAudio.config.numChannels == st->numOutChannels && "Number of input channels does not match between prerenderer and input config" ); - assert( inAudio.config.sampleRate != 0 && "Invalid sample rate" ); - assert( inAudio.config.bufferSize != 0 && "Invalid frame size" ); - assert( inAudio.data != NULL && "Can't render - input buffer is empty" ); - - /* ========================== Actual processing =========================== */ - /* Clear output buffer */ - set_zero( outAudio.data, outAudio.config.numChannels * outAudio.config.bufferSize ); - - /* Render target format: Ambisonics */ - if ( st->outConfig.ambisonics != prndr_ambisonics_none ) - { - if ( st->inConfig.numAmbisonicsBuses != 0 ) - { - renderAmbiToAmbi( st, inAudio, outAudio ); - } - - if ( st->inConfig.numMultiChannelBuses != 0 ) - { - renderChannelsToAmbi( st, inAudio, outAudio ); - } - - if ( st->inConfig.numAudioObjects != 0 ) - { - renderObjectsToAmbi( st, inAudio, metadataBuffer, outAudio ); - } - } /* Render target format: multichannel */ - else if ( st->outConfig.speakerLayout != prndr_speaker_layout_none ) - { - if ( st->inConfig.numAmbisonicsBuses != 0 ) - { - renderAmbiToChannels( st, inAudio, outAudio ); - } - - if ( st->inConfig.numMultiChannelBuses != 0 ) - { - renderChannelsToChannels( st, inAudio, outAudio ); - } - - if ( st->inConfig.numAudioObjects != 0 ) - { - renderObjectsToChannels( st, inAudio, metadataBuffer, outAudio ); - } - } - - /* Apply limiting in place */ - ivas_limiter_prerenderer( - st->hLimiter, - outAudio.data, - outAudio.config.bufferSize, - LIMITER_THRESHOLD ); - - if ( st->firstFrame ) - { - st->firstFrame = 0; - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -void Prndr_Prerenderer_setNeverDropLfe( - Prndr_Prerenderer *st, - int8_t neverDropLfe ) -{ - st->neverDropLfe = neverDropLfe; -} - -int16_t Prndr_Prerenderer_getInChannels( - Prndr_Prerenderer *st ) -{ - assert( st != NULL && "Can't get number of input channels - prerenderer pointer is NULL" ); - if ( st ) - { - return st->numInChannels; - } - return 0; -} - -int16_t Prndr_Prerenderer_getOutChannels( - Prndr_Prerenderer *st ) -{ - assert( st != NULL && "Can't get number of output channels - prerenderer pointer is NULL" ); - if ( st ) - { - return st->numOutChannels; - } - return 0; -} - -void Prndr_Prerenderer_close( Prndr_Prerenderer *st ) -{ - uint32_t i; - uint32_t j; - uint32_t numChannels; - assert( st != NULL && "Can't close prerenderer - pointer is NULL" ); - - if ( st->efapRenderer != NULL ) - { - efap_free_data( &st->efapRenderer ); - } - - if ( st->objPanInfo != NULL ) - { - for ( i = 0; i < st->inConfig.numAudioObjects; ++i ) - { - if ( st->objPanInfo[i].panGains != NULL ) - { - count_free( st->objPanInfo[i].panGains ); - } - } - - count_free( st->objPanInfo ); - } - - if ( st->speakerPanGains != NULL ) - { - for ( i = 0; i < st->inConfig.numMultiChannelBuses; ++i ) - { - numChannels = Prndr_getNumChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[i].speakerLayout ); - - for ( j = 0; j < numChannels; ++j ) - { - count_free( st->speakerPanGains[i][j] ); - } - - count_free( st->speakerPanGains[i] ); - } - - count_free( st->speakerPanGains ); - } - - if ( st->outConfig.speakerLayout == prndr_speaker_layout_custom ) - { - count_free( st->outConfig.outSetupCustom ); - st->outConfig.outSetupCustom = NULL; - } - - if ( st->tmpGainBuffer != NULL ) - { - count_free( st->tmpGainBuffer ); - } - - if ( st->noLfePanBuffer != NULL ) - { - count_free( st->noLfePanBuffer ); - } - - if ( st->crossfade != NULL ) - { - count_free( st->crossfade ); - } - - if ( st->mcPassthrough != NULL ) - { - count_free( st->mcPassthrough ); - } - - if ( st->lfePanGains ) - { - count_free( st->lfePanGains ); - } - - if ( st->ambi_dec_mtx != NULL ) - { - count_free( st->ambi_dec_mtx ); - } - - ivas_limiter_close( &st->hLimiter ); - - count_free( st ); -} - -/* ============================= Local functions ============================ */ -static float *get_smpl_ptr( Prndr_AudioBuffer buffer, uint32_t chnlIdx, uint32_t smplIdx ) -{ - return buffer.data + chnlIdx * buffer.config.bufferSize + smplIdx; -} - -static void renderAmbiToAmbi( const Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ) -{ - float *inSmpl; - float *outSmpl; - int16_t lastChannelIdx; - int16_t smplIdx; - int16_t chnlIdx; - uint32_t inAmbiChannelIdx; - uint32_t ambiIdx; - float gain_lin; - - -#ifdef WMOPS - wmops_sub_start( "renderAmbiToAmbi" ); -#endif - - /* Iterate over given Ambisonics inputs */ - for ( ambiIdx = 0; ambiIdx < st->inConfig.numAmbisonicsBuses; ++ambiIdx ) - { - inAmbiChannelIdx = st->inConfig.ambisonicsBuses[ambiIdx].inputChannelIndex; - - /* Find out how many channels to process */ - lastChannelIdx = min( Prndr_getNumChannelsAmbisonics( st->inConfig.ambisonicsBuses[ambiIdx].ambisonicsConfig ), st->numOutChannels ) - 1; - - gain_lin = dBToLin( st->inConfig.ambisonicsBuses[ambiIdx].gain_dB ); - - /* Passthrough channels */ - for ( chnlIdx = 0; chnlIdx <= lastChannelIdx; ++chnlIdx ) - { - inSmpl = get_smpl_ptr( inAudio, chnlIdx + inAmbiChannelIdx, 0 ); - outSmpl = get_smpl_ptr( outAudio, chnlIdx, 0 ); - - for ( smplIdx = 0; smplIdx < inAudio.config.bufferSize; ++smplIdx ) - { - *outSmpl += *inSmpl * gain_lin; - - ++inSmpl; - ++outSmpl; - } - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void renderChannelsToAmbi( Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ) -{ - const uint32_t *lfeLastIdxs; - uint32_t inMcChannelIdx; - uint32_t numNonLfeInChannels; - uint32_t numInChannels; - uint32_t mcIdx; - uint32_t inChIdx; - float gain_lin; - -#ifdef WMOPS - wmops_sub_start( "renderChannelsToAmbi" ); -#endif - - /* Iterate over given MC inputs */ - for ( mcIdx = 0; mcIdx < st->inConfig.numMultiChannelBuses; ++mcIdx ) - { - /* Get channel idx of current MC input within the multitrack buffer */ - inMcChannelIdx = st->inConfig.multiChannelBuses[mcIdx].inputChannelIndex; - - /* Number of input speakers */ - numInChannels = Prndr_getNumChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - numNonLfeInChannels = Prndr_getNumNonLfeChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - lfeLastIdxs = Prndr_getReorderedChannelIndices( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - gain_lin = dBToLin( st->inConfig.multiChannelBuses[mcIdx].gain_dB ); - - /* Iterate over channels */ - for ( inChIdx = 0; inChIdx < numNonLfeInChannels; ++inChIdx ) - { - applyChannelGainsAndAddToOutput( inAudio, - inMcChannelIdx + lfeLastIdxs[inChIdx], - st->speakerPanGains[mcIdx][inChIdx], - NULL, - gain_lin, - st->crossfade, - outAudio ); - } - - if ( st->neverDropLfe ) - { - /* Render LFE channels into the scene */ - for ( ; inChIdx < numInChannels; ++inChIdx ) - { - applyChannelGainsAndAddToOutput( inAudio, - inMcChannelIdx + lfeLastIdxs[inChIdx], - st->lfePanGains, - NULL, - gain_lin, - st->crossfade, - outAudio ); - } - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void renderObjectsToAmbi( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const Prndr_AudioObjectMetadataBuffer metadataBuffer, - Prndr_AudioBuffer outAudio ) -{ - const Prndr_AudioObject *curObj; - uint32_t objIdx; - Prndr_AudioObjectPosition pos; - float gain_lin; - -#ifdef WMOPS - wmops_sub_start( "renderObjectsToAmbi" ); -#endif - - assert( st->inConfig.numAudioObjects == metadataBuffer.numObjects && "Metadata provided for a different number of objects than found in input" ); - - /* Iterate over given audio objects */ - for ( objIdx = 0; objIdx < st->inConfig.numAudioObjects; ++objIdx ) - { - /* Get pointer to current object and its metadata */ - curObj = &st->inConfig.audioObjects[objIdx]; - pos = metadataBuffer.positions[objIdx]; - gain_lin = dBToLin( st->inConfig.audioObjects[objIdx].gain_dB ); - - /* Render to ambisonics */ - renderSingleObjectToAmbi( - st, - inAudio, - curObj->inputChannelIndex, - &st->objPanInfo[objIdx], - pos, - gain_lin, - outAudio ); - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void renderAmbiToChannels( const Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ) -{ - uint32_t inAmbiChannelIdx; - uint32_t ambiIdx; - uint32_t numInAmbiChnls; - uint32_t ambiChnIdx; - float gain_lin; - -#ifdef WMOPS - wmops_sub_start( "renderAmbiToChannels" ); -#endif - - /* Iterate over all given ambisonics inputs */ - for ( ambiIdx = 0; ambiIdx < st->inConfig.numAmbisonicsBuses; ++ambiIdx ) - { - inAmbiChannelIdx = st->inConfig.ambisonicsBuses[ambiIdx].inputChannelIndex; - - /* Number of input channels */ - numInAmbiChnls = Prndr_getNumChannelsAmbisonics( st->inConfig.ambisonicsBuses[ambiIdx].ambisonicsConfig ); - - gain_lin = dBToLin( st->inConfig.multiChannelBuses[ambiIdx].gain_dB ); - - /* Render each ambisonics channel */ - for ( ambiChnIdx = 0; ambiChnIdx < numInAmbiChnls; ++ambiChnIdx ) - { - /* Write decoding gains to temp buffer */ - Prndr_getHoaDecVecForAmbiChnl( ambiChnIdx, st->outConfig, st->ambi_dec_mtx, st->tmpGainBuffer ); - - /* Apply decoding gains and add to output */ - applyChannelGainsAndAddToOutput( inAudio, - inAmbiChannelIdx + ambiChnIdx, - st->tmpGainBuffer, - NULL, - gain_lin, - st->crossfade, - outAudio ); - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void renderChannelsToChannels( - const Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - Prndr_AudioBuffer outAudio ) -{ - const uint32_t *lfeLastIdxs; - uint32_t inMcChannelIdx; - uint32_t numNonLfeInChannels; - uint32_t numInChannels; - uint32_t passThroughIdx; - uint32_t mcIdx; - uint32_t inChIdx; - float gain_lin; - -#ifdef WMOPS - wmops_sub_start( "renderChannelsToChannels" ); -#endif - - passThroughIdx = 0; - - /* Iterate over given MC inputs */ - for ( mcIdx = 0; mcIdx < st->inConfig.numMultiChannelBuses; ++mcIdx ) - { - /* Get channel idx of current MC input within the multitrack buffer */ - inMcChannelIdx = st->inConfig.multiChannelBuses[mcIdx].inputChannelIndex; - - /* Number of non-LFE input channels */ - numNonLfeInChannels = Prndr_getNumNonLfeChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - /* Number of all input channels */ - numInChannels = Prndr_getNumChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - lfeLastIdxs = Prndr_getReorderedChannelIndices( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - gain_lin = dBToLin( st->inConfig.multiChannelBuses[mcIdx].gain_dB ); - - /* Iterate over non-LFE channels */ - for ( inChIdx = 0; inChIdx < numNonLfeInChannels; ++inChIdx ) - { - if ( st->mcPassthrough[passThroughIdx] == -1 ) - { - applyChannelGainsAndAddToOutput( inAudio, - inMcChannelIdx + lfeLastIdxs[inChIdx], - st->speakerPanGains[mcIdx][inChIdx], - NULL, - gain_lin, - st->crossfade, - outAudio ); - } - else - { - passthroughChannel( inAudio, - inMcChannelIdx + lfeLastIdxs[inChIdx], - st->mcPassthrough[passThroughIdx], - gain_lin, - outAudio ); - } - - ++passThroughIdx; - } - - /* Iterate over LFE channels */ - for ( ; inChIdx < numInChannels; ++inChIdx ) - { - /* Pass through if possible */ - if ( st->mcPassthrough[passThroughIdx] != -1 ) - { - passthroughChannel( inAudio, - inMcChannelIdx + lfeLastIdxs[inChIdx], - st->mcPassthrough[passThroughIdx], - gain_lin, - outAudio ); - } - else - { - if ( st->neverDropLfe ) - { - applyChannelGainsAndAddToOutput( inAudio, - inMcChannelIdx + lfeLastIdxs[inChIdx], - st->lfePanGains, - NULL, - gain_lin, - st->crossfade, - outAudio ); - } - } - - ++passThroughIdx; - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void renderObjectsToChannels( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const Prndr_AudioObjectMetadataBuffer metadataBuffer, - Prndr_AudioBuffer outAudio ) -{ - const Prndr_AudioObject *curObj; - uint32_t objIdx; - Prndr_AudioObjectPosition pos; - float gain_lin; - -#ifdef WMOPS - wmops_sub_start( "renderObjectsToChannels" ); -#endif - - assert( st->inConfig.numAudioObjects == metadataBuffer.numObjects && "Metadata provided for a different number of objects than found in input" ); - - /* Iterate over given audio objects */ - for ( objIdx = 0; objIdx < st->inConfig.numAudioObjects; ++objIdx ) - { - /* Get pointer to current object and its metadata */ - curObj = &st->inConfig.audioObjects[objIdx]; - pos = metadataBuffer.positions[objIdx]; - gain_lin = dBToLin( st->inConfig.audioObjects[objIdx].gain_dB ); - - /* Render to MC */ - renderSingleObjectToChannels( - st, - inAudio, - curObj->inputChannelIndex, - &st->objPanInfo[objIdx], - pos, - gain_lin, - outAudio ); - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void renderSingleObjectToAmbi( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const uint32_t itemChnlIdx, - Prndr_ObjPanInfo *prevPanInfo, - const Prndr_AudioObjectPosition curFrmPos, - const float gain_lin, - Prndr_AudioBuffer outAudio ) -{ - float *swapPtr; - -#ifdef WMOPS - wmops_sub_start( "renderSingleObjectToAmbi" ); -#endif - - /* Update panning gains if position changed */ - if ( prevPanInfo->position.azimuth != curFrmPos.azimuth || - prevPanInfo->position.elevation != curFrmPos.elevation || - st->firstFrame ) - { - /* Write current panning gains to tmpBuffer */ - ivas_dirac_dec_get_response( curFrmPos.azimuth, - curFrmPos.elevation, - st->tmpGainBuffer, - Prndr_getAmbisonicsOrder( st->outConfig.ambisonics ) ); - - prevPanInfo->position.azimuth = curFrmPos.azimuth; - prevPanInfo->position.elevation = curFrmPos.elevation; - - applyChannelGainsAndAddToOutput( inAudio, - itemChnlIdx, - st->tmpGainBuffer, - st->firstFrame ? NULL : prevPanInfo->panGains, - gain_lin, - st->crossfade, - outAudio ); - - /* Save current gains as most recently applied gains */ - swapPtr = prevPanInfo->panGains; - prevPanInfo->panGains = st->tmpGainBuffer; - st->tmpGainBuffer = swapPtr; - } - /* Otherwise use most recent gains and no interpolation */ - else - { - applyChannelGainsAndAddToOutput( inAudio, - itemChnlIdx, - prevPanInfo->panGains, - NULL, - gain_lin, - st->crossfade, - outAudio ); - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void renderSingleObjectToChannels( - Prndr_Prerenderer *const st, - const Prndr_AudioBuffer inAudio, - const uint32_t itemChnlIdx, - Prndr_ObjPanInfo *prevPanInfo, - const Prndr_AudioObjectPosition curFrmPos, - const float gain_lin, - Prndr_AudioBuffer outAudio ) -{ - float *swapPtr; - -#ifdef WMOPS - wmops_sub_start( "renderSingleObjectToChannels" ); -#endif - - /* Update panning gains if position changed */ - if ( prevPanInfo->position.azimuth != curFrmPos.azimuth || - prevPanInfo->position.elevation != curFrmPos.elevation || - st->firstFrame ) - { - /* Write current panning gains to tmpBuffer */ - getSpeakerGains( st, curFrmPos.azimuth, curFrmPos.elevation, st->tmpGainBuffer ); - prevPanInfo->position.azimuth = curFrmPos.azimuth; - prevPanInfo->position.elevation = curFrmPos.elevation; - - applyChannelGainsAndAddToOutput( inAudio, - itemChnlIdx, - st->tmpGainBuffer, - st->firstFrame ? NULL : prevPanInfo->panGains, - gain_lin, - st->crossfade, - outAudio ); - - /* Save current gains as most recently applied gains */ - swapPtr = prevPanInfo->panGains; - prevPanInfo->panGains = st->tmpGainBuffer; - st->tmpGainBuffer = swapPtr; - } - /* Otherwise use most recent gains and no interpolation */ - else - { - applyChannelGainsAndAddToOutput( inAudio, - itemChnlIdx, - prevPanInfo->panGains, - NULL, - gain_lin, - st->crossfade, - outAudio ); - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void applyChannelGainsAndAddToOutput( - const Prndr_AudioBuffer inAudio, - const uint32_t itemChnlIdx, - const float *const gainsCurrent, - const float *const gainsPrev, - const float gain_lin, - const float *const crossfade, - Prndr_AudioBuffer outAudio ) -{ - float *inSmpl; - float *outSmpl; - const float *fadeIn; - const float *fadeOut; - const float *lastInSmpl; - int16_t outChnlIdx; - float currentGain; - float previousGain; - -#ifdef WMOPS - wmops_sub_start( "applyChannelGainsAndAddToOutput" ); -#endif - - - /* Pointer to behind last input sample */ - lastInSmpl = get_smpl_ptr( inAudio, itemChnlIdx, inAudio.config.bufferSize ); - - for ( outChnlIdx = 0; outChnlIdx < outAudio.config.numChannels; ++outChnlIdx ) - { -#ifdef WMOPS - wmops_sub_start( "applyChannelGainsAndAddToOutput_chnl_loop" ); -#endif - currentGain = gainsCurrent[outChnlIdx] * gain_lin; - previousGain = gainsPrev == NULL ? 0.f : gainsPrev[outChnlIdx] * gain_lin; - - /* Process current output channel only if applying non-zero gains */ - if ( fabsf( currentGain ) > EPSILON || ( gainsPrev != NULL && fabsf( previousGain ) > EPSILON ) ) - { - /* Reset crossfade pointers */ - fadeIn = crossfade; - fadeOut = &crossfade[inAudio.config.bufferSize - 1]; - - /* Reset input pointer to the beginning of input channel */ - inSmpl = get_smpl_ptr( inAudio, itemChnlIdx, 0 ); - - /* Set output pointer to first output channel sample */ - outSmpl = get_smpl_ptr( outAudio, outChnlIdx, 0 ); - - if ( gainsPrev == NULL || fabsf( previousGain - currentGain ) <= EPSILON ) - { -#ifdef WMOPS - wmops_sub_start( "applyChannelGainsAndAddToOutput_smpl_loop_no_intrpl" ); -#endif - /* If no interpolation from previous frame, apply current gain */ - do - { - *outSmpl += currentGain * ( *inSmpl ); - ++outSmpl; - ++inSmpl; - - } while ( inSmpl != lastInSmpl ); -#ifdef WMOPS - wmops_sub_end(); -#endif - } - else - { -#ifdef WMOPS - wmops_sub_start( "applyChannelGainsAndAddToOutput_smpl_loop_intrpl" ); -#endif - /* Otherwise use weighted average between previous and current gain */ - do - { - *outSmpl += ( ( *fadeIn ) * currentGain + ( *fadeOut ) * previousGain ) * ( *inSmpl ); - ++outSmpl; - ++inSmpl; - - ++fadeIn; - --fadeOut; - } while ( inSmpl != lastInSmpl ); -#ifdef WMOPS - wmops_sub_end(); -#endif - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void prepareLfeHandling( - Prndr_Prerenderer *const st ) -{ - /* uint32_t i; */ - -#ifdef WMOPS - wmops_sub_start( "prepareLfeHandling" ); -#endif - - st->lfePanGains = count_calloc( st->numOutChannels, sizeof( float ) ); - - if ( st->outConfig.ambisonics != prndr_ambisonics_none ) - { - /* Pan LFE to south pole (experimental) */ - ivas_dirac_dec_get_response( 0, - -90, - st->lfePanGains, - Prndr_getAmbisonicsOrder( st->outConfig.ambisonics ) ); - - /* TODO(sgi): Apply 10 dB gain? Almost surely will clip */ - /* for (i=0; i< st->numOutChannels; ++i) { - st->lfePanGains[i] *= 3.1622776602f; - } */ - } - else - { - set_zero( st->lfePanGains, st->numOutChannels ); - - /* Pan LFE to L and R with 4dB gain each (== 10dB - 6dB) */ - if ( st->numOutChannels > 1 ) - { - st->lfePanGains[0] = 1.5848931925f; - st->lfePanGains[1] = 1.5848931925f; - } - else - { - /* Put LFE in center channel, do not add 10dB gain to avoid clipping */ - st->lfePanGains[1] = 1.f; - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void prepareMcPanGains( Prndr_Prerenderer *const st ) -{ - uint32_t mcIdx; - int32_t spkIdx; - int32_t numChannels; - const float *spkAzi; - const float *spkEle; - -#ifdef WMOPS - wmops_sub_start( "prepareMcPanGains" ); -#endif - - st->speakerPanGains = count_calloc( st->inConfig.numMultiChannelBuses, sizeof( float ** ) ); - - for ( mcIdx = 0; mcIdx < st->inConfig.numMultiChannelBuses; ++mcIdx ) - { - numChannels = Prndr_getNumChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - st->speakerPanGains[mcIdx] = count_calloc( numChannels, sizeof( float * ) ); - - spkAzi = Prndr_getSpeakerAzimuths( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - spkEle = Prndr_getSpeakerElevations( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - if ( st->outConfig.ambisonics != prndr_ambisonics_none ) - { - for ( spkIdx = 0; spkIdx < numChannels; ++spkIdx ) - { - st->speakerPanGains[mcIdx][spkIdx] = count_calloc( st->numOutChannels, sizeof( float ) ); - ivas_dirac_dec_get_response( (int16_t) spkAzi[spkIdx], - (int16_t) spkEle[spkIdx], - st->speakerPanGains[mcIdx][spkIdx], - Prndr_getAmbisonicsOrder( st->outConfig.ambisonics ) ); - } - } - else if ( st->outConfig.speakerLayout != prndr_speaker_layout_none ) - { - for ( spkIdx = 0; spkIdx < numChannels; ++spkIdx ) - { - st->speakerPanGains[mcIdx][spkIdx] = count_calloc( st->numOutChannels, sizeof( float ) ); - getSpeakerGains( st, spkAzi[spkIdx], spkEle[spkIdx], st->speakerPanGains[mcIdx][spkIdx] ); - } - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void prepareMcPassthrough( Prndr_Prerenderer *const st ) -{ - /* Output config */ - const float *outSpkAzi; - const float *outSpkEle; - const uint32_t *lfeLastIdxs; - uint32_t numNonLfeOutChannels; - uint32_t numOutChannels; - uint32_t lfeLastIdx_lsCustom[MAX_OUTPUT_CHANNELS]; - - /* Input config */ - const float *inSpkAzi; - const float *inSpkEle; - uint32_t numInChannels; - uint32_t numNonLfeInChannels; - - /* Input channel index */ - uint32_t passThroughIdx; - - uint32_t mcIdx; - uint32_t inChIdx; - uint32_t outChIdx; - -#ifdef WMOPS - wmops_sub_start( "prepareMcPassthrough" ); -#endif - - st->mcPassthrough = count_calloc( st->numInChannelsMc, sizeof( int32_t ) ); - - - if ( st->outConfig.speakerLayout == prndr_speaker_layout_custom ) - { - /* Number of non-LFE output channels */ - numNonLfeOutChannels = st->outConfig.outSetupCustom->num_spk; - - /* Number of output channels */ - numOutChannels = st->outConfig.outSetupCustom->num_spk + st->outConfig.outSetupCustom->num_lfe; - - /* Output speaker coordinates */ - outSpkAzi = st->outConfig.outSetupCustom->ls_azimuth; - outSpkEle = st->outConfig.outSetupCustom->ls_elevation; - - /* num_spk + num_lfe must be <= MAX_OUTPUT_CHANNELS for custom loudspeaker layouts */ - if ( st->outConfig.outSetupCustom->num_lfe > 0 ) - { - lfeLastIdx_lsCustom[numNonLfeOutChannels] = st->outConfig.outSetupCustom->lfe_idx[0]; - } - - for ( outChIdx = 0; outChIdx < numNonLfeOutChannels; ++outChIdx ) - { - ( ( st->outConfig.outSetupCustom->num_lfe > 0 ) && ( (int16_t) outChIdx >= st->outConfig.outSetupCustom->lfe_idx[0] ) ) ? ( lfeLastIdx_lsCustom[outChIdx] = outChIdx + 1 ) : ( lfeLastIdx_lsCustom[outChIdx] = outChIdx ); - } - - lfeLastIdxs = &lfeLastIdx_lsCustom[0]; - } - else - { - /* Number of non-LFE output channels */ - numNonLfeOutChannels = Prndr_getNumNonLfeChannelsInSpeakerLayout( st->outConfig.speakerLayout ); - - /* Number of output channels */ - numOutChannels = Prndr_getNumChannelsInSpeakerLayout( st->outConfig.speakerLayout ); - - /* Output speaker coordinates */ - outSpkAzi = Prndr_getSpeakerAzimuths( st->outConfig.speakerLayout ); - outSpkEle = Prndr_getSpeakerElevations( st->outConfig.speakerLayout ); - - lfeLastIdxs = Prndr_getReorderedChannelIndices( st->outConfig.speakerLayout ); - } - - passThroughIdx = 0; - for ( mcIdx = 0; mcIdx < st->inConfig.numMultiChannelBuses; ++mcIdx ) - { - /* Number of non-LFE input channels for current MC input */ - numNonLfeInChannels = Prndr_getNumNonLfeChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - /* Number of input channels for current MC input */ - numInChannels = Prndr_getNumChannelsInSpeakerLayout( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - /* Input speaker coordinates */ - inSpkAzi = Prndr_getSpeakerAzimuths( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - inSpkEle = Prndr_getSpeakerElevations( st->inConfig.multiChannelBuses[mcIdx].speakerLayout ); - - /* Check if passthrough possible for, save I/O mapping */ - for ( inChIdx = 0; inChIdx < numNonLfeInChannels; ++inChIdx ) - { - st->mcPassthrough[passThroughIdx] = -1; - - for ( outChIdx = 0; outChIdx < numNonLfeOutChannels; ++outChIdx ) - { - if ( inSpkAzi[inChIdx] == outSpkAzi[outChIdx] && - inSpkEle[inChIdx] == outSpkEle[outChIdx] ) - { - st->mcPassthrough[passThroughIdx] = lfeLastIdxs[outChIdx]; - break; - } - } - - ++passThroughIdx; - } - - /* Setup LFE passthrough, save I/O mapping */ - outChIdx = numNonLfeOutChannels; - for ( ; inChIdx < numInChannels; ++inChIdx ) - { - if ( outChIdx < numOutChannels ) - { - st->mcPassthrough[passThroughIdx] = lfeLastIdxs[outChIdx]; - } - else - { - st->mcPassthrough[passThroughIdx] = -1; - } - - ++outChIdx; - ++passThroughIdx; - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void passthroughChannel( const Prndr_AudioBuffer inAudio, - const uint32_t srcChnlIdx, - const uint32_t dstChnlIdx, - const float gain_lin, - Prndr_AudioBuffer outAudio ) -{ - float *inSmpl; - float *outSmpl; - int16_t smplIdx; - -#ifdef WMOPS - wmops_sub_start( "passthroughChannel" ); -#endif - - inSmpl = get_smpl_ptr( inAudio, srcChnlIdx, 0 ); - outSmpl = get_smpl_ptr( outAudio, dstChnlIdx, 0 ); - - for ( smplIdx = 0; smplIdx < inAudio.config.bufferSize; ++smplIdx ) - { - *outSmpl += *inSmpl * gain_lin; - - ++outSmpl; - ++inSmpl; - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -static void getSpeakerGains( const Prndr_Prerenderer *const st, - const float azi, - const float ele, - float *const spkGains ) -{ - const uint32_t *lfeLastIdxs; - int16_t numNonLfeOutChannels; - int16_t noLfeIdx; - Prndr_SpeakerLayout speakerLayout; - -#ifdef WMOPS - wmops_sub_start( "getSpeakerGains" ); -#endif - - /* EFAP returns an array of gains only for non-LFE speakers */ - efap_determine_gains( st->efapRenderer, st->noLfePanBuffer, azi, ele, EFAP_MODE_EFAP ); - - speakerLayout = st->outConfig.speakerLayout; - if ( speakerLayout == prndr_speaker_layout_custom ) - { - uint32_t lfeIdx; - - numNonLfeOutChannels = st->outConfig.outSetupCustom->num_spk; - - /* Clear speaker gains - not all elements will be overwritten below */ - set_zero( spkGains, numNonLfeOutChannels + st->outConfig.outSetupCustom->num_lfe ); - - /* Copy to gain array where LFE channel(s) are included */ - for ( lfeIdx = 0, noLfeIdx = 0; noLfeIdx < numNonLfeOutChannels; lfeIdx++, noLfeIdx++ ) - { - if ( noLfeIdx == st->outConfig.outSetupCustom->lfe_idx[0] ) - { - lfeIdx++; - } - spkGains[lfeIdx] = st->noLfePanBuffer[noLfeIdx]; - } - } - else - { - numNonLfeOutChannels = Prndr_getNumNonLfeChannelsInSpeakerLayout( speakerLayout ); - lfeLastIdxs = Prndr_getReorderedChannelIndices( speakerLayout ); - - /* Clear speaker gains - not all elements will be overwritten below */ - set_zero( spkGains, Prndr_getNumChannelsInSpeakerLayout( speakerLayout ) ); - - /* Copy to gain array where LFE channel(s) are included */ - for ( noLfeIdx = 0; noLfeIdx < numNonLfeOutChannels; ++noLfeIdx ) - { - spkGains[lfeLastIdxs[noLfeIdx]] = st->noLfePanBuffer[noLfeIdx]; - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -int16_t Prndr_getNumChannelsAmbisonics( Prndr_Ambisonics ambisonics ) -{ - switch ( ambisonics ) - { - case prndr_ambisonics_none: - return 0; - case prndr_ambisonics_mono: - return 1; - case prndr_ambisonics_foa: - return 4; - case prndr_ambisonics_soa: - return 9; - case prndr_ambisonics_toa: - return 16; - default: - assert( !"Invalid ambisonics config" ); - } - - return 0; -} - -static int16_t Prndr_getAmbisonicsOrder( Prndr_Ambisonics ambisonics ) -{ - assert( ambisonics != prndr_ambisonics_none && "Invalid ambisonics config" ); - return ambisonics; /* Enum values map to ambisonics order */ -} - -int16_t Prndr_getNumChannelsInSpeakerLayout( Prndr_SpeakerLayout layout ) -{ - switch ( layout ) - { - case prndr_speaker_layout_none: - return 0; - case prndr_speaker_layout_mono: - return 1; - case prndr_speaker_layout_stereo: - return 2; - case prndr_speaker_layout_5_1: - return 6; - case prndr_speaker_layout_7_1: - return 8; - case prndr_speaker_layout_5_1_4: - return 10; - case prndr_speaker_layout_7_1_4: - return 12; - default: - assert( !"Invalid speaker layout" ); - } - - return 0; -} - -int16_t Prndr_getNumNonLfeChannelsInSpeakerLayout( Prndr_SpeakerLayout layout ) -{ - switch ( layout ) - { - case prndr_speaker_layout_mono: - return 1; - case prndr_speaker_layout_stereo: - return 2; - case prndr_speaker_layout_5_1: - return 5; - case prndr_speaker_layout_7_1: - return 7; - case prndr_speaker_layout_5_1_4: - return 9; - case prndr_speaker_layout_7_1_4: - return 11; - default: - assert( !"Invalid speaker layout" ); - } - - return 0; -} - -const float *Prndr_getSpeakerAzimuths( Prndr_SpeakerLayout layout ) -{ - switch ( layout ) - { - case prndr_speaker_layout_mono: - return ls_azimuth_CICP1; - case prndr_speaker_layout_stereo: - return ls_azimuth_CICP2; - case prndr_speaker_layout_5_1: - return ls_azimuth_CICP6; - case prndr_speaker_layout_7_1: - return ls_azimuth_CICP12; - case prndr_speaker_layout_5_1_4: - return ls_azimuth_CICP16; - case prndr_speaker_layout_7_1_4: - return ls_azimuth_CICP19; - default: - assert( !"Invalid speaker layout" ); - } - - return NULL; -} - -const float *Prndr_getSpeakerElevations( Prndr_SpeakerLayout layout ) -{ - switch ( layout ) - { - case prndr_speaker_layout_mono: - return ls_elevation_CICP1; - case prndr_speaker_layout_stereo: - return ls_elevation_CICP2; - case prndr_speaker_layout_5_1: - return ls_elevation_CICP6; - case prndr_speaker_layout_7_1: - return ls_elevation_CICP12; - case prndr_speaker_layout_5_1_4: - return ls_elevation_CICP16; - case prndr_speaker_layout_7_1_4: - return ls_elevation_CICP19; - default: - assert( !"Invalid speaker layout" ); - } - - return NULL; -} - -const uint32_t *Prndr_getReorderedChannelIndices( Prndr_SpeakerLayout layout ) -{ - switch ( layout ) - { - case prndr_speaker_layout_mono: - return ls_LFE_last_idx_CICP1; - case prndr_speaker_layout_stereo: - return ls_LFE_last_idx_CICP2; - case prndr_speaker_layout_5_1: - return ls_LFE_last_idx_CICP6; - case prndr_speaker_layout_7_1: - return ls_LFE_last_idx_CICP12; - case prndr_speaker_layout_5_1_4: - return ls_LFE_last_idx_CICP16; - case prndr_speaker_layout_7_1_4: - return ls_LFE_last_idx_CICP19; - default: - assert( !"Invalid speaker layout" ); - } - - return NULL; -} - -static ivas_error Prndr_getHoaRenderMtx( - const Prndr_OutputConfig outConfig, - float **decMtx, - uint32_t ambiOrder ) -{ - IVAS_OUTPUT_SETUP hOutSetup; - ivas_error error; - - error = IVAS_ERR_OK; - -#ifdef WMOPS - wmops_sub_start( "Prndr_getHoaRenderMtx" ); -#endif - - switch ( outConfig.speakerLayout ) - { - case prndr_speaker_layout_mono: - ivas_output_init( &hOutSetup, AUDIO_CONFIG_MONO ); - hOutSetup.ls_azimuth = ls_azimuth_CICP1; - hOutSetup.ls_elevation = ls_elevation_CICP1; - break; - case prndr_speaker_layout_stereo: - ivas_output_init( &hOutSetup, AUDIO_CONFIG_STEREO ); - break; - case prndr_speaker_layout_5_1: - ivas_output_init( &hOutSetup, AUDIO_CONFIG_5_1 ); - break; - case prndr_speaker_layout_7_1: - ivas_output_init( &hOutSetup, AUDIO_CONFIG_7_1 ); - break; - case prndr_speaker_layout_5_1_4: - ivas_output_init( &hOutSetup, AUDIO_CONFIG_5_1_4 ); - break; - case prndr_speaker_layout_7_1_4: - ivas_output_init( &hOutSetup, AUDIO_CONFIG_7_1_4 ); - break; - case prndr_speaker_layout_custom: - ivas_ls_custom_setup( &hOutSetup, outConfig.outSetupCustom ); - break; - default: - assert( !"Invalid speaker config" ); - return IVAS_ERR_WRONG_PARAMS; - } - - if ( ( error = ivas_sba_get_hoa_dec_matrix( hOutSetup, decMtx, (int16_t) ambiOrder ) ) != IVAS_ERR_OK ) - { - return error; - } - - -#ifdef WMOPS - wmops_sub_end(); -#endif - - return error; -} - -void Prndr_getHoaDecVecForAmbiChnl( - uint32_t ambiChnnlIdx, - const Prndr_OutputConfig outConfig, - const float *decMtx, - float *decCoeffs ) -{ - - const uint32_t *lfeLastIdxs; - int16_t numNonLfeChannels; - int16_t nonLfeChIdx; - -#ifdef WMOPS - wmops_sub_start( "Prndr_getHoaDecVecForAmbiChnl" ); -#endif - - - if ( outConfig.speakerLayout == prndr_speaker_layout_custom ) - { - uint32_t lfeIdx; - - numNonLfeChannels = outConfig.outSetupCustom->num_spk; - - /* Clear speaker gains - not all elements will be overwritten below */ - set_zero( decCoeffs, numNonLfeChannels + outConfig.outSetupCustom->num_lfe ); - - /* Copy to gain array where LFE channel(s) are included */ - for ( lfeIdx = 0, nonLfeChIdx = 0; nonLfeChIdx < numNonLfeChannels; lfeIdx++, nonLfeChIdx++ ) - { - if ( nonLfeChIdx == outConfig.outSetupCustom->lfe_idx[0] ) - { - lfeIdx++; - } - decCoeffs[lfeIdx] = decMtx[16 * nonLfeChIdx + ambiChnnlIdx]; - } - } - else - { - numNonLfeChannels = Prndr_getNumNonLfeChannelsInSpeakerLayout( outConfig.speakerLayout ); - - lfeLastIdxs = Prndr_getReorderedChannelIndices( outConfig.speakerLayout ); - - /* Clear decoding coefficients - not all elements will be overwritten below */ - set_zero( decCoeffs, Prndr_getNumChannelsInSpeakerLayout( outConfig.speakerLayout ) ); - - for ( nonLfeChIdx = 0; nonLfeChIdx < numNonLfeChannels; ++nonLfeChIdx ) - { - decCoeffs[lfeLastIdxs[nonLfeChIdx]] = decMtx[16 * nonLfeChIdx + ambiChnnlIdx]; - } - } - -#ifdef WMOPS - wmops_sub_end(); -#endif -} - -/*-------------------------------------------------------------------* - * ivas_limiter_prerenderer() - * - * In-place saturation control for multichannel buffers with adaptive release time - *-------------------------------------------------------------------*/ -static void ivas_limiter_prerenderer( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - float *output, /* i/o: I/O buffer */ - const int16_t output_frame, /* i : number of samples per channel in the buffer */ - const float threshold /* i : signal amplitude above which limiting starts to be applied */ -) -{ - int16_t c; - float **channels; - int16_t num_channels; - - /* return early if given bad parameters */ - if ( hLimiter == NULL || output == NULL || output_frame <= 0 ) - { - return; - } - - channels = hLimiter->channel_ptrs; - num_channels = hLimiter->num_channels; - - for ( c = 0; c < num_channels; ++c ) - { - channels[c] = output + c * output_frame; - } - - limiter_process( hLimiter, output_frame, threshold, 0, NULL ); - - return; -} - -static float dBToLin( const float gain_dB ) -{ - return powf( 10.f, gain_dB / 20.f ); -} diff --git a/lib_util/ivas_prerenderer.h b/lib_util/ivas_prerenderer.h deleted file mode 100644 index f21f893dc98e7b9e93eb103971f77e44b3c7161a..0000000000000000000000000000000000000000 --- a/lib_util/ivas_prerenderer.h +++ /dev/null @@ -1,190 +0,0 @@ -/****************************************************************************************************** - - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. - -*******************************************************************************************************/ - -#ifndef IVAS_PRERENDERER_H -#define IVAS_PRERENDERER_H - -#include -#include - -#include "options.h" -#include "common_api_types.h" -#include "ls_custom_file_reader.h" -#include "ivas_error.h" - -#define PRERENDERER_MAX_ISM_INPUTS 16 -#define PRERENDERER_MAX_MC_INPUTS 2 -#define PRERENDERER_MAX_SBA_INPUTS 2 - -typedef enum Prndr_Ambisonics -{ - prndr_ambisonics_none = -1, - prndr_ambisonics_mono = 0, - prndr_ambisonics_foa = 1, - prndr_ambisonics_soa = 2, - prndr_ambisonics_toa = 3 -} Prndr_Ambisonics; /* Numerical value corresponds to Ambisonics order */ - -typedef enum Prndr_SpeakerLayout -{ - prndr_speaker_layout_none = -1, - prndr_speaker_layout_custom = 0, - prndr_speaker_layout_mono = 1, - prndr_speaker_layout_stereo = 2, - prndr_speaker_layout_5_1 = 6, - prndr_speaker_layout_5_1_4 = 16, - prndr_speaker_layout_7_1 = 12, - prndr_speaker_layout_7_1_4 = 19 -} Prndr_SpeakerLayout; /* Numerical value corresponds to CICP index */ - -typedef struct Prndr_AudioObjectPosition -{ - int16_t azimuth; - int16_t elevation; -} Prndr_AudioObjectPosition; - -typedef struct Prndr_AudioObjectMetadataBuffer -{ - Prndr_AudioObjectPosition positions[PRERENDERER_MAX_ISM_INPUTS]; - uint32_t numObjects; -} Prndr_AudioObjectMetadataBuffer; - -typedef struct Prndr_AudioObject -{ - uint8_t inputChannelIndex; - float gain_dB; -} Prndr_AudioObject; - -typedef struct Prndr_ObjPanInfo -{ - Prndr_AudioObjectPosition position; - float *panGains; -} Prndr_ObjPanInfo; - -typedef struct Prndr_AmbisonicsBus -{ - Prndr_Ambisonics ambisonicsConfig; - uint8_t inputChannelIndex; - float gain_dB; -} Prndr_AmbisonicsBus; - -typedef struct Prndr_MultiChannelBus -{ - Prndr_SpeakerLayout speakerLayout; - uint8_t inputChannelIndex; - float gain_dB; -} Prndr_MultiChannelBus; - -typedef struct Prndr_AudioBufferConfig -{ - int32_t sampleRate; - int16_t bufferSize; - int16_t numChannels; -} Prndr_AudioBufferConfig; - -typedef struct Prndr_AudioBuffer -{ - Prndr_AudioBufferConfig config; - float *data; -} Prndr_AudioBuffer; - -typedef struct Prndr_InputConfig -{ - Prndr_AudioObject audioObjects[PRERENDERER_MAX_ISM_INPUTS]; - uint8_t numAudioObjects; - Prndr_MultiChannelBus multiChannelBuses[PRERENDERER_MAX_MC_INPUTS]; - uint8_t numMultiChannelBuses; - Prndr_AmbisonicsBus ambisonicsBuses[PRERENDERER_MAX_SBA_INPUTS]; - uint8_t numAmbisonicsBuses; -} Prndr_InputConfig; - -typedef struct Prndr_OutputConfig -{ - Prndr_SpeakerLayout speakerLayout; - Prndr_Ambisonics ambisonics; - IVAS_LSSETUP_CUSTOM_HANDLE outSetupCustom; -} Prndr_OutputConfig; - -typedef struct Prndr_Prerenderer Prndr_Prerenderer; - -/* clang-format off */ -/*----------------------------------------------------------------------------------* - * Prerenderer prototypes - *----------------------------------------------------------------------------------*/ - -/*! Creates a prerenderer state. - * r: pointer to opened prerenderer */ -Prndr_Prerenderer *Prndr_Prerenderer_open( - void -); - -/*! Configures the prerenderer - needs to be called after Prndr_Prerenderer_open(). */ -ivas_error Prndr_Prerenderer_configure( - Prndr_Prerenderer *const st, /* i : Prerenderer state */ - const Prndr_InputConfig inConfig, /* i : Input configuration */ - const Prndr_OutputConfig outConfig, /* i : Output configuration */ - int32_t frameSize, /* i : Processing frame size in samples */ - uint32_t sampleRate /* i : Processing sampling rate */ -); - -/*! Renders one frame of audio samples */ -void Prndr_Prerenderer_render( - Prndr_Prerenderer *const st, /* i : Prerenderer state */ - const Prndr_AudioBuffer inAudio, /* i : Buffer with pointer to input samples and associated info */ - const Prndr_AudioObjectMetadataBuffer metadataBuffer, /* i : Buffer with object metadata for current frame */ - Prndr_AudioBuffer outAudio /* o : Buffer with pointer to output samples and associated info */ -); - -/*! Enable/disable experimental LFE handling */ -void Prndr_Prerenderer_setNeverDropLfe( - Prndr_Prerenderer *st, /* i : Prerenderer state */ - int8_t neverDropLfe /* i : If 0, LFE channel will be dropped when rendering to configs w/o LFE. - If 1, tries to render LFE into other channels in an optimal way when rendering to configs w/o LFE. */ -); - -/*! Get number of input channels based on InputConfig */ -int16_t Prndr_Prerenderer_getInChannels( - Prndr_Prerenderer *st /* i : Prerenderer state */ -); - -/*! Get number of output channels based on OutputConfig */ -int16_t Prndr_Prerenderer_getOutChannels( - Prndr_Prerenderer *st /* i : Prerenderer state */ -); - -/*! Destructs the prerenderer state and frees memory */ -void Prndr_Prerenderer_close( - Prndr_Prerenderer *st /* i : Prerenderer state */ -); -/* clang-format on */ - -#endif /* IVAS_PRERENDERER_H */ diff --git a/lib_util/jbm_file_reader.c b/lib_util/jbm_file_reader.c new file mode 100644 index 0000000000000000000000000000000000000000..1be5c223658691c85b01d403c1ea79f330e82658 --- /dev/null +++ b/lib_util/jbm_file_reader.c @@ -0,0 +1,180 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "jbm_file_reader.h" +#include "cmdl_tools.h" +#include +#include + +struct JbmFileReader +{ + FILE *file; + char *file_path; +}; + + +/*---------------------------------------------------------------------* + * JbmFileReader_open() + * + * Allocates memory for an JbmFileReader and opens the file at given path for reading. + *---------------------------------------------------------------------*/ + +/*! r: JbmFileReader handle */ +JbmFileReader *JbmFileReader_open( + const char *filePath /* i : path to CA config file */ +) +{ + JbmFileReader *self; + FILE *file; + + if ( !filePath ) + { + return NULL; + } + + file = fopen( filePath, "rb" ); + + if ( !file ) + { + return NULL; + } + + self = calloc( sizeof( JbmFileReader ), 1 ); + self->file = file; + self->file_path = calloc( sizeof( char ), strlen( filePath ) + 1 ); + strcpy( self->file_path, filePath ); + + return self; +} + + +/*---------------------------------------------------------------------* + * JbmFileReader_readCAconfig() + * + * Read Chanel-aware config. entry + *---------------------------------------------------------------------*/ + +ivas_error JbmFileReader_readCAconfig( + JbmFileReader *self, /* i/o: JbmFileReader handle */ + IVAS_ENC_CHANNEL_AWARE_CONFIG *caConfig /* i/o: configuration of channel-aware mode */ +) +{ + char rline[10], str[4]; + int16_t tmp; + + /* Initialize */ + caConfig->fec_offset = 0; + caConfig->fec_indicator = IVAS_ENC_FEC_HI; + + while ( fgets( rline, 10, self->file ) == NULL && feof( self->file ) ) + { + rewind( self->file ); + } + + if ( sscanf( rline, "%s %hd", str, &tmp ) != 2 ) + { + fprintf( stderr, "Error in the RF configuration file. There is no proper configuration line.\n" ); + return IVAS_ERR_INVALID_FEC_CONFIG; + } + + /* Read RF FEC indicator */ + to_upper( str ); + + if ( strcmp( str, "HI" ) == 0 ) + { + caConfig->fec_indicator = IVAS_ENC_FEC_HI; + } + else if ( strcmp( str, "LO" ) == 0 ) + { + caConfig->fec_indicator = IVAS_ENC_FEC_LO; + } + else + { + fprintf( stderr, "Error: Incorrect FEC indicator string. Exiting the encoder.\n" ); + return IVAS_ERR_INVALID_FEC_CONFIG; + } + + /* Read RF FEC offset */ + if ( tmp == 0 || tmp == 2 || tmp == 3 || tmp == 5 || tmp == 7 ) + { + caConfig->fec_offset = tmp; + } + else + { + fprintf( stderr, "Error: incorrect FEC offset specified in the RF configuration file; RF offset can be 2, 3, 5, or 7. \n" ); + return IVAS_ERR_INVALID_FEC_CONFIG; + } + + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * JbmFileReader_close() + * + * De-allocates all underlying memory of an JbmFileReader. + *---------------------------------------------------------------------*/ + +void JbmFileReader_close( + JbmFileReader **selfPtr /* i/o: pointer to JbmFileReader handle */ +) +{ + if ( selfPtr == NULL || *selfPtr == NULL ) + { + return; + } + + fclose( ( *selfPtr )->file ); + free( ( *selfPtr )->file_path ); + free( *selfPtr ); + *selfPtr = NULL; + + return; +} + + +/*---------------------------------------------------------------------* + * JbmFileReader_getFilePath() + * + *---------------------------------------------------------------------*/ + +const char *JbmFileReader_getFilePath( + JbmFileReader *self /* i/o: JbmFileReader handle */ +) +{ + if ( self == NULL ) + { + return NULL; + } + + return self->file_path; +} diff --git a/lib_util/ivas_rom_prerenderer.c b/lib_util/jbm_file_reader.h similarity index 69% rename from lib_util/ivas_rom_prerenderer.c rename to lib_util/jbm_file_reader.h index 43421165771e08f74c195272104c947335359d35..64d2d17e45efdf246ab05ec56de690c5fd252b70 100644 --- a/lib_util/ivas_rom_prerenderer.c +++ b/lib_util/jbm_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,33 +30,36 @@ *******************************************************************************************************/ -#include "ivas_rom_prerenderer.h" -#include "wmops.h" +#ifndef IVAS_JBM_FILE_READER_H +#define IVAS_JBM_FILE_READER_H + +#include "common_api_types.h" /* clang-format off */ -/*----------------------------------------------------------------------------------* - * Prerenderer SBA & MC enc/dec matrices - *----------------------------------------------------------------------------------*/ +typedef struct JbmFileReader JbmFileReader; -/* CICP1 - Mono */ -const float ls_azimuth_CICP1[1] = { 0.0f }; -const float ls_elevation_CICP1[1] = { 0.0f }; -const uint32_t ls_LFE_last_idx_CICP1[1] = { 0 }; -/* CICP2 - Stereo */ -const uint32_t ls_LFE_last_idx_CICP2[2] = { 0, 1 }; +/*! r: JbmFileReader handle */ +JbmFileReader *JbmFileReader_open( + const char *filePath /* i : path to CA config file */ +); -/* CICP6 - 5.1 */ -const uint32_t ls_LFE_last_idx_CICP6[6] = { 0, 1, 2, 4, 5, 3 }; +ivas_error JbmFileReader_readCAconfig( + JbmFileReader* self, /* i/o: JbmFileReader handle */ + IVAS_ENC_CHANNEL_AWARE_CONFIG *caConfig /* i/o: configuration of channel-aware mode */ +); -/* CICP12 - 7.1 */ -const uint32_t ls_LFE_last_idx_CICP12[8] = { 0, 1, 2, 4, 5, 6, 7, 3 }; +void JbmFileReader_close( + JbmFileReader **selfPtr /* i/o: pointer to JbmFileReader handle */ +); -/* CICP16 - 5.1.4 */ -const uint32_t ls_LFE_last_idx_CICP16[10] = { 0, 1, 2, 4, 5, 6, 7, 8, 9, 3 }; +/*! r: path to the currently opened file or NULL if `self` is NULL */ +const char *JbmFileReader_getFilePath( + JbmFileReader* self /* i/o: JbmFileReader handle */ +); -/* CICP19 - 7.1.4 */ -const uint32_t ls_LFE_last_idx_CICP19[12] = { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 3 }; /* clang-format on */ + +#endif /* IVAS_JBM_FILE_READER_H */ diff --git a/lib_util/jbm_file_writer.c b/lib_util/jbm_file_writer.c index bf34c5187279d47dcdaecb3a1dc37886ff6dbedb..584a22bc7f97df3c3084e1a4045356f6547e80bf 100644 --- a/lib_util/jbm_file_writer.c +++ b/lib_util/jbm_file_writer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -31,7 +31,6 @@ *******************************************************************************************************/ #include "jbm_file_writer.h" -#include #include #include @@ -78,7 +77,7 @@ ivas_error JbmOffsetFileWriter_open( return IVAS_ERR_FAILED_FILE_OPEN; } - self = calloc( sizeof( JbmTraceFileWriter ), 1 ); + self = calloc( sizeof( JbmOffsetFileWriter ), 1 ); self->file = file; self->file_path = calloc( sizeof( char ), strlen( jbmOffsetFilename ) + 1 ); strcpy( self->file_path, jbmOffsetFilename ); @@ -191,9 +190,6 @@ ivas_error JbmTraceFileWriter_open( JbmTraceFileWriter *self; FILE *file; -#ifdef SUPPORT_JBM_TRACEFILE -#endif - if ( strlen( jbmTraceFilename ) < 1 ) { return IVAS_ERR_FAILED_FILE_OPEN; @@ -227,8 +223,8 @@ ivas_error JbmTraceFileWriter_open( /*! r: error code */ ivas_error JbmTraceFileWriter_writeFrame( - const IVAS_JBM_TRACE_DATA *JbmTraceData, /* i : JBM trace data */ - JbmTraceFileWriter *jbmTraceWriter /* o : JbmTraceFileWriter handle */ + const IVAS_JBM_TRACE_DATA *data, /* i : JBM trace data */ + JbmTraceFileWriter *jbmTraceWriter /* o : JbmTraceFileWriter handle */ ) { FILE *file; @@ -242,21 +238,23 @@ ivas_error JbmTraceFileWriter_writeFrame( if ( file ) { + /* the first sample of the decoded/concealed frame will be played after the samples in the ring buffer */ + double playTime = data->systemTimestamp_ms + data->extBufferedSamples * 1000.0 / data->output_Fs; /* rtpSeqNo;rtpTs;rcvTime;playTime;active\n */ - if ( JbmTraceData->dataUnit_flag ) + if ( data->dataUnit_flag ) { - if ( JbmTraceData->partial_frame_flag == 1 ) + if ( data->partial_frame == 1 ) { - fprintf( file, "%d;%d;%d;%f;%d;%d\n", -1, -1, -1, JbmTraceData->playTime, JbmTraceData->lastDecodedWasActive, JbmTraceData->partialCopyOffset ); + fprintf( file, "%d;%d;%d;%f;%d;%d\n", -1, -1, -1, playTime, data->lastDecodedWasActive, data->partialCopyOffset ); } else { - fprintf( file, "%u;%u;%u;%f;%d\n", JbmTraceData->sequenceNumber, JbmTraceData->timeStamp, JbmTraceData->rcvTime, JbmTraceData->playTime, JbmTraceData->lastDecodedWasActive ); + fprintf( file, "%u;%u;%u;%f;%d\n", data->sequenceNumber, data->timeStamp, data->rcvTime, playTime, data->lastDecodedWasActive ); } } else { - fprintf( file, "%d;%d;%d;%f;%d\n", -1, -1, -1, JbmTraceData->playTime, JbmTraceData->lastDecodedWasActive ); + fprintf( file, "%d;%d;%d;%f;%d\n", -1, -1, -1, playTime, data->lastDecodedWasActive ); } } else diff --git a/lib_util/jbm_file_writer.h b/lib_util/jbm_file_writer.h index 5cfab08f613f02f1d7f2a65c752a08512d86bbc8..c82c38e0f9bcbfd9b039a5c31a4b863900e21139 100644 --- a/lib_util/jbm_file_writer.h +++ b/lib_util/jbm_file_writer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,9 +33,7 @@ #ifndef IVAS_JBM_FILE_WRITER_H #define IVAS_JBM_FILE_WRITER_H -#include #include "common_api_types.h" -#include "ivas_error.h" /* clang-format off */ diff --git a/lib_util/ls_custom_file_reader.c b/lib_util/ls_custom_file_reader.c index c961374c208e7e8e02f2ee3630b07308136f17ed..9b39fab486bd99ab3259fc5dd6770351792e1e6e 100644 --- a/lib_util/ls_custom_file_reader.c +++ b/lib_util/ls_custom_file_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,7 +32,6 @@ #include "ls_custom_file_reader.h" #include -#include #include #include "ivas_prot.h" #include "prot.h" @@ -52,8 +51,8 @@ struct LsCustomFileReader *-----------------------------------------------------------------------*/ ivas_error CustomLsReader_open( - char *LsFilePath, /* i : LS custom layout file name */ - LsCustomFileReader **hLsCustomReader /* o : HeadRotFileReader handle */ + const char *LsFilePath, /* i : LS custom layout file name */ + LsCustomFileReader **hLsCustomReader /* o : LsCustomFileReader handle */ ) { LsCustomFileReader *self; @@ -90,7 +89,7 @@ ivas_error CustomLsReader_open( *-----------------------------------------------------------------------*/ void CustomLsReader_close( - LsCustomFileReader **hLsCustomReader /* i/o: HeadRotFileReader handle */ + LsCustomFileReader **hLsCustomReader /* i/o: LsCustomFileReader handle */ ) { if ( hLsCustomReader == NULL || *hLsCustomReader == NULL ) @@ -229,7 +228,7 @@ static void CustomLoudspeakerLayout_print_info( *-------------------------------------------------------------------------*/ LS_CUSTOM_FILEREADER_ERROR CustomLsFileReading( - LsCustomFileReader *hLsCustomReader, /* i/o: HeadRotFileReader handle */ + LsCustomFileReader *hLsCustomReader, /* i/o: LsCustomFileReader handle */ IVAS_CUSTOM_LS_DATA *hLsCustomData /* o : Custom loudspeaker setup data */ ) { @@ -269,7 +268,7 @@ LS_CUSTOM_FILEREADER_ERROR CustomLsFileReading( tok++; } - if ( *tok == '\0' ) + if ( *tok == '\0' ) // replace by isEmptyString() { continue; } @@ -314,7 +313,7 @@ LS_CUSTOM_FILEREADER_ERROR CustomLsFileReading( } } - /* parse LFE indicies; skip if blank line */ + /* parse LFE indices; skip if blank line */ if ( ( fgets( line, 200, hLsCustomReader->file ) != NULL ) && ( strcmp( line, "\n" ) != 0 ) && ( strcmp( line, "\r\n" ) != 0 ) ) { for ( tok = strtok( line, "," ); tok && *tok; tok = strtok( NULL, ",\n" ) ) diff --git a/lib_util/ls_custom_file_reader.h b/lib_util/ls_custom_file_reader.h index 3f9e0d56d378ff5bbec1dba7de091f6ab01cfbf8..df7fe6bde7a929cb7dff5ae4a4e17d34ab0b58eb 100644 --- a/lib_util/ls_custom_file_reader.h +++ b/lib_util/ls_custom_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,9 +33,7 @@ #ifndef IVAS_LS_CUSTOM_FILE_READER_H #define IVAS_LS_CUSTOM_FILE_READER_H -#include #include "common_api_types.h" -#include "ivas_error.h" typedef struct LsCustomFileReader LsCustomFileReader; @@ -65,8 +63,8 @@ typedef enum _LS_CUSTOM_FILEREADER_ERROR *-----------------------------------------------------------------------*/ ivas_error CustomLsReader_open( - char *LsFilePath, /* i : LS custom layout file name */ - LsCustomFileReader **hLsCustomReader /* o : HeadRotFileReader handle */ + const char *LsFilePath, /* i : LS custom layout file name */ + LsCustomFileReader **hLsCustomReader /* o : LsCustomFileReader handle */ ); /*-----------------------------------------------------------------------* @@ -76,7 +74,7 @@ ivas_error CustomLsReader_open( *-----------------------------------------------------------------------*/ void CustomLsReader_close( - LsCustomFileReader **hLsCustomReader /* i/o: HeadRotFileReader handle */ + LsCustomFileReader **hLsCustomReader /* i/o: LsCustomFileReader handle */ ); /*-------------------------------------------------------------------------* @@ -86,7 +84,7 @@ void CustomLsReader_close( *-------------------------------------------------------------------------*/ LS_CUSTOM_FILEREADER_ERROR CustomLsFileReading( - LsCustomFileReader *hLsCustomReader, /* i/o: HeadRotFileReader handle */ + LsCustomFileReader *hLsCustomReader, /* i/o: LsCustomFileReader handle */ IVAS_CUSTOM_LS_DATA *hLsCustomData /* o : Custom loudspeaker setup data */ ); diff --git a/lib_util/masa_file_reader.c b/lib_util/masa_file_reader.c index 918d613d379f3d06b64565d5575743e30d6a8be2..19f12182f3ab11246cbe74ff5ddf2eec45a0ca89 100644 --- a/lib_util/masa_file_reader.c +++ b/lib_util/masa_file_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,7 +32,7 @@ #include "masa_file_reader.h" #include "ivas_prot.h" -#include +#include "ivas_stat_com.h" #include #include diff --git a/lib_util/masa_file_reader.h b/lib_util/masa_file_reader.h index 898303c99e08cdde30815bac2214d720b134452b..5f3f2fec2a9ce19d539ddad48bc29ba53e3c7b0d 100644 --- a/lib_util/masa_file_reader.h +++ b/lib_util/masa_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,9 +33,7 @@ #ifndef IVAS_MASA_FILE_READER_H #define IVAS_MASA_FILE_READER_H -#include #include "common_api_types.h" -#include "ivas_error.h" struct MasaFileReader; diff --git a/lib_util/masa_file_writer.c b/lib_util/masa_file_writer.c index e8f9a09c68d812dfa9f3f4059932c1d4046cb90b..5667968ece8b39c4a1a8ecc783a9efcea63b2011 100644 --- a/lib_util/masa_file_writer.c +++ b/lib_util/masa_file_writer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -32,25 +32,43 @@ #include "masa_file_writer.h" #include "ivas_stat_com.h" +#ifdef FIX_350_MASA_DELAY_COMP +#include "ivas_stat_dec.h" +#endif #include "ivas_cnst.h" #include -#include #include #include +#ifdef FIX_350_MASA_DELAY_COMP +typedef struct masaMetaDelayStorage +{ + MASA_DECRIPTIVE_META descriptiveMeta; + uint16_t directionIndex[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS]; + uint8_t directToTotalRatio[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS]; + uint8_t spreadCoherence[MASA_MAXIMUM_DIRECTIONS][DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS]; + uint8_t surroundCoherence[DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS]; + uint8_t diffuseToTotalRatio[DELAY_MASA_PARAM_DEC_SFR][MASA_FREQUENCY_BANDS]; + +} MASA_META_DELAY_STORAGE; +#endif struct MasaFileWriter { FILE *file; char *file_path; +#ifdef FIX_350_MASA_DELAY_COMP + MASA_META_DELAY_STORAGE *delayStorage; +#endif }; /*-----------------------------------------------------------------------* * Local constants *-----------------------------------------------------------------------*/ +#ifndef FIX_350_MASA_DELAY_COMP #define SPH_IDX_FRONT ( MASA_NO_POINTS_EQUATOR / 2 ) /* Spherical index corresponding to front direction for setting as default value */ - +#endif /*-----------------------------------------------------------------------* * Local functions @@ -66,7 +84,7 @@ static void getExtMasaMetadataFileName( /* sizeof( ext_meta ) accounts for terminating NULL, don't subtract extra 1 */ const int32_t maxNameLenWithoutExt = sizeof( metadata_filename[0] ) - sizeof( ext_meta ); strncpy( metadata_filename[0], outputWavFilename, maxNameLenWithoutExt ); - sprintf( ext_meta, ".met" ); + snprintf( ext_meta, sizeof( ext_meta ), ".met" ); /* strlen( metadata_filename[0] ) doesn't account for terminating NULL, subtract extra 1 */ const int32_t maxNumCharactersToAppend = (int32_t) ( sizeof( metadata_filename[0] ) - strlen( metadata_filename[0] ) - 1 ); @@ -75,16 +93,77 @@ static void getExtMasaMetadataFileName( return; } +#ifdef FIX_350_MASA_DELAY_COMP +static void delayMasaMetadata( + MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o : New input metadata which is inplace replaced with delayed metadata frame */ + MASA_META_DELAY_STORAGE *delayStorage /* i/o : Storage for 10 ms of metadata and related descriptive metadata */ +) +{ + int16_t dir, sf, band; + uint8_t currentNumberOfDirections; + + /* Move meta to delay and output. Always use two directions as the metadata is prepared to contain zero energy second direction + * if there is 1dir meta. */ + for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES - DELAY_MASA_PARAM_DEC_SFR; sf++ ) + { + for ( band = 0; band < MASA_FREQUENCY_BANDS; band++ ) + { + uint16_t temp_u16; + uint8_t temp_u8; + for ( dir = 0; dir < MASA_MAXIMUM_DIRECTIONS; dir++ ) + { + temp_u16 = delayStorage->directionIndex[dir][sf][band]; + delayStorage->directionIndex[dir][sf][band] = extOutMeta->directionIndex[dir][sf + DELAY_MASA_PARAM_DEC_SFR][band]; + extOutMeta->directionIndex[dir][sf + DELAY_MASA_PARAM_DEC_SFR][band] = extOutMeta->directionIndex[dir][sf][band]; + extOutMeta->directionIndex[dir][sf][band] = temp_u16; + + temp_u8 = delayStorage->directToTotalRatio[dir][sf][band]; + delayStorage->directToTotalRatio[dir][sf][band] = extOutMeta->directToTotalRatio[dir][sf + DELAY_MASA_PARAM_DEC_SFR][band]; + extOutMeta->directToTotalRatio[dir][sf + DELAY_MASA_PARAM_DEC_SFR][band] = extOutMeta->directToTotalRatio[dir][sf][band]; + extOutMeta->directToTotalRatio[dir][sf][band] = temp_u8; + + temp_u8 = delayStorage->spreadCoherence[dir][sf][band]; + delayStorage->spreadCoherence[dir][sf][band] = extOutMeta->spreadCoherence[dir][sf + DELAY_MASA_PARAM_DEC_SFR][band]; + extOutMeta->spreadCoherence[dir][sf + DELAY_MASA_PARAM_DEC_SFR][band] = extOutMeta->spreadCoherence[dir][sf][band]; + extOutMeta->spreadCoherence[dir][sf][band] = temp_u8; + } + + temp_u8 = delayStorage->surroundCoherence[sf][band]; + delayStorage->surroundCoherence[sf][band] = extOutMeta->surroundCoherence[sf + DELAY_MASA_PARAM_DEC_SFR][band]; + extOutMeta->surroundCoherence[sf + DELAY_MASA_PARAM_DEC_SFR][band] = extOutMeta->surroundCoherence[sf][band]; + extOutMeta->surroundCoherence[sf][band] = temp_u8; + + temp_u8 = delayStorage->diffuseToTotalRatio[sf][band]; + delayStorage->diffuseToTotalRatio[sf][band] = extOutMeta->diffuseToTotalRatio[sf + DELAY_MASA_PARAM_DEC_SFR][band]; + extOutMeta->diffuseToTotalRatio[sf + DELAY_MASA_PARAM_DEC_SFR][band] = extOutMeta->diffuseToTotalRatio[sf][band]; + extOutMeta->diffuseToTotalRatio[sf][band] = temp_u8; + } + } + + /* Finalize descriptive meta by using new frame except for number of directions which is the larger of the two */ + currentNumberOfDirections = extOutMeta->descriptiveMeta.numberOfDirections; + if ( delayStorage->descriptiveMeta.numberOfDirections > extOutMeta->descriptiveMeta.numberOfDirections ) + { + extOutMeta->descriptiveMeta.numberOfDirections = delayStorage->descriptiveMeta.numberOfDirections; + } + delayStorage->descriptiveMeta.numberOfDirections = currentNumberOfDirections; + + return; +} +#endif /*---------------------------------------------------------------------* - * MasaFileWriter_writeFrame() + * MasaFileWriter_open() * * *---------------------------------------------------------------------*/ ivas_error MasaFileWriter_open( const char *outputWavFilename, /* i : name of the output audio file */ - MasaFileWriter **masaWriter /* o : MasaFileWriter handle */ +#ifdef FIX_350_MASA_DELAY_COMP + const bool delayCompensationEnabled, /* i : is delay compensation enabled */ +#endif + MasaFileWriter **masaWriter /* o : MasaFileWriter handle */ ) { MasaFileWriter *self; @@ -110,6 +189,13 @@ ivas_error MasaFileWriter_open( self->file_path = calloc( sizeof( char ), strlen( filePath ) + 1 ); strcpy( self->file_path, filePath ); +#ifdef FIX_350_MASA_DELAY_COMP + if ( !delayCompensationEnabled ) + { + self->delayStorage = calloc( sizeof( MASA_META_DELAY_STORAGE ), 1 ); + } +#endif + *masaWriter = self; return IVAS_ERR_OK; @@ -123,8 +209,12 @@ ivas_error MasaFileWriter_open( *---------------------------------------------------------------------*/ ivas_error MasaFileWriter_writeFrame( - MasaFileWriter *self, /* i/o: MasaFileWriter handle */ - IVAS_MASA_QMETADATA_HANDLE hMasaQMetadata /* i/o: MASA qMetadata handle to be written */ + MasaFileWriter *self, /* i/o: MasaFileWriter handle */ +#ifdef FIX_350_MASA_DELAY_COMP + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta /* i/o: MASA ext out meta handle to be written */ +#else + IVAS_MASA_QMETADATA_HANDLE hMasaQMetadata /* i/o: MASA qMetadata handle to be written */ +#endif ) { if ( self == NULL ) @@ -132,6 +222,11 @@ ivas_error MasaFileWriter_writeFrame( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef FIX_350_MASA_DELAY_COMP + uint16_t descMetaTemp = 0; + int16_t i, sf, dir, numDirections; + uint8_t writeTempOther[MASA_FREQUENCY_BANDS]; +#else const uint8_t ivasmasaFormatDescriptor[8] = { 0x49, 0x56, 0x41, 0x53, 0x4D, 0x41, 0x53, 0x41 }; /* "IVASMASA" */ uint16_t descMetaTemp = 0; int16_t i, sf, b_old, b_new, dir; @@ -147,7 +242,45 @@ ivas_error MasaFileWriter_writeFrame( numCodingBands = hMasaQMetadata->numCodingBands; bandMap = hMasaQMetadata->bandMap; nchan_transport = hMasaQMetadata->nchan_transport; +#endif + +#ifdef FIX_350_MASA_DELAY_COMP + /* If delay storage has been reserved, then we are in the normal mode for the decoder + * (i.e., no delay compensation for PCM) which means that metadata should be delayed + * by two subframes (10 ms). Descriptive metadata is a combined result. */ + if ( self->delayStorage ) + { + delayMasaMetadata( hMasaExtOutMeta, self->delayStorage ); + } + numDirections = hMasaExtOutMeta->descriptiveMeta.numberOfDirections + 1; + + if ( fwrite( &( hMasaExtOutMeta->descriptiveMeta.formatDescriptor ), sizeof( uint8_t ), 8, self->file ) != 8 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.numberOfDirections << 15u; + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.numberOfChannels << 14u; + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.sourceFormat << 12u; + if ( hMasaExtOutMeta->descriptiveMeta.sourceFormat == 0x0 || hMasaExtOutMeta->descriptiveMeta.sourceFormat == 0x1 ) + { + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.transportDefinition << 9u; + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.channelAngle << 6u; + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.channelDistance; + } + else if ( hMasaExtOutMeta->descriptiveMeta.sourceFormat == 0x2 ) + { + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.channelLayout << 9u; + /* 9 LSB remain at zero */ + } + else if ( hMasaExtOutMeta->descriptiveMeta.sourceFormat == 0x3 ) + { + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.transportDefinition << 9u; + descMetaTemp += hMasaExtOutMeta->descriptiveMeta.channelAngle << 6u; + /* 6 LSB remain at zero */ + } +#else /* Construct descriptive meta */ for ( i = 0; i < 8; i++ ) { @@ -187,6 +320,7 @@ ivas_error MasaFileWriter_writeFrame( descMetaTemp += descMeta.channelAngle << 6u; /* 6 LSB remain at zero */ } +#endif if ( fwrite( &( descMetaTemp ), sizeof( uint16_t ), 1, self->file ) != 1 ) { @@ -198,6 +332,9 @@ ivas_error MasaFileWriter_writeFrame( for ( dir = 0; dir < numDirections; dir++ ) { /* Spherical index */ +#ifdef FIX_350_MASA_DELAY_COMP + if ( fwrite( hMasaExtOutMeta->directionIndex[dir][sf], sizeof( uint16_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#else for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) { writeTempIndex[i] = SPH_IDX_FRONT; @@ -212,11 +349,15 @@ ivas_error MasaFileWriter_writeFrame( } if ( fwrite( writeTempIndex, sizeof( uint16_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#endif { return IVAS_ERR_FAILED_FILE_WRITE; } /* Direct-to-total ratio */ +#ifdef FIX_350_MASA_DELAY_COMP + if ( fwrite( hMasaExtOutMeta->directToTotalRatio[dir][sf], sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#else for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) { writeTempOther[i] = 0; @@ -231,11 +372,15 @@ ivas_error MasaFileWriter_writeFrame( } if ( fwrite( writeTempOther, sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#endif { return IVAS_ERR_FAILED_FILE_WRITE; } /* Spread coherence */ +#ifdef FIX_350_MASA_DELAY_COMP + if ( fwrite( hMasaExtOutMeta->spreadCoherence[dir][sf], sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#else for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) { writeTempOther[i] = 0; @@ -253,6 +398,7 @@ ivas_error MasaFileWriter_writeFrame( } if ( fwrite( writeTempOther, sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#endif { return IVAS_ERR_FAILED_FILE_WRITE; } @@ -260,6 +406,9 @@ ivas_error MasaFileWriter_writeFrame( /* Common spatial meta */ /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */ +#ifdef FIX_350_MASA_DELAY_COMP + if ( fwrite( hMasaExtOutMeta->diffuseToTotalRatio[sf], sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#else for ( b_new = 0; b_new < MASA_FREQUENCY_BANDS; b_new++ ) { writeTempOther[b_new] = UINT8_MAX; @@ -278,11 +427,16 @@ ivas_error MasaFileWriter_writeFrame( } if ( fwrite( writeTempOther, sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#endif { return IVAS_ERR_FAILED_FILE_WRITE; } /* Surround coherence */ +#ifdef FIX_350_MASA_DELAY_COMP + if ( fwrite( hMasaExtOutMeta->surroundCoherence[sf], sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#else + /* Surround coherence */ for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) { writeTempOther[i] = 0; @@ -300,16 +454,24 @@ ivas_error MasaFileWriter_writeFrame( } if ( fwrite( writeTempOther, sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) +#endif { return IVAS_ERR_FAILED_FILE_WRITE; } /* Remainder-to-total ratio */ /* This is zero after codec */ +#ifdef FIX_350_MASA_DELAY_COMP + for ( i = 0; i < MASA_FREQUENCY_BANDS; i++ ) + { + writeTempOther[i] = 0u; + } +#else for ( b_new = 0; b_new < MASA_FREQUENCY_BANDS; b_new++ ) { writeTempOther[b_new] = 0u; } +#endif if ( fwrite( writeTempOther, sizeof( uint8_t ), MASA_FREQUENCY_BANDS, self->file ) != MASA_FREQUENCY_BANDS ) { @@ -338,6 +500,9 @@ void MasaFileWriter_close( fclose( ( *selfPtr )->file ); free( ( *selfPtr )->file_path ); +#ifdef FIX_350_MASA_DELAY_COMP + free( ( *selfPtr )->delayStorage ); +#endif free( *selfPtr ); *selfPtr = NULL; diff --git a/lib_util/masa_file_writer.h b/lib_util/masa_file_writer.h index ce4ed2e238fdb651f87d49b9de844bac6767df51..cb7d8f3d1efdb608e5e880be8a18a49bd43bffec 100644 --- a/lib_util/masa_file_writer.h +++ b/lib_util/masa_file_writer.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,8 +34,11 @@ #define IVAS_MASA_FILE_WRITER_H #include +#include "options.h" +#ifdef FIX_350_MASA_DELAY_COMP +#include +#endif #include "common_api_types.h" -#include "ivas_error.h" struct MasaFileWriter; @@ -43,12 +46,19 @@ typedef struct MasaFileWriter MasaFileWriter; ivas_error MasaFileWriter_open( const char *outputWavFilename, /* i : name of the output audio file */ - MasaFileWriter **masaWriter /* o : MasaFileWriter handle */ +#ifdef FIX_350_MASA_DELAY_COMP + const bool delayCompensationEnabled, /* i : is delay compensation enabled */ +#endif + MasaFileWriter **masaWriter /* o : MasaFileWriter handle */ ); ivas_error MasaFileWriter_writeFrame( - MasaFileWriter *self, /* i/o: MasaFileWriter handle */ + MasaFileWriter *self, /* i/o: MasaFileWriter handle */ +#ifdef FIX_350_MASA_DELAY_COMP + MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta /* i/o: MASA ext out meta handle to be written */ +#else IVAS_MASA_QMETADATA_HANDLE hMasaQMetadata /* i/o: MASA qMetadata handle to be written */ +#endif ); void MasaFileWriter_close( diff --git a/lib_util/mime_io.c b/lib_util/mime_io.c index 36cd61adbbdc0f41e2da93ab34448a6ea12088dd..b5c257bb49558d5c59d02977a566974ff30b5fb2 100644 --- a/lib_util/mime_io.c +++ b/lib_util/mime_io.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,7 +30,6 @@ *******************************************************************************************************/ -#include "options.h" #include "mime_io.h" #include "mime.h" #include "prot.h" diff --git a/lib_util/mime_io.h b/lib_util/mime_io.h index 770b4dd5e4bed5b5b70c6fda02880875e0d0b82e..91b9160529600b46447baf60dca5485c71a3ec1a 100644 --- a/lib_util/mime_io.h +++ b/lib_util/mime_io.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index a9027bf92adc41e7fc6d33ef6e401f86835d416a..54f2d012ce7f06c567ba87d1e216e98680306845 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -33,12 +33,11 @@ #include "render_config_reader.h" #include #include -#include #include #include #include "cmdl_tools.h" #include "prot.h" -#include "ivas_cnst.h" + /*------------------------------------------------------------------------------------------* * PreProc Macros @@ -48,6 +47,22 @@ #define MAX_ITEM_LENGTH ( 64 ) #define N_REVERB_VECTORS ( 3 ) +#define SHORTEST_REV_DEL_LINE ( 0.015f ) +#define N_BANDS_MIN ( 2 ) +#define N_BANDS_MAX ( 60 ) +#define FC_INPUT_MIN ( 0.0f ) +#define FC_INPUT_MAX ( 1.0e+5f ) +#define ACOUSTIC_RT60_MIN ( 1.0e-3f ) +#define ACOUSTIC_RT60_MAX ( 1.0e+2f ) +#define ACOUSTIC_DSR_MIN ( 0.0f ) +#define ACOUSTIC_DSR_MAX ( 1.0e+2f ) +#define ACOUSTIC_DSR_EPSILON ( 1.0e-15f ) +#define ACOUSTICPREDELAY_JOTREV_MIN ( SHORTEST_REV_DEL_LINE ) +#define ACOUSTICPREDELAY_JOTREV_MAX ( SHORTEST_REV_DEL_LINE + 1.0f / (float) FRAMES_PER_SEC ) +#define ACOUSTICPREDELAY_FDREV_MIN ( 1.0f / (float) ( 16 * FRAMES_PER_SEC ) ) +#define ACOUSTICPREDELAY_FDREV_MAX ( (float) ( REVERB_PREDELAY_MAX ) / (float) ( 16 * FRAMES_PER_SEC ) ) +#define INPUTPREDELAY_MIN ( 0.0f ) +#define INPUTPREDELAY_MAX ( 1.0e+2f ) /*------------------------------------------------------------------------------------------* * Type definitions @@ -74,17 +89,17 @@ static int16_t read_bool( if ( sscanf( pLine, "%s", (char *) &value ) != 1 ) { - return true; + return TRUE; } if ( strcmp( value, "TRUE" ) == 0 ) { - *pTarget = true; - return false; + *pTarget = TRUE; + return FALSE; } if ( strcmp( value, "FALSE" ) == 0 ) { - *pTarget = false; - return false; + *pTarget = FALSE; + return FALSE; } return true; @@ -205,6 +220,98 @@ static int32_t errorHandler( return numErrors; } +/*------------------------------------------------------------------------------------------* + * RenderConfigReader_checkValues() + * + * Verifies if the configuration parameters lie within acceptable limits + *------------------------------------------------------------------------------------------*/ + +static ivas_error RenderConfigReader_checkValues( + IVAS_RENDER_CONFIG_HANDLE hRenderConfig /* o : Renderer configuration handle */ +) +{ + int16_t band_idx, tab_value_err_count; + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoom_acoustics; + pRoom_acoustics = &hRenderConfig->room_acoustics; + tab_value_err_count = 0; + + /* Verify the number of frequency bands in the config input data */ + if ( ( pRoom_acoustics->nBands > N_BANDS_MAX ) || ( pRoom_acoustics->nBands < N_BANDS_MIN ) ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + /* Verify input pre-delay value */ + if ( ( pRoom_acoustics->inputPreDelay > INPUTPREDELAY_MAX ) || ( pRoom_acoustics->inputPreDelay < INPUTPREDELAY_MIN ) ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + /* Verify data per band in the acoustic properties table */ + for ( band_idx = 0; band_idx < pRoom_acoustics->nBands; band_idx++ ) + { + /* Verify if the frequencies are in the ascending order (required for interpolation) */ + if ( band_idx != 0 ) + { + if ( pRoom_acoustics->pFc_input[band_idx] <= pRoom_acoustics->pFc_input[band_idx - 1] ) + { + tab_value_err_count++; + } + } + + /* Check the input frequencies */ + if ( ( pRoom_acoustics->pFc_input[band_idx] > FC_INPUT_MAX ) || ( pRoom_acoustics->pFc_input[band_idx] < FC_INPUT_MIN ) ) + { + tab_value_err_count++; + } + + /* Check the input RT60 values */ + if ( ( pRoom_acoustics->pAcoustic_rt60[band_idx] > ACOUSTIC_RT60_MAX ) || ( pRoom_acoustics->pAcoustic_rt60[band_idx] < ACOUSTIC_RT60_MIN ) ) + { + tab_value_err_count++; + } + + /* Check the input DSR values */ + if ( ( pRoom_acoustics->pAcoustic_dsr[band_idx] > ACOUSTIC_DSR_MAX ) || ( pRoom_acoustics->pAcoustic_dsr[band_idx] < ACOUSTIC_DSR_MIN ) ) + { + tab_value_err_count++; + } + + /* Replace zero DSR values with very small positive values, to avoid issues with coloration filter design */ + if ( pRoom_acoustics->pAcoustic_dsr[band_idx] <= 0.0f ) + { + pRoom_acoustics->pAcoustic_dsr[band_idx] = ACOUSTIC_DSR_EPSILON; + } + } + + if ( tab_value_err_count != 0 ) + { + return IVAS_ERR_WRONG_PARAMS; + } + +#ifdef DEBUGGING + /* Specific limits for Jot reverb */ + if ( hRenderConfig->renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_CREND ) + { + if ( ( pRoom_acoustics->acousticPreDelay > ACOUSTICPREDELAY_JOTREV_MAX ) || ( pRoom_acoustics->acousticPreDelay < ACOUSTICPREDELAY_JOTREV_MIN ) ) + { + return IVAS_ERR_WRONG_PARAMS; + } + } + + /* Specific limits for frequency-domain reverb */ + if ( hRenderConfig->renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_FASTCONV ) + { + if ( ( pRoom_acoustics->acousticPreDelay > ACOUSTICPREDELAY_FDREV_MAX ) || ( pRoom_acoustics->acousticPreDelay < ACOUSTICPREDELAY_FDREV_MIN ) ) + { + return IVAS_ERR_WRONG_PARAMS; + } + } +#endif /* DEBUGGING */ + + return IVAS_ERR_OK; +} + /*------------------------------------------------------------------------------------------* * RenderConfigReader_open() @@ -310,8 +417,8 @@ ivas_error RenderConfigReader_read( pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) { - hRenderConfig->room_acoustics.override = true; - params_idx += strlen( item ) + strlen( pValue ) + 2; + hRenderConfig->room_acoustics.override = TRUE; + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); #ifdef DEBUGGING fprintf( stderr, " PARAM: %s -> %s\n", item, pValue ); #endif @@ -398,7 +505,7 @@ ivas_error RenderConfigReader_read( pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) { - params_idx += strlen( item ) + strlen( pValue ) + 2; + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); fprintf( stderr, " PARAM: %s -> %s\n", item, pValue ); if ( strcmp( item, "RENDERER" ) == 0 ) { @@ -415,6 +522,13 @@ ivas_error RenderConfigReader_read( errorHandler( pValue, ERROR_VALUE_INVALID ); } } + else if ( strcmp( item, "DIRECTIVITY" ) == 0 ) + { + if ( read_vector( pValue, 3, hRenderConfig->directivity ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } #ifdef DEBUGGING else { @@ -452,7 +566,7 @@ ivas_error RenderConfigReader_read( return IVAS_ERR_FAILED_FILE_PARSE; } - return IVAS_ERR_OK; + return RenderConfigReader_checkValues( hRenderConfig ); } diff --git a/lib_util/render_config_reader.h b/lib_util/render_config_reader.h index 1130b43b8cb7603ea0e0a80ef9bbb2ce8258d510..c2afb92e8bb11cd1b8706fbb573961dd69a1b36c 100644 --- a/lib_util/render_config_reader.h +++ b/lib_util/render_config_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -34,7 +34,6 @@ #define RENDER_CONFIG_READER_H #include "common_api_types.h" -#include "ivas_error.h" typedef struct RenderConfigReader RenderConfigReader; diff --git a/lib_util/rtpdump.c b/lib_util/rtpdump.c index 79a4e43ede8133de491186177ef706817f9a3f45..262f114a13ef015d83562bb35d5d978ed0bc794a 100644 --- a/lib_util/rtpdump.c +++ b/lib_util/rtpdump.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_util/rtpdump.h b/lib_util/rtpdump.h index 3b5cb6b64b35359bec260727560c3ebbeef2dd8e..46300c0e9a1e85fbd704ea54df6da123e40df741 100644 --- a/lib_util/rtpdump.h +++ b/lib_util/rtpdump.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_util/tinywavein_c.h b/lib_util/tinywavein_c.h index 1f826a03013a040952958aefd1aa728778227c46..2d9a218934cf29bccc1b96ba4b0b169dce7ef37f 100644 --- a/lib_util/tinywavein_c.h +++ b/lib_util/tinywavein_c.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/lib_util/tinywaveout_c.h b/lib_util/tinywaveout_c.h index c0cdf0812908b8d965d3b9780dff948f5d3db118..d0531eb6653c47288f7db1b6f1c84d454f55227d 100644 --- a/lib_util/tinywaveout_c.h +++ b/lib_util/tinywaveout_c.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -241,8 +241,8 @@ static WAVEFILEOUT *CreateWav( return CreateBWF( fileName, sampleRate, numChannels, bps ); } -const int16_t MAX_PCM16 = 32767; -const int16_t MIN_PCM16 = -32768; +static const int16_t MAX_PCM16 = 32767; +static const int16_t MIN_PCM16 = -32768; static __inline int32_t CLIP_PCM16( int32_t sample, uint32_t *clipcount ) @@ -266,8 +266,8 @@ static __inline int32_t CLIP_PCM16( return tmp; } -const int32_t MAX_PCM24 = 8388607; -const int32_t MIN_PCM24 = -8388608; +static const int32_t MAX_PCM24 = 8388607; +static const int32_t MIN_PCM24 = -8388608; static __inline int32_t CLIP_PCM24( int32_t sample, uint32_t *clipcount ) diff --git a/lib_util/vector3_pair_file_reader.c b/lib_util/vector3_pair_file_reader.c new file mode 100644 index 0000000000000000000000000000000000000000..9e03358b91c901e9c6f2875bb8f714cce00a86db --- /dev/null +++ b/lib_util/vector3_pair_file_reader.c @@ -0,0 +1,163 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "vector3_pair_file_reader.h" +#include +#include +#include +#include +#include "prot.h" +#include "options.h" /* only included to get access to the feature-defines */ + + +struct Vector3PairFileReader +{ + FILE *trajFile; + char *file_path; +}; + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_open() + * + * Allocate and initialize reader + *-----------------------------------------------------------------------*/ + +ivas_error Vector3PairFileReader_open( + const char *trajFilePath, /* i : trajectory file name */ + Vector3PairFileReader **vector3PairReader /* o : Vector3PairFileReader handle */ +) +{ + Vector3PairFileReader *self; + FILE *trajFile; + + /* Open trajectory file */ + if ( strlen( trajFilePath ) < 1 ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + trajFile = fopen( trajFilePath, "r" ); + + if ( !trajFile ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + self = calloc( sizeof( Vector3PairFileReader ), 1 ); + self->trajFile = trajFile; + self->file_path = calloc( sizeof( char ), strlen( trajFilePath ) + 1 ); + strcpy( self->file_path, trajFilePath ); + + *vector3PairReader = self; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_read() + * + * Read one line of values from the trajectory file + *-----------------------------------------------------------------------*/ + +ivas_error Vector3PairFileReader_read( + Vector3PairFileReader *vector3PairReader, /* i/o: Vector3PairFileReader handle */ + IVAS_VECTOR3 *pFirst, /* o : first x,y,z position in the line */ + IVAS_VECTOR3 *pSecond /* o : second x,y,z position in the line */ +) +{ + float x1, y1, z1, x2, y2, z2; + + if ( vector3PairReader == NULL || pFirst == NULL || pSecond == NULL ) + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + + if ( 6 != fscanf( vector3PairReader->trajFile, "%f,%f,%f,%f,%f,%f", &x1, &y1, &z1, &x2, &y2, &z2 ) ) + { + if ( feof( vector3PairReader->trajFile ) ) + { + rewind( vector3PairReader->trajFile ); + return Vector3PairFileReader_read( vector3PairReader, pFirst, pSecond ); + } + return IVAS_ERR_FAILED_FILE_PARSE; + } + + pFirst->x = x1; + pFirst->y = y1; + pFirst->z = z1; + pSecond->x = x2; + pSecond->y = y2; + pSecond->z = z2; + + return IVAS_ERR_OK; +} + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_close() + * + * Deallocates memory for the Head-Tracking reader + *-----------------------------------------------------------------------*/ + +void Vector3PairFileReader_close( + Vector3PairFileReader **reader /* i/o: Vector3PairFileReader handle */ +) +{ + if ( reader == NULL || *reader == NULL ) + { + return; + } + + fclose( ( *reader )->trajFile ); + free( ( *reader )->file_path ); + free( *reader ); + *reader = NULL; + + return; +} + + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_getFilePath() + * + * + *-----------------------------------------------------------------------*/ + +const char *Vector3PairFileReader_getFilePath( + Vector3PairFileReader *reader /* i/o: Vector3PairFileReader handle */ +) +{ + if ( reader == NULL ) + { + return NULL; + } + + return reader->file_path; +} diff --git a/scripts/ivas_pytests/tests/unit_tests/crend/ivas_prox_mix.h b/lib_util/vector3_pair_file_reader.h similarity index 60% rename from scripts/ivas_pytests/tests/unit_tests/crend/ivas_prox_mix.h rename to lib_util/vector3_pair_file_reader.h index 8aa4b5713007eda8d72c05f64b9f8cb2b15909b3..4ab687848c25265bc08fc33a7f2d5e474516e25b 100644 --- a/scripts/ivas_pytests/tests/unit_tests/crend/ivas_prox_mix.h +++ b/lib_util/vector3_pair_file_reader.h @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -30,42 +30,58 @@ *******************************************************************************************************/ +#ifndef IVAS_V3PAIR_FILE_READER_H +#define IVAS_V3PAIR_FILE_READER_H -#ifndef IVAS_PROX_MIX_H -#define IVAS_PROX_MIX_H - -/**************************************************************************** -* File description - -* This header file contains declarations which are common between IVAS -* spatial decoding tools -****************************************************************************/ - -/*------------------------------------------------------------------------------------------* -* include header files -*------------------------------------------------------------------------------------------*/ -#include "stdio.h" -#include "stdlib.h" -#include "string.h" -#include "ivas_stat_dec.h" -#include "ivas_result_t.h" - -/*------------------------------------------------------------------------------------------* -* PreProcessor -*------------------------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------------------------* - * Global variables - *------------------------------------------------------------------------------------------*/ -#define LOC_BITSTREAM_DELIMITER ( 128 ) -#define MAX_BITSTREAM_LEN ( 128 ) -#define POWER_FACT ( 1.2f ) -#define POWER_SMOOTH_HI ( 0.8f ) -#define POWER_SMOOTH_LO ( 0.95f ) - -/*------------------------------------------------------------------------------------------* - * function declarations - *------------------------------------------------------------------------------------------*/ -ivas_result_t get_users_locations( uint8_t *bitstream, int32_t len, int16_t *userLoc ); -ivas_result_t get_prox_downmix_mixer( int16_t userID, float *pMixer, int16_t *userLoc, int32_t nChan, float ppPcm_in[][L_FRAME48k], int32_t frame_len, float *powvec ); - -#endif +#include "common_api_types.h" +#include "ivas_error.h" +#include "options.h" /* only included to get access to the feature-defines */ + + +typedef struct Vector3PairFileReader Vector3PairFileReader; + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_open() + * + * Allocate and initialize Head-Tracking handle + *-----------------------------------------------------------------------*/ + +ivas_error Vector3PairFileReader_open( + const char *trajFilePath, /* i : trajectory file name */ + Vector3PairFileReader **vector3PairReader /* o : Vector3PairFileReader handle */ +); + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_read() + * + * Read one line of values from the trajectory file + *-----------------------------------------------------------------------*/ + +ivas_error Vector3PairFileReader_read( + Vector3PairFileReader *vector3PairReader, /* i/o: Vector3PairFileReader handle */ + IVAS_VECTOR3 *pFirst, /* o : first x,y,z position in the line */ + IVAS_VECTOR3 *pSecond /* o : second x,y,z position in the line */ +); + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_close() + * + * Deallocates memory for the handle + *-----------------------------------------------------------------------*/ + +void Vector3PairFileReader_close( + Vector3PairFileReader **vector3PairReader /* i/o: Vector3PairFileReader handle */ +); + +/*-----------------------------------------------------------------------* + * Vector3PairFileReader_getFilePath() + * + * + *-----------------------------------------------------------------------*/ + +const char *Vector3PairFileReader_getFilePath( + Vector3PairFileReader *vector3PairReader /* i/o: Vector3PairFileReader handle */ +); + + +#endif /* IVAS_V3PAIR_FILE_READER_H */ diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000000000000000000000000000000000000..0cb53d22bb924dd5867a455a30ba395c324a59b6 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,16 @@ +# pytest.ini +# note: per convention, this file is placed in the root directory of the repository +[pytest] +# TODO remove ignore after tests are harmonized +addopts = -ra --tb=short --basetemp=./tmp -n auto -v --ignore=tests/renderer +# Write captured system-out log messages to JUnit report. +junit_logging = system-out +# Do not capture log information for passing tests to JUnit report. +junit_log_passing_tests = False +junit_duration_report = call +junit_family = xunit1 +log_file_level = DEBUG +log_format = %(asctime)s %(levelname)s %(message)s +log_date_format = %Y-%m-%d %H:%M:%S +# for pytest-html report: do not log environment variables from the runners +environment_table_redact_list = .* diff --git a/readme.txt b/readme.txt index 4d4de5864ae4ede8f600777ba144f0146819066d..c566c78ea233901d72fc367809458787ddc2e9fa 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -160,8 +160,13 @@ R : Bitrate in bps, *VBR mode (average bitrate), for AMR-WB IO modes R = (6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850) - for IVAS stereo & ISm R =(13200, 16400, 24400, 32000, 48000, 64000, 80000, - 96000, 128000, 160000, 192000, 256000) + for IVAS stereo R = (13200, 16400, 24400, 32000, 48000, 64000, 80000, + 96000, 128000, 160000, 192000, 256000) + for IVAS ISM R = 13200 for 1 ISM, 16400 for 1 ISM and 2 ISM, + (24400, 32000, 48000, 64000, 80000, 96000, 128000) + for 2 ISM, 3 ISM and 4 ISM also 160000, 192000, 256000 + for 3 ISM and 4 ISM also 384000 + for 4 ISM also 512000 for IVAS SBA, MASA, MC R=(13200, 16400, 24400, 32000, 48000, 64000, 80000, 96000, 128000, 160000, 192000, 256000, 384000, 512000) Alternatively, R can be a bitrate switching file which consists of R values @@ -176,16 +181,16 @@ Options: EVS mono is default, for IVAS choose one of the following: -stereo, -ism, -sba, -masa, -mc -stereo [Mode] : Stereo format, default is unified stereo optional for Mode: 1: DFT Stereo, 2: TD Stereo, 3: MDCT Stereo --ism Channels Files : ISm format - where Channels specifies the number of ISms (1-4) +-ism Channels Files : ISM format + where Channels specifies the number of ISMs (1-4) and Files specify input files containing metadata, one file per object (use NULL for no input metadata) -sba +/-Order : Scene Based Audio input format (Ambisonics ACN/SN3D), where Order specifies the Ambisionics order (1-3), where positive (+) means full 3D and negative (-) only 2D/planar components to be coded --masa Ch File : MASA format - where Ch specifies the number of input/transport channels (1 or 2): - and File specifies input file containing parametric metadata +-masa Channels File : MASA format + where Channels specifies the number of input/transport channels (1 or 2): + and File specifies input file containing parametric MASA metadata -mc InputConf : Multi-channel format where InputConf specifies the channel configuration: 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4 Loudspeaker positions are assumed to have azimuth and elevation as per @@ -195,8 +200,7 @@ EVS mono is default, for IVAS choose one of the following: -stereo, -ism, -sba, where 0 = adaptive, 3-100 = fixed in number of frames, default is deactivated -dtx : Activate DTX mode with a SID update rate of 8 frames - Note: DTX is currently supported in EVS, DFT/TD stereo, 1 ISm, - SBA (up to 128kbps) and MASA (up to 128kbps) + Note: DTX is supported in EVS, stereo, ISM, SBA up to 80kbps and MASA up to 128kbps -rf p o : Activate channel-aware mode for WB and SWB signal at 13.2kbps, where FEC indicator, p: LO or HI, and FEC offset, o: 2, 3, 5, or 7 in number of frames. Alternatively p and o can be replaced by a rf configuration file with each line @@ -251,22 +255,26 @@ Options: Format files, the magic word in the mime file is used to determine which of the two supported formats is in use. default bitstream file format is G.192 --T File : Head rotation specified by external trajectory File -hrtf File : HRTF filter File used in ISm format and BINAURAL output configuration --force_subframe_bin : Forces parametric binauralizer code to use 5 ms time resolution even when - output time resolution is larger. +-T File : Head rotation specified by external trajectory File +-otr tracking_type : Head orientation tracking type: 'none', 'ref', 'avg', 'ref_vec' + or 'ref_vec_lev' (only for binaural rendering) +-rf File : Reference rotation specified by external trajectory file + works only in combination with '-otr ref' mode +-rvf File : Reference vector specified by external trajectory file + works only in combination with '-otr ref_vec' and 'ref_vec_lev' modes +-render_config File : Renderer configuration option File +-no_diegetic_pan : panning mono non-diegetic sound to stereo -1<= pan <=1, + left or l or 1->left, right or r or -1->right, center or c or 0->middle +-q : Quiet mode, no frame counter + default is deactivated -FEC X : Insert frame erasures, X = 0-10 is the percentage of erased frames, or X may be the name of binary file or file with G192 headers indicating GOOD FRAME or BAD FRAME containing FEC pattern (short values of 0 (good) or 1 (bad)) default is OFF, if this option is not used -force R : Force specific binaural rendering mode, R = (TDREND, CLDFBREND), --otr tracking_type : head orientation tracking type: 'ref' or 'avg' (only for binaural rendering) --render_config File : Renderer configuration option File --no_diegetic_pan : panning mono no dietic sound to stereo -1<= pan <=1, - left or l or 1->left, right or r or -1->right, center or c or 0->middle --q : Quiet mode, no frame counter - default is deactivated + MULTICHANNEL LOUDSPEAKER INPUT / OUTPUT CONFIGURATIONS @@ -294,6 +302,7 @@ The output channel ordering is 0, 1, ... N-1. The third row contains an index "L specifying the output channel to which the LFE input will be routed if present. If the third row is omitted, the LFE input is downmixed to all channels with a factor of 1/N. Position is not considered for the LFE channel. +An example custom loudspeaker layout file is available: ls_setup_16ch_8+4+4.txt @@ -308,55 +317,56 @@ points or complete coverage. Documentation on the self_test.py can be found as a part of scripts/README.md. -Note: Running the self_test.py requires the input vectors in the folder scripts/testv. The -audio files could unfortunately not be shared, and they need to be replaced in order to -run the self_test.py. To complement the test vector set, please replace the empty *.pcm-files -in the self_test folder with 16 bit PCM files following the specification below. - -stv1ISM48s.pcm - 1 channel (1 audio object), 48000 Hz, 1440000 samples -stv2ISM48s.pcm - 2 channels (discrete audio objects), 48000 Hz, 1440000 samples per channel -stv2OA32c.pcm - 9 channels (2nd order Ambisonics ACN/SN3D), 32000 Hz -stv2OA48c.pcm - 9 channels (2nd order Ambisonics ACN/SN3D), 48000 Hz -stv3ISM48s.pcm - 3 channels (discrete audio objects), 48000 Hz, 1440000 samples per channel -stv3OA32c.pcm - 16 channels (3rd order Ambisonics ACN/SN3D), 32000 Hz, 288939 samples per channel -stv3OA48c.pcm - 16 channels (3rd order Ambisonics ACN/SN3D), 48000 Hz, 433408 samples per channel -stv4ISM48s.pcm - 4 channel (discrete audio objects), 48000 Hz, 1440000 samples per channel -stv8c.pcm - 1 channel, 8000 Hz, clean speech/audio -stv8n.pcm - 1 channel, 8000 Hz, noisy speech -stv16c.pcm - 1 channel, 16000 Hz, 610307 samples, clean speech -stv16n.pcm - 1 channel, 16000 Hz, 257024 samples, noisy speech -stv32c.pcm - 1 channel, 32000 Hz, 1220613 samples, clean speech/audio -stv32n.pcm - 1 channel, 32000 Hz, 514048 samples, noisy speech -stv48c.pcm - 1 channel, 48000 Hz, 1830919 samples, clean speech/audio -stv51MC48c.pcm - 6 channels (5.1 1..6 where 4th channel is LFE), 3231233 samples per channel, 48000 Hz, movie excerpt -stv512MC48c.pcm - 8 channels (5.1+2 1..8 where 4th channel is LFE), 144000 samples per channel, 48000 Hz, movie excerpt -stv714MC48c.pcm - 12 channels (7.1+4 1..12 where 4th channel is LFE), 144000 samples per channel, 48000 Hz, movie excerpt -stvFOA16c.pcm - 4 channels (1st order Ambisonics ACN/SN3D), 16000 Hz, -stvFOA32c.pcm - 4 channels (1st order Ambisonics ACN/SN3D), 32000 Hz, 288939 samples per channel -stvFOA48c.pcm - 4 channels (1st order Ambisonics ACN/SN3D), 48000 Hz, 433408 samples per channel -stvST16c.pcm - 2 channels, 16000 Hz, 329601 samples per channel, clean speech/audio -stvST16n.pcm - 2 channels, 16000 Hz, 310401 samples per channel, noisy speech -stvST32c.pcm - 2 channels, 32000 Hz, 659200 samples per channel, clean speech/audio -stvST32n.pcm - 2 channels, 32000 Hz, 620800 samples per channel, noisy speech -stvST48c.pcm - 2 channels, 48000 Hz, 988800 samples per channel, clean speech/audio -stvST48n.pcm - 2 channels, 48000 Hz, 931200 samples per channel, noisy speech -stv_IVASMASA_1dir1TC.pcm - 1 channel (1 MASA transport channel), 48000 Hz, 48000 Hz, 144000 samples -stv_IVASMASA_1dir1TC_DTX.pcm - 1 channel (1 MASA transport channel), 48000 Hz, 48000 Hz, 963840 samples -stv_IVASMASA_1dir2TC.pcm - 2 channels (2 MASA transport channel), 48000 Hz, 48000 Hz, 288000 samples per channel -stv_IVASMASA_1dir2TC_DTX.pcm - 2 channels (2 MASA transport channel), 48000 Hz, 48000 Hz, 963840 samples per channel -stv_IVASMASA_2dir1TC.pcm - 1 channel (1 MASA transport channel), 48000 Hz, 48000 Hz, 288000 -stv_IVASMASA_2dir2TC.pcm - 2 channels (2 MASA transport channel), 48000 Hz, 48000 Hz, 144000 samples per channel +Note: Running the self_test.py requires the input vectors in the folder scripts/testv. + +stv1ISM48s.wav - 1 channel (1 audio object), 48000 Hz, 1440000 samples +stv2ISM48s.wav - 2 channels (discrete audio objects), 48000 Hz, 1440000 samples per channel +stv2OA32c.wav - 9 channels (2nd order Ambisonics ACN/SN3D), 32000 Hz +stv2OA48c.wav - 9 channels (2nd order Ambisonics ACN/SN3D), 48000 Hz +stv3ISM48s.wav - 3 channels (discrete audio objects), 48000 Hz, 1440000 samples per channel +stv3OA32c.wav - 16 channels (3rd order Ambisonics ACN/SN3D), 32000 Hz, 288939 samples per channel +stv3OA48c.wav - 16 channels (3rd order Ambisonics ACN/SN3D), 48000 Hz, 433408 samples per channel +stv4ISM48s.wav - 4 channel (discrete audio objects), 48000 Hz, 1440000 samples per channel +stv4ISM48n.wav - 4 channel (discrete audio objects), 48000 Hz, noisy speech +stv8c.wav - 1 channel, 8000 Hz, clean speech/audio +stv8n.wav - 1 channel, 8000 Hz, noisy speech +stv16c.wav - 1 channel, 16000 Hz, 610307 samples, clean speech +stv16n.wav - 1 channel, 16000 Hz, 257024 samples, noisy speech +stv32c.wav - 1 channel, 32000 Hz, 1220613 samples, clean speech/audio +stv32n.wav - 1 channel, 32000 Hz, 514048 samples, noisy speech +stv48c.wav - 1 channel, 48000 Hz, 960000 samples, clean speech/audio +stv48n.wav - 1 channel, 48000 Hz, 931200 samples, noisy clean speech +stv51MC48c.wav - 6 channels (5.1 1..6 where 4th channel is LFE), 960000 samples per channel, 48000 Hz +stv512MC48c.wav - 8 channels (5.1+2 1..8 where 4th channel is LFE), 144000 samples per channel, 48000 Hz +stv514MC48c.wav - 10 channels (7.1+2 1..10 where 4th channel is LFE), 144000 samples per channel, 48000 Hz +stv71MC48c.wav - 8 channels (7.1 1..8 where 4th channel is LFE), 144000 samples per channel, 48000 Hz +stv714MC48c.wav - 12 channels (7.1+4 1..12 where 4th channel is LFE), 144000 samples per channel, 48000 Hz +stvFOA16c.wav - 4 channels (1st order Ambisonics ACN/SN3D), 16000 Hz, +stvFOA32c.wav - 4 channels (1st order Ambisonics ACN/SN3D), 32000 Hz, 288939 samples per channel +stvFOA48c.wav - 4 channels (1st order Ambisonics ACN/SN3D), 48000 Hz, 433408 samples per channel +stvST16c.wav - 2 channels, 16000 Hz, 329601 samples per channel, clean speech/audio +stvST16n.wav - 2 channels, 16000 Hz, 310401 samples per channel, noisy speech +stvST32c.wav - 2 channels, 32000 Hz, 659200 samples per channel, clean speech/audio +stvST32n.wav - 2 channels, 32000 Hz, 620800 samples per channel, noisy speech +stvST48c.wav - 2 channels, 48000 Hz, 988800 samples per channel, clean speech/audio +stvST48n.wav - 2 channels, 48000 Hz, 931200 samples per channel, noisy speech +stv1MASA1TC48c.wav - 1 channel (1 MASA transport channel), 48000 Hz, 48000 Hz, 144000 samples +stv1MASA1TC48n.wav - 1 channel (1 MASA transport channel), 48000 Hz, 48000 Hz, 963840 samples +stv1MASA2TC48c.wav - 2 channels (2 MASA transport channel), 48000 Hz, 48000 Hz, 288000 samples per channel +stv1MASA2TC48n.wav - 2 channels (2 MASA transport channel), 48000 Hz, 48000 Hz, 963840 samples per channel +stv2MASA1TC48c.wav - 1 channel (1 MASA transport channel), 48000 Hz, 48000 Hz, 288000 +stv2MASA2TC48c.wav - 2 channels (2 MASA transport channel), 48000 Hz, 48000 Hz, 144000 samples per channel For the MASA operation modes, in addition the following metadata files are required: -stv_IVASMASA_1dir1TC.met -stv_IVASMASA_1dir1TC_DTX.met -stv_IVASMASA_1dir2TC.met -stv_IVASMASA_1dir2TC_DTX.met -stv_IVASMASA_2dir1TC.met -stv_IVASMASA_2dir2TC.met +stv1MASA1TC48c.met +stv1MASA1TC48n.met +stv1MASA2TC48c.met +stv1MASA2TC48n.met +stv2MASA1TC48c.met +stv2MASA2TC48c.met It is strongly recommended to align these files to the corresponding PCM audio files. The MASA metadata files can be generated with the @@ -374,23 +384,37 @@ stvISM4.csv These are comma separated files (csv) which indicate the per object position in the format: -frame index, azimuth, elevation, distance (unit circle), spread, gain +frame azimuth, elevation, distance (unit circle), spread, gain with the following meaning: | Parameter | format, value range | meaning ----------------------------------------------------------------------- -| frame index | int, [0, INT_MAX] | associated IVAS frame ----------------------------------------------------------------------- +----------------------------------------------------------------------------------- | azimuth | float, [-180,180[ | azimuth; positive indicates left ----------------------------------------------------------------------- +----------------------------------------------------------------------------------- | elevation | float, [-90,90] | elevation; positive indicates up ----------------------------------------------------------------------- -| distance | float, tbd | default: 0 ----------------------------------------------------------------------- -| spread | float, [0,360] | spread in angles from 0 ... 360ø ----------------------------------------------------------------------- -| gain | float, [0,1] | gain ----------------------------------------------------------------------- +----------------------------------------------------------------------------------- +| distance | float, tbd | distance; default: 1 +----------------------------------------------------------------------------------- +| spread | float, [0,360] | spread in angles from 0...360 deg; default: 0 +----------------------------------------------------------------------------------- +| gain | float, [0,1] | gain; default: 1 +----------------------------------------------------------------------------------- + + +For the Head rotation operation modes, external trajectory files are available: + +headrot.csv +headrot_case00_3000_q.csv +headrot_case01_3000_q.csv +headrot_case02_3000_q.csv +headrot_case03_3000_q.csv + + +For the Renderer configuration option operation modes, external configuration files are available: + +rend_config_hospital_patientroom.cfg +config_recreation.cfg +config_renderer.cfg ADDITIONAL SCRIPTS diff --git a/scripts/IvasBuildAndRun.py b/scripts/IvasBuildAndRun.py index 9053d55291878d5df10e2293b4aef359fdb57d08..554c216b184eb47331ffbad3947ad767ae16d17f 100755 --- a/scripts/IvasBuildAndRun.py +++ b/scripts/IvasBuildAndRun.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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/scripts/IvasBuildAndRunChecks.py b/scripts/IvasBuildAndRunChecks.py index fe1953a6030a99fbd9af431ff374cee97d41dbc1..f32ade77733d567f2dd235dea577d781383785f1 100755 --- a/scripts/IvasBuildAndRunChecks.py +++ b/scripts/IvasBuildAndRunChecks.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ - (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2023 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 @@ -36,7 +36,9 @@ import sys from pyivastest.IvasSvnBuilder import * from pyivastest import IvasScriptsCommon import pyivastest.constants as constants -from pyivastest import ivas_svn + + +RET_CODE_FAILURE = 101 class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): @@ -169,14 +171,10 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): for check in checks: br.run(check) if self.args["create_html_output"]: - revision = ivas_svn.get_local_svn_info(self.args["srcdir"], self.logger) - if revision is None: - print("Could not get revision from local copy") - revision = -1 - else: - revision = revision["commit_revision"] + cmd = ["git", "rev-parse", "HEAD"] + commit_hash = subprocess.run(cmd, capture_output=True).stdout.decode("utf8") br.build_and_run_dict[check]["analyzer"].write_html_file( - check, self.args["create_html_output"], revision + check, self.args["create_html_output"], commit_hash ) for r in br.build_and_run_dict[check]["runner"].results: self.logger.console(r[0]) @@ -195,7 +193,16 @@ class IvasBuildAndRunChecks(IvasScriptsCommon.IvasScript): self.args["create_complexity_tables"] ) + returncode = 0 + for check in checks: + runner = br.build_and_run_dict[check]["runner"] + failed_encs = runner.failed_modes["enc"] + failed_decs = runner.failed_modes["dec"] + if len(failed_encs) > 0 or len(failed_decs) > 0: + returncode = RET_CODE_FAILURE + + return returncode if __name__ == "__main__": script = IvasBuildAndRunChecks() - script.run() + sys.exit(script.run()) diff --git a/scripts/README.md b/scripts/README.md index 7264ccf7a54d8463d4f0a2d09356800b6f5326e8..fec54ffeac8a7929b329d55ecb72641eb79b0e22 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,6 +1,6 @@