Commit 280b4d23 authored by Marek Szczerba's avatar Marek Szczerba
Browse files

Merge branch 'main' into 777-render-config-reader-fails-to-read-combined-config-file-test-cases

parents 965ba198 6ca9e7d1
Loading
Loading
Loading
Loading
Loading
+225 −71
Original line number Diff line number Diff line
@@ -20,7 +20,10 @@ variables:
      - 'default'
      - 'test-be-release'
      - 'test-long-self-test'
      - 'ivas-conformance'
  GIT_CLEAN_FLAGS: -ffdxq
  TESTCASE_TIMEOUT_STV_SANITIZERS: 180
  TESTCASE_TIMEOUT_LTV_SANITIZERS: 1200


default:
@@ -51,6 +54,9 @@ workflow:
    - if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'test-long-self-test'
      variables:
        IVAS_PIPELINE_NAME: 'Test long self-test against main pipeline: $CI_COMMIT_BRANCH'
    - if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'ivas-conformance'
      variables:
        IVAS_PIPELINE_NAME: 'Draft IVAS Conformance test: $CI_COMMIT_BRANCH'        
    - if: $CI_PIPELINE_SOURCE == 'trigger'

stages:
@@ -182,6 +188,18 @@ stages:
  - (Get-Content -Path "CMakeLists.txt") -replace '# \(add_compile_options\("\/WX"\)\)', '$1' | Set-Content -Path "CMakeLists.txt"
  - Get-ChildItem -Path "Workspace_msvc" -Filter "*.vcxproj" | ForEach-Object { (Get-Content -Path $_.FullName) -replace '<TreatWarningAsError>false', '<TreatWarningAsError>true' | Set-Content -Path $_.FullName }

# to be reused in MR and LTV-scheduled sanitizer test jobs
# set CLANG_NUM, SELFTEST_SANITY_TIMEOUT and SELF_TEST_PRM_FILE in before_script section
.sanitizer-selftest-anchor: &sanitizer-selftest-anchor
  script:
    - *print-common-info
    - *copy-ltv-files-to-testv-dir
    - make clean
    - make -j CLANG=$CLANG_NUM
    - testcase_timeout=$SELFTEST_SANITY_TIMEOUT
    - UBSAN_OPTIONS=suppressions=scripts/ubsan.supp,report_error_type=1 python3 -m pytest $SELF_TEST_PRM_FILE -v --update_ref 1 -m create_ref --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout=$testcase_timeout --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec


# ---------------------------------------------------------------
# Job templates
# ---------------------------------------------------------------
@@ -203,6 +221,8 @@ stages:
      when: never
    - if: $MANUAL_PIPELINE_TYPE == 'test-long-self-test' # Skip all the normal jobs when testing manually against release codec
      when: never
    - if: $MANUAL_PIPELINE_TYPE == 'ivas-conformance'
      when: never      
    - when: on_success

.rules-merge-request:
@@ -249,6 +269,39 @@ stages:
    - python3 scripts/prepare_combined_format_inputs.py
    - cp -r scripts/testv/* $TESTV_DIR/

.sanitizer-selftest-on-mr:
  stage: test
  extends:
    - .test-job-linux-needs-testv-dir
    - .rules-merge-request
  artifacts:
    name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results"
    expire_in: 1 week
    when: always
    paths:
      - report-junit.xml
      - report.html
    expose_as: "Sanitizer selftest results"
    reports:
      junit:
        - report-junit.xml

.sanitizer-selftest-ltv:
  stage: test
  extends:
    - .test-job-linux-needs-testv-dir
  artifacts:
    name: "$CI_JOB_NAME--sha-$CI_COMMIT_SHORT_SHA--results"
    expire_in: 2 week
    when: always
    paths:
      - report-junit.xml
      - report.html
    expose_as: "Sanitizer selftest results"
    reports:
      junit:
        - report-junit.xml

# ---------------------------------------------------------------
# .pre jobs for setting up things
# ---------------------------------------------------------------
@@ -399,7 +452,7 @@ build-codec-windows-msbuild:
  script:
    - *print-common-info-windows
    - *activate-WX-windows
    - py .\scripts\strip_split_rendering.py
    - python .\scripts\strip_split_rendering.py
    - MSBuild.exe -maxcpucount .\Workspace_msvc\Workspace_msvc.sln /property:Configuration=Debug

# ---------------------------------------------------------------
@@ -443,83 +496,32 @@ codec-smoke-test:
# code selftest testvectors with memory-sanitizer binaries
codec-msan:
  extends:
    - .test-job-linux-needs-testv-dir
    - .rules-merge-request
  stage: test
  needs: ["build-codec-sanitizers-linux"]
  script:
    - *print-common-info
    - make clean
    - make -j CLANG=1
    - testcase_timeout=180
    - exit_code=0
    - python3 -m pytest tests/codec_be_on_mr_nonselection/test_param_file.py -v --update_ref 1 -m create_ref --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout=$testcase_timeout --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec || exit_code=$?
    - if [ $exit_code != 0 ] ; then echo "Run errors found by Clang memory-sanitizer"; exit 1; fi
  artifacts:
    name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results"
    expire_in: 1 week
    when: always
    paths:
      - report-junit.xml
      - report.html
    expose_as: "msan selftest results"
    reports:
      junit:
        - report-junit.xml
    - .sanitizer-selftest-on-mr
  before_script:
    - CLANG_NUM=1
    - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS
    - SELF_TEST_PRM_FILE="tests/codec_be_on_mr_nonselection/test_param_file.py"
  <<: *sanitizer-selftest-anchor

# code selftest testvectors with address-sanitizer binaries
codec-asan:
  extends:
    - .test-job-linux-needs-testv-dir
    - .rules-merge-request
  stage: test
  needs: ["build-codec-sanitizers-linux"]
  script:
    - *print-common-info
    - make clean
    - make -j CLANG=2
    - testcase_timeout=180
    - exit_code=0
    - python3 -m pytest tests/codec_be_on_mr_nonselection/test_param_file.py -v --update_ref 1 -m create_ref --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout=$testcase_timeout --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec || exit_code=$?
    - if [ $exit_code != 0 ] ; then echo "Run errors found by Clang address-sanitizer"; exit 1; fi
  artifacts:
    name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results"
    expire_in: 1 week
    when: always
    paths:
      - report-junit.xml
      - report.html
    expose_as: "asan selftest results"
    reports:
      junit:
        - report-junit.xml
    - .sanitizer-selftest-on-mr
  before_script:
    - CLANG_NUM=2
    - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS
    - SELF_TEST_PRM_FILE="tests/codec_be_on_mr_nonselection/test_param_file.py"
  <<: *sanitizer-selftest-anchor

# code selftest testvectors with address-sanitizer binaries
# code selftest testvectors with undefined-behaviour-sanitizer binaries
codec-usan:
  extends:
    - .test-job-linux-needs-testv-dir
    - .rules-merge-request
  stage: test
  needs: ["build-codec-sanitizers-linux"]
  script:
    - *print-common-info
    - make clean
    - make -j CLANG=3
    - testcase_timeout=180
    - exit_code=0
    - UBSAN_OPTIONS=suppressions=scripts/ubsan.supp,report_error_type=1 python3 -m pytest tests/codec_be_on_mr_nonselection/test_param_file.py -v --update_ref 1 -m create_ref --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout=$testcase_timeout --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec || exit_code=$?
    - if [ $exit_code != 0 ] ; then echo "Run errors found by Clang undefined-behavior-sanitizer"; exit 1; fi
  artifacts:
    name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results"
    expire_in: 1 week
    when: always
    paths:
      - report-junit.xml
      - report.html
    expose_as: "usan selftest results"
    reports:
      junit:
        - report-junit.xml
    - .sanitizer-selftest-on-mr
  before_script:
    - CLANG_NUM=3
    - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS
    - SELF_TEST_PRM_FILE="tests/codec_be_on_mr_nonselection/test_param_file.py"
  <<: *sanitizer-selftest-anchor

# test renderer executable
renderer-smoke-test:
@@ -1044,6 +1046,29 @@ lc3plus-ensure-no-code-changes:
    - modified_files=$(git status -s)
    - if [[ $modified_files ]]; then printf 'LC3plus codebase was modified!\n\n'"$modified_files"'\n\n'; exit $EXIT_CODE_FAIL; fi

check-bitexactness-hrtf-rom-and-file:
  extends:
    - .test-job-linux
    - .rules-merge-request
  stage: test
  needs: ["build-codec-linux-cmake"]
  timeout: "5 minutes"
  script:
    - *print-common-info
    - cmake .
    - make -j
    - python3 tests/create_short_testvectors.py --which all --cut_len 1.0
    - python3 -m pytest tests/hrtf_binary_loading --html=report.html --junit-xml=report-junit.xml --self-contained-html
  artifacts:
    paths:
      - report.html
      - report-junit.xml
    when: always
    name: "$CI_JOB_NAME--$CI_MERGE_REQUEST_ID--sha-$CI_COMMIT_SHA--hrtf-loading"
    expose_as: "logs-hrtf-loading"
    expire_in: "5 days"


# ---------------------------------------------------------------
# Test jobs for main branch
# ---------------------------------------------------------------
@@ -1215,6 +1240,85 @@ test-be-to-release:
    expose_as: "test-be-to-release results"


ivas-conformance:
  tags:
    - ivas-windows
  stage: test
  timeout: "60 minutes"
  rules:
    - if: ($CI_PIPELINE_SOURCE == 'web' || $CI_PIPELINE_SOURCE == 'trigger') && $MANUAL_PIPELINE_TYPE == 'ivas-conformance'
  allow_failure:
    exit_codes:
      - 123
  script:
    - *print-common-info-windows
    # Prepare reference exec, use tests and scripts from reference
    - $source_branch_commit_sha = $(git rev-parse HEAD)
    - git checkout main # This should be set to a relevant reference
    - python .\scripts\strip_split_rendering.py
    - MSBuild.exe -maxcpucount .\Workspace_msvc\Workspace_msvc.sln /property:Configuration=Debug    
    - cp -force IVAS_cod.exe IVAS_cod_ref.exe
    - cp -force IVAS_dec.exe IVAS_dec_ref.exe
    - cp -force IVAS_rend.exe IVAS_rend_ref.exe
    - git restore .
    - git checkout $source_branch_commit_sha
    
    # Reference creation
    - python tests/create_short_testvectors.py
    - python scripts/prepare_combined_format_inputs.py
    - python -m pytest tests/codec_be_on_mr_nonselection -v -n auto --update_ref 1 -m create_ref --keep_files
    - python -m pytest tests/codec_be_on_mr_nonselection -v -n auto --update_ref 1 -m create_ref_part2 --keep_files
    - python -m pytest tests/renderer/test_renderer.py --create_ref --keep_files

    # Output creation
    - python -m pytest tests/codec_be_on_mr_nonselection tests/renderer/test_renderer.py -v -n auto --keep_files --create_cut --html=report_cmd.html --self-contained-html
    - python scripts/parse_commands.py report_cmd.html Readme_IVAS.txt
    
    # Copy input data and output ref data
    - if (Test-Path testvec) {rm -r -force testvec}
    - mkdir testvec
    - mkdir testvec/binauralRenderer_interface
    - mkdir testvec/testv
    - mkdir testvec/testv/renderer
    - mkdir testvec/bin    
    - cp -r -force -ErrorAction Ignore scripts/testv/* testvec/testv
    - cp -r -force -ErrorAction Ignore scripts/ls_layouts testvec
    - cp -r -force -ErrorAction Ignore scripts/switchPaths testvec
    - cp -r -force -ErrorAction Ignore scripts/trajectories testvec
    - cp -r -force -ErrorAction Ignore scripts/binauralRenderer_interface/binaural_renderers_hrtf_data testvec/binauralRenderer_interface
    - cp -r -force -ErrorAction Ignore tests/ref testvec/testv/ref
    - cp -r -force -ErrorAction Ignore tests/dut/* testvec/testv/ref
    - cp -r -force -ErrorAction Ignore tests/renderer/cut testvec/testv/renderer/ref
    - cp -r -force -ErrorAction Ignore tests/conformance-test testvec/
    - cp Readme_IVAS_dec.txt testvec
    - cp Readme_IVAS_enc.txt testvec 
    - cp Readme_IVAS_rend.txt testvec
    - cp Readme_IVAS_JBM_dec.txt testvec
    - cp IVAS_cod.exe testvec/bin
    - cp IVAS_dec.exe testvec/bin
    - cp IVAS_rend.exe testvec/bin
    
    # Test run generated scripts in testvec
    - cd testvec    
    - python -m pytest conformance-test/test_26252.py --junit-xml=report-junit.xml --html=report.html --self-contained-html
    - mv report.html ..
    - mv report-junit.xml ..

  artifacts:
    name: "ivas-conformance-$CI_COMMIT_SHORT_SHA"
    expire_in: 1 week
    when: always
    paths:
      - report-junit.xml
      - report.html
      - Readme_IVAS_dec.txt  
      - Readme_IVAS_enc.txt  
      - Readme_IVAS_rend.txt
      - Readme_IVAS_JBM_dec.txt
    expose_as: "Draft IVAS conformance"
    reports:
      junit: report-junit.xml

test-long-self-test:
  tags:
    - ivas-linux-fast
@@ -1289,6 +1393,56 @@ test-long-self-test:
# ---------------------------------------------------------------
# Scheduled jobs on main
# ---------------------------------------------------------------

# code selftest long testvectors with memory-sanitizer binaries
ltv-msan:
  extends:
    - .sanitizer-selftest-ltv
  rules:
    - if: $SANITIZER_SCHEDULE_E
  timeout: 1 hour
  tags:
    - ivas-linux-fast
  before_script:
    - CLANG_NUM=1
    - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS
    - SELF_TEST_PRM_FILE="tests/test_param_file_ltv.py"
  <<: *sanitizer-selftest-anchor

# code selftest long testvectors with address-sanitizer binaries
ltv-asan:
  extends:
    - .sanitizer-selftest-ltv
  rules:
    - if: $SANITIZER_SCHEDULE_E
      when: delayed
      start_in: 1 hours
  tags:
    - ivas-linux-fast
  timeout: 1 hour
  before_script:
    - CLANG_NUM=2
    - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS
    - SELF_TEST_PRM_FILE="tests/test_param_file_ltv.py"
  <<: *sanitizer-selftest-anchor

# code selftest long testvectors with undefined-behaviour-sanitizer binaries
ltv-usan:
  extends:
    - .sanitizer-selftest-ltv
  rules:
    - if: $SANITIZER_SCHEDULE_E
      when: delayed
      start_in: 2 hours
  tags:
    - ivas-linux-fast
  timeout: 1 hour
  before_script:
    - CLANG_NUM=3
    - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS
    - SELF_TEST_PRM_FILE="tests/test_param_file_ltv.py"
  <<: *sanitizer-selftest-anchor

.sanitizer-test-template:
  extends:
    - .test-job-linux
+39 −0
Original line number Diff line number Diff line
### Basic info

- Commit SHA: 

### Bug description

Clang ASAN sanitizer test in pipeline found an error:

<!--- Copy sanitizer traceback from command line here -->
```

```

<!--- Copy test job URL here -->
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):
<!--- check correct sanitizer type -->
<!--- add error pattern if needed -->
```
python3 scripts/IvasBuildAndRunChecks.py --checks CLANG2 -m MODE -p /path/to/my/local/ci_linux_ltv_local.json
```
or directly:

```
make clean
make -j CLANG=2
./IVAS_cod ...
networkSimulator_g192 dly_profile.dat bit bit_err trace_dump 1
./IVAS_dec ...
```

<!--- Below are labels that will be added but are not shown in description. This is a template to help fill them.
      Add further information to the first row and remove and add labels as necessary.  -->

/label ~"Priority::Critical" ~Company: ~Subpart:
/label ~Type:Bug ~Status::ToDo
+46 −0
Original line number Diff line number Diff line
### Basic info

- Commit SHA: 

### Bug description

Clang MSAN sanitizer test in pipeline found an error:

<!--- Copy sanitizer traceback from command line here -->
```

```

<!--- Copy test job URL here -->
Link to test pipeline: XXX

### Ways to reproduce

Activate [origin-tracking](https://clang.llvm.org/docs/MemorySanitizer.html#msan-origins) (more detailed traceback about where the undefined value came from) by appending
```
 -fsanitize-memory-track-origins
```
in the `Makefile` at lines 71 and 72. Note that this may increase runtime heavily.

Using the [scripts](https://forge.3gpp.org/rep/ivas-codec-pc/ivas-codec/-/wikis/Software-development/pyivastest-howto#how-to-reproduce-tests):
<!--- check correct sanitizer type -->
<!--- add error pattern if needed -->

```
python3 scripts/IvasBuildAndRunChecks.py --checks CLANG1 -m MODE -p /path/to/my/local/ci_linux_ltv_local.json
```
or directly:

```
make clean
make -j CLANG=1
./IVAS_cod ...
networkSimulator_g192 dly_profile.dat bit bit_err trace_dump 1
./IVAS_dec ...
```

<!--- Below are labels that will be added but are not shown in description. This is a template to help fill them.
      Add further information to the first row and remove and add labels as necessary.  -->

/label ~"Priority::Critical" ~Company: ~Subpart:
/label ~Type:Bug ~Status::ToDo
+4 −4
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

### Bug description

Clang (m,a,u)san sanitizer test in pipeline found an error:
Clang USAN sanitizer test in pipeline found an error:

<!--- Copy sanitizer traceback from command line here -->
```
@@ -20,15 +20,15 @@ Using the [scripts](https://forge.3gpp.org/rep/ivas-codec-pc/ivas-codec/-/wikis/
<!--- check correct sanitizer type -->
<!--- add error pattern if needed -->
```
python3 scripts/IvasBuildAndRunChecks.py --checks CLANGX -m MODE -p /path/to/my/local/ci_linux_ltv_local.json --usan_supp_file scripts/ubsan.supp
python3 scripts/IvasBuildAndRunChecks.py --checks CLANG3 -m MODE -p /path/to/my/local/ci_linux_ltv_local.json --usan_supp_file scripts/ubsan.supp
```
or directly:

```
make clean
make -j CLANG=X
make -j CLANG=3
./IVAS_cod ...
eid-xor -vbr -fer bit ep_015.g192 bit_fer
networkSimulator_g192 dly_profile.dat bit bit_err trace_dump 1
./IVAS_dec ...
```

+94 −33
Original line number Diff line number Diff line
@@ -455,14 +455,9 @@ int main(
     *------------------------------------------------------------------------------------------*/

#ifdef SPLIT_REND_WITH_HEAD_ROT
#ifdef SPLIT_REND_LCLD_5MS
    asked_frame_size = arg.renderFramesize;
#endif
    if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM )
    {
#ifndef SPLIT_REND_LCLD_5MS
        asked_frame_size = arg.renderFramesize;
#endif
        if ( ( error = IVAS_DEC_EnableSplitRendering( hIvasDec ) ) != IVAS_ERR_OK )
        {
            fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) );
@@ -475,12 +470,6 @@ int main(
            goto cleanup;
        }

#ifndef SPLIT_REND_LCLD_5MS
        if ( arg.renderFramesize != asked_frame_size )
        {
            fprintf( stderr, "\nChanged render framesize, only 20ms are allowed for split rendering!\n" );
        }
#endif
        arg.enableHeadRotation = true;
    }
#endif
@@ -633,26 +622,6 @@ int main(
            goto cleanup;
        }

#ifdef SPLIT_REND_WITH_HEAD_ROT
#ifndef SPLIT_REND_LCLD_5MS
        if ( arg.renderFramesize == IVAS_RENDER_FRAMESIZE_5MS && ( renderConfig.split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE ||
                                                                   renderConfig.split_rend_config.dof == 0 ) )
        {
            /*TODO : needs to be refined as this wont work with LCLD codec*/
            arg.renderFramesize = IVAS_RENDER_FRAMESIZE_5MS;
        }
        else
        {
            arg.renderFramesize = IVAS_RENDER_FRAMESIZE_20MS;
        }

        if ( ( error = IVAS_DEC_SetRenderFramesize( hIvasDec, arg.renderFramesize ) ) != IVAS_ERR_OK )
        {
            return error;
        }

#endif
#endif
        if ( RenderConfigReader_read( renderConfigReader, arg.renderConfigFilename, &renderConfig ) != IVAS_ERR_OK )
        {
            fprintf( stderr, "Failed to read renderer configuration from file %s\n\n", arg.renderConfigFilename );
@@ -665,7 +634,6 @@ int main(
            goto cleanup;
        }

#ifdef SPLIT_REND_LCLD_5MS
#ifdef SPLIT_REND_WITH_HEAD_ROT
        if ( asked_frame_size != IVAS_RENDER_FRAMESIZE_20MS && ( renderConfig.split_rend_config.poseCorrectionMode == IVAS_SPLIT_REND_POSE_CORRECTION_MODE_NONE ||
                                                                 renderConfig.split_rend_config.dof == 0 ) )
@@ -686,7 +654,6 @@ int main(
        {
            fprintf( stderr, "\nChanged render framesize, only 20ms are allowed for non-0dof split rendering!\n" );
        }
#endif
#endif

        if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB )
@@ -3425,7 +3392,14 @@ static ivas_error decodeVoIP(
        }
        vec_pos_update = ( vec_pos_update + 1 ) % vec_pos_len;
        frame++;
#ifdef NONBE_FIX_864_JBM_RENDER_FRAMESIZE
        if ( vec_pos_update == 0 )
        {
            systemTime_ms += vec_pos_len * systemTimeInc_ms;
        }
#else
        systemTime_ms += systemTimeInc_ms;
#endif

#ifdef WMOPS
        update_mem();
@@ -3433,6 +3407,93 @@ static ivas_error decodeVoIP(
#endif
    }


#ifdef NONBE_FIX_864_JBM_RENDER_FRAMESIZE
    int16_t nSamplesFlushed = 0;

    /* decode and get samples */
#ifdef SPLIT_REND_WITH_HEAD_ROT
    if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK )
#else
    if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK )
#endif
    {
        fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) );
        goto cleanup;
    }

    if ( nSamplesFlushed )
    {
        /* Write current frame */
        if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, nSamplesFlushed * nOutChannels ) ) != IVAS_ERR_OK )
        {
            fprintf( stderr, "\nOutput audio file writer error\n" );
            goto cleanup;
        }

        /* Write ISm metadata to external file(s) */
        if ( decodedGoodFrame && arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL )
        {
            if ( bsFormat == IVAS_DEC_BS_OBJ || bsFormat == IVAS_DEC_BS_MASA_ISM || bsFormat == IVAS_DEC_BS_SBA_ISM )
            {
                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 )
                {
                    IVAS_ISM_METADATA IsmMetadata;

                    if ( ( error = IVAS_DEC_GetObjectMetadata( hIvasDec, &IsmMetadata, 0, 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 ( bsFormat == IVAS_DEC_BS_MASA || bsFormat == IVAS_DEC_BS_MASA_ISM )
            {
                IVAS_MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta;
#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
                int16_t fullDelayNumSamples[3];
                float delayMs;

                /* delayNumSamples is zeroed, and delayNumSamples_orig is updated only on first good frame, so need to re-fetch delay info */
                if ( ( error = IVAS_DEC_GetDelay( hIvasDec, fullDelayNumSamples, &delayTimeScale ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nUnable to get delay of decoder: %s\n", ivas_error_to_string( error ) );
                }
#endif
                if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta, 0 ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) );
                    goto cleanup;
                }

#ifdef NONBE_FIX_984_OMASA_EXT_OUTPUT
                delayMs = (float) ( fullDelayNumSamples[0] ) / (float) ( delayTimeScale );
                if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta, &delayMs ) ) != IVAS_ERR_OK )
#else
                if ( ( error = MasaFileWriter_writeFrame( masaWriter, hMasaExtOutMeta ) ) != IVAS_ERR_OK )
#endif
                {
                    fprintf( stderr, "\nError writing MASA metadata to file: %s\n", MasaFileWriter_getFilePath( masaWriter ) );
                    goto cleanup;
                }
            }
        }
    }
#endif

    /*------------------------------------------------------------------------------------------*
     * Add zeros at the end to have equal length of synthesized signals
     *------------------------------------------------------------------------------------------*/
Loading