diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 36b589383f1aeffa1bce9cd586d4b1cd6a9d1535..cdd3435b24567685c42667d0ece97805d3eccf3d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -909,7 +909,7 @@ lc3-wrapper-unit-test: script: - cmake -B cmake-build -G "Unix Makefiles" -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - cmake --build cmake-build -- -j - - scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test + - scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test # compare split-rendering bitexactness between target and source branch split-rendering-pytest-on-merge-request: @@ -2446,7 +2446,9 @@ coverage-test-on-main-scheduled: - 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 + # 1. check for public_dir being there as this might not be the case when artifact download failed + # 2. check for public dir not being empty - handle job failures in prev job that happen after the dir is created. In that case, the empty dir is in the artifacts + - if [ -d $public_dir ] && [ ! -z "$( ls -A $public_dir )" ]; then - mv $public_dir/* wmops/ # check here if we have the split-by-levels files present - if not, fake them up with the existing global one # this is needed for the first run with split graphs on a branch where the global version did run previously diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c5beb9a0d546fe2649575fe8110037314df6621..c2143c90900c12c534cc9abad40187d05e5928d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,7 +174,7 @@ target_include_directories(lib_util PUBLIC lib_util PRIVATE lib_com lib_enc lib_ target_include_directories(lib_util PRIVATE lib_lc3plus lib_isar) if(NOT WMOPS) - add_executable(ivas_lc3plus_unit_test scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c) + add_executable(ivas_lc3plus_unit_test scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test.c) target_link_libraries(ivas_lc3plus_unit_test lib_rend lib_dec lib_util lib_com lib_debug lib_isar) endif() @@ -213,7 +213,7 @@ if(COPY_EXECUTABLES_FROM_BUILD_DIR) add_custom_command(TARGET IVAS_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") add_custom_command(TARGET ISAR_post_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") if (NOT WMOPS) - add_custom_command(TARGET ivas_lc3plus_unit_test POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/split_rendering/lc3plus") + add_custom_command(TARGET ivas_lc3plus_unit_test POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/split_rendering/lc3plus_float") endif() endif() diff --git a/ci/run-first-frame-is-sid-test.sh b/ci/run-first-frame-is-sid-test.sh index fb18eec5ccdb52aa89213678dcd0263d022d8ff6..a6e81f9352f6930c9df6eda00971c6dc1e012bfe 100755 --- a/ci/run-first-frame-is-sid-test.sh +++ b/ci/run-first-frame-is-sid-test.sh @@ -6,9 +6,10 @@ make -j IVAS_cod mv IVAS_cod IVAS_cod_nosan # run all modes and cut bitstream to start with an SID. Use mono output to limit runtime, test is only about decoding the first frame -modes_no_sba=$(scripts/runIvasCodec.py -l | grep dtx | grep -vE "FOA|HOA" ) +modes_no_sba=$(scripts/runIvasCodec.py -l | grep dtx | grep -vE "stereo|FOA|HOA" ) modes_hoa=$(scripts/runIvasCodec.py -l | grep dtx | grep -E "HOA") modes_foa=$(scripts/runIvasCodec.py -l | grep dtx | grep "FOA") +modes_stereo=$(scripts/runIvasCodec.py -l | grep dtx | grep "stereo") # config vars testcase_timeout=20 @@ -25,12 +26,14 @@ cp IVAS_cod_nosan CLANG1/IVAS_cod exit_code_msan=0 echo "-------------- 1. Encoder + Msan decoder -------------- " -echo "-------------- 1.1 all DTX modes except SBA -------------- " +echo "-------------- 1.1 all DTX modes except SBA and stereo -------------- " scripts/IvasBuildAndRunChecks.py --checks CLANG1 -m $modes_no_sba -U 0:20 $common_args || exit_code_msan=$? echo "-------------- 1.2 HOA2 + HOA3 DTX modes -------------- " scripts/IvasBuildAndRunChecks.py --checks CLANG1 -m $modes_hoa -U 70:80 $common_args || exit_code_msan=$? echo "-------------- 1.3 FOA DTX modes -------------- " scripts/IvasBuildAndRunChecks.py --checks CLANG1 -m $modes_foa -U 75:110 $common_args || exit_code_msan=$? +echo "-------------- 1.4 stereo DTX modes -------------- " +scripts/IvasBuildAndRunChecks.py --checks CLANG1 -m $modes_stereo -U 40:60 $common_args || exit_code_msan=$? # archive encoder logs separately mkdir logs_enc logs_dec_msan mv CLANG1/logs/*.enc.txt logs_enc/ @@ -44,12 +47,14 @@ cp -r CLANG1/enc CLANG3/enc exit_code_asan_usan=0 echo "-------------- 2. Asan + Usan decoder -------------- " -echo "-------------- 2.1 all DTX modes except SBA -------------- " +echo "-------------- 2.1 all DTX modes except SBA and stereo -------------- " scripts/IvasBuildAndRunChecks.py --checks CLANG2 CLANG3 --decoder_only -m $modes_no_sba -U 0:20 $common_args || exit_code_asan_usan=$? echo "-------------- 2.2 HOA2 + HOA3 DTX modes -------------- " scripts/IvasBuildAndRunChecks.py --checks CLANG2 CLANG3 --decoder_only -m $modes_hoa -U 70:80 $common_args || exit_code_asan_usan=$? echo "-------------- 2.3 FOA DTX modes -------------- " scripts/IvasBuildAndRunChecks.py --checks CLANG2 CLANG3 --decoder_only -m $modes_foa -U 75:110 $common_args || exit_code_asan_usan=$? +echo "-------------- 2.4 stereo DTX modes -------------- " +scripts/IvasBuildAndRunChecks.py --checks CLANG2 CLANG3 --decoder_only -m $modes_stereo -U 40:60 $common_args || exit_code_asan_usan=$? mv CLANG2/logs logs_dec_asan mv CLANG3/logs logs_dec_usan diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index f12ee0330adffd7ebfd290ff5bbeb913e5680c52..cde0689360e565ae96ac90a6b3c904d07d5789cd 100755 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1142,8 +1142,12 @@ enum #define MASA_TRANSP_BITS 1 #define NO_BITS_MASA_ISM_NO_OBJ 2 #define MASA2TOTAL_THR 0.98f + #define BITS_MASA2TOTTAL_DCT0 6 #define STEP_M2T 0.1f +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +#define STEP_M2T_FX 214748365 // Q31 +#endif #define MASA_HEADER_BITS 2 #define MASA_SUBFRAME_BITS 1 #define MASA_LOWBITRATE_MODE_BITS 1 diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 08dba288eca6067742e1d8a016f72c1bfc022d52..f4c8c88f076507b1eb548541c7c101bfd0ed362f 100755 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -756,6 +756,32 @@ int16_t get_igf_startline( float rand_triangular_signed( int16_t *seed ); +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +Word16 matrix_product_fx( + const Word32 *X_fx, /* i : left hand matrix Qx*/ + const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/ + const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/ + const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/ + const Word32 *Y_fx, /* i : right hand matrix Qy*/ + const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/ + const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/ + const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/ + Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Qx + Qy - 31*/ +); + +Word16 matrix_product_q30_fx( + const Word32 *X_fx, /* i : left hand matrix Q31*/ + const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/ + const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/ + const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/ + const Word32 *Y_fx, /* i : right hand matrix Q25*/ + const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/ + const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/ + const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/ + Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Q30*/ +); +#endif + void dtx_read_padding_bits( DEC_CORE_HANDLE st, diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index 5f81d801f7672a0afadac4453627adf8995636e0..2e55c8799a1515a25b2491a5e5d43d91471ebccf 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -2778,6 +2778,48 @@ const int32_t sep_object_brate[][MAX_NUM_OBJECTS] = }; /* column wise DCT matrices for 4 5, and 8 dim */ +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +const Word32 dct4_fx[4 * 4] = { // Q31 + 1073741824, 1402951040, 1073741824, 581109056, + 1073741824, 581109056, -1073741824, -1402951040, + 1073741824, -581109056, -1073741824, 1402951040, + 1073741824, -1402951040, 1073741824, -581109056 +}; + +const Word32 dct5_fx[5 * 5] = { // Q31 + 960354688, 1291711360, 1098867328, 798219648, 419618304, + 960354688, 798219648, -419618304, -1291711360, -1098867328, + 960354688, 0, -1358283392, 0, 1358283392, + 960354688, -798219648, -419618304, 1291711360, -1098867328, + 960354688, -1291711360, 1098867328, -798219648, 419618304 +}; + +const Word32 dct8_fx[8 * 8] = { // Q31 + 759350208, 1053125952, 991922688, 892708928, 759350208, 596570944, 410813632, 209379648, + 759350208, 892708928, 410813632, -209379648, -759350208, -1053125952, -991922688, -596570944, + 759350208, 596570944, -410813632, -1053125952, -759350208, 209379648, 991922688, 892708928, + 759350208, 209379648, -991922688, -596570944, 759350208, 892708928, -410813632, -1053125952, + 759350208, -209379648, -991922688, 596570944, 759350208, -892708928, -410813632, 1053125952, + 759350208, -596570944, -410813632, 1053125952, -759350208, -209379648, 991922688, -892708928, + 759350208, -892708928, 410813632, 209379648, -759350208, 1053125952, -991922688, 596570944, + 759350208, -1053125952, 991922688, -892708928, 759350208, -596570944, 410813632, -209379648 +}; + +const Word32 dct12_fx[12 * 12] = { // Q31 + 619978560, 869301376, 846752832, 810030848, 759350208, 695569984, 619978560, 533649696, 438301408, 335436960, 226989024, 114460880, + 619978560, 810030848, 619978560, 335436960, 0, -335436960, -619978560, -810030848, -876602816, -810030848, -619978560, -335436960, + 619978560, 695569984, 226989024, -335436960, -759350208, -869301376, -619978560, -114460880, 438301408, 810030848, 846752832, 533649696, + 619978560, 533649696, -226989024, -810030848, -759350208, -114460880, 619978560, 869301376, 438301408, -335436960, -846752832, -695569984, + 619978560, 335436960, -619978560, -810030848, 0, 810030848, 619978560, -335436960, -876602816, -335436960, 619978560, 810030848, 619978560, + 114460880, -846752832, -335436960, 759350208, 533649696, -619978560, -695569984, 438301408, 810030848, -226989024, -869301376, 619978560, + -114460880, -846752832, 335436960, 759350208, -533649696, -619978560, 695569984, 438301408, -810030848, -226989024, 869301376, 619978560, + -335436960, -619978560, 810030848, 0, -810030848, 619978560, 335436960, -876602816, 335436960, 619978560, -810030848, 619978560, -533649696, + -226989024, 810030848, -759350208, 114460880, 619978560, -869301376, 438301408, 335436960, -846752832, 695569984, 619978560, -695569984, + 226989024, 335436960, -759350208, 869301376, -619978560, 114460880, 438301408, -810030848, 846752832, -533649696, 619978560, -810030848, + 619978560, -335436960, 0, 335436960, -619978560, 810030848, -876602816, 810030848, -619978560, 335436960, 619978560, -869301376, 846752832, + -810030848, 759350208, -695569984, 619978560, -533649696, 438301408, -335436960, 226989024, -114460880 +}; +#endif const float dct4[4*4] = { 0.5000f, 0.6533f, 0.5000f, 0.2706f, diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index c6c8250b038277d7debc172aad4682a74de35eea..b19ae93c176e926fc853db95f3f91800e3006d77 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -325,6 +325,12 @@ extern const float McMASA_LFEGain_vectors[64]; *----------------------------------------------------------------------------------*/ extern const int32_t sep_object_brate[][MAX_NUM_OBJECTS]; +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +extern const Word32 dct4_fx[]; +extern const Word32 dct5_fx[]; +extern const Word32 dct8_fx[]; +extern const Word32 dct12_fx[]; +#endif extern const float dct4[]; extern const float dct5[]; extern const float dct8[]; diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index f91dc214c8db9292e4be99a3a06222e8a3cde268..a38c1050284f5820d00b87e7e679c965f861ec0a 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -41,6 +41,9 @@ #include "ivas_prot.h" #include "wmc_auto.h" #include "ivas_rom_com.h" +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +#include "basop_settings.h" +#endif /*--------------------------------------------------------------- * sumAbs() @@ -1274,3 +1277,242 @@ float rand_triangular_signed( return 0.5f - 0.5f * sqrtf( 1.0f - rand_val ); } } +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +Word16 matrix_product_fx( + const Word32 *X_fx, /* i : left hand matrix Qx*/ + const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/ + const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/ + const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/ + const Word32 *Y_fx, /* i : right hand matrix Qy*/ + const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/ + const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/ + const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/ + Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Qx + Qy - 31*/ +) +{ + Word16 i, j, k; + Word16 x_idx, y_idx; + Word32 *Zp_fx = Z_fx; + + /* Processing */ + + if ( transpX == 1 && transpY == 0 ) /* We use X transpose */ + { + if ( rowsX != rowsY ) + { + return EXIT_FAILURE; + } + for ( j = 0; j < colsY; ++j ) + { + for ( i = 0; i < colsX; ++i ) + { + ( *Zp_fx ) = 0; + + for ( k = 0; k < rowsX; ++k ) + { + x_idx = k + i * rowsX; /*Q0*/ + y_idx = k + j * rowsY; /*Q0*/ + ( *Zp_fx ) = *Zp_fx + Mpy_32_32( X_fx[x_idx], Y_fx[y_idx] ); /*Qx + Qy - 31*/ + } + Zp_fx++; + } + } + } + else if ( transpX == 0 && transpY == 1 ) /* We use Y transpose */ + { + if ( colsX != colsY ) + { + return EXIT_FAILURE; + } + for ( j = 0; j < rowsY; ++j ) + { + for ( i = 0; i < rowsX; ++i ) + { + ( *Zp_fx ) = 0; + for ( k = 0; k < colsX; ++k ) + { + x_idx = i + k * rowsX; /*Q0*/ + y_idx = j + k * rowsY; /*Q0*/ + ( *Zp_fx ) = ( *Zp_fx ) + Mpy_32_32( X_fx[x_idx], Y_fx[y_idx] ); /*Qx + Qy - 31*/ + } + Zp_fx++; + } + } + } + else if ( transpX == 1 && transpY == 1 ) /* We use both transpose */ + { + if ( rowsX != colsY ) + { + return EXIT_FAILURE; + } + for ( j = 0; j < rowsY; ++j ) + { + for ( i = 0; i < colsX; ++i ) + { + ( *Zp_fx ) = 0; + + for ( k = 0; k < colsX; ++k ) + { + x_idx = k + i * rowsX; /*Q0*/ + y_idx = j + k * rowsY; /*Q0*/ + ( *Zp_fx ) = ( *Zp_fx ) + Mpy_32_32( X_fx[x_idx], Y_fx[y_idx] ); /*Qx + Qy - 31*/ + } + + Zp_fx++; + } + } + } + else /* Regular case */ + { + if ( colsX != rowsY ) + { + return EXIT_FAILURE; + } + + for ( j = 0; j < colsY; ++j ) + { + for ( i = 0; i < rowsX; ++i ) + { + ( *Zp_fx ) = 0; + + for ( k = 0; k < colsX; ++k ) + { + x_idx = i + k * rowsX; /*Q0*/ + y_idx = k + j * rowsY; /*Q0*/ + ( *Zp_fx ) = ( *Zp_fx ) + Mpy_32_32( X_fx[x_idx], Y_fx[y_idx] ); /*Qx + Qy - 31 L_sat_add() */ + /* TODO: overflow of Z_fx to be checked */ + move32(); + } + Zp_fx++; + } + } + } + + return EXIT_SUCCESS; +} + +Word16 matrix_product_q30_fx( + const Word32 *X_fx, /* i : left hand matrix Q31*/ + const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/ + const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/ + const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/ + const Word32 *Y_fx, /* i : right hand matrix Q25*/ + const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/ + const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/ + const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/ + Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Q30*/ +) +{ + Word16 i, j, k; + Word16 x_idx, y_idx; + Word32 *Zp_fx = Z_fx; + int64_t W_tmp; + + /* Processing */ + test(); + test(); + test(); + if ( transpX == 1 && transpY == 0 ) /* We use X transpose */ + { + if ( rowsX != rowsY ) + { + return EXIT_FAILURE; + } + for ( j = 0; j < colsY; ++j ) + { + for ( i = 0; i < colsX; ++i ) + { + W_tmp = 0; + for ( k = 0; k < rowsX; ++k ) + { + /*( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ) ); */ + x_idx = k + i * rowsX; /* Q0 */ + y_idx = k + j * rowsY; /* Q0 */ + W_tmp += ( (int64_t) X_fx[x_idx] * (int64_t) Y_fx[y_idx] ); /* Q56 */ + } + W_tmp = W_tmp * 64; /* W_shl( W_tmp, 6 ); */ /*Q62*/ + ( *Zp_fx ) = ( W_tmp + 0x80000000 ) >> 32; /* W_round64_L( W_tmp ); */ /*Q30*/ + Zp_fx++; + } + } + } + else if ( transpX == 0 && transpY == 1 ) /* We use Y transpose */ + { + if ( colsX != colsY ) + { + return EXIT_FAILURE; + } + for ( j = 0; j < rowsY; ++j ) + { + for ( i = 0; i < rowsX; ++i ) + { + W_tmp = 0; + for ( k = 0; k < colsX; ++k ) + { + /* ( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ) ); */ + x_idx = i + k * rowsX; /*Q0*/ + y_idx = j + k * rowsY; /*Q0*/ + W_tmp += ( (int64_t) X_fx[x_idx] * (int64_t) Y_fx[y_idx] ); /* Q56 */ + } + W_tmp = W_tmp * 64; /*Q62*/ + ( *Zp_fx ) = ( W_tmp + 0x80000000 ) >> 32; /*Q30*/ + Zp_fx++; + } + } + } + else if ( transpX == 1 && transpY == 1 ) /* We use both transpose */ + { + if ( rowsX != colsY ) + { + return EXIT_FAILURE; + } + for ( j = 0; j < rowsY; ++j ) + { + for ( i = 0; i < colsX; ++i ) + { + W_tmp = 0; + for ( k = 0; k < colsX; ++k ) + { + /* ( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ) ); */ + x_idx = k + i * rowsX; /*Q0*/ + y_idx = j + k * rowsY; /*Q0*/ + W_tmp += ( (int64_t) X_fx[x_idx] * (int64_t) Y_fx[y_idx] ); /* Q56*/ + } + W_tmp = W_tmp * 64; /*Q62*/ + ( *Zp_fx ) = ( W_tmp + 0x80000000 ) >> 32; /*Q30*/ + + Zp_fx++; + } + } + } + else /* Regular case */ + { + if ( colsX != rowsY ) + { + return EXIT_FAILURE; + } + + for ( j = 0; j < colsY; ++j ) + { + for ( i = 0; i < rowsX; ++i ) + { + W_tmp = 0; + + for ( k = 0; k < colsX; ++k ) + { + /* ( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ) ); */ + x_idx = i + k * rowsX; /*Q0*/ + y_idx = k + j * rowsY; /*Q0*/ + W_tmp += ( (int64_t) X_fx[x_idx] * (int64_t) Y_fx[y_idx] ); /* Q56*/ + } + W_tmp = W_tmp * 64; /*Q62*/ + ( *Zp_fx ) = ( W_tmp + 0x80000000 ) >> 32; /*Q30*/ + + Zp_fx++; + } + } + } + + return EXIT_SUCCESS; +} +#endif diff --git a/lib_com/options.h b/lib_com/options.h index c4e5186e5a06105a99b5a7d3e16453a1aefca926..eb68083354d8edc3fed7840ccdd9ca40ab7536d3 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -169,7 +169,13 @@ /* all switches in this category should start with "NONBE_" */ #define NONBE_FIX_GSC_BSTR /* VA: issue 1264: Fix bitstream synchronization between encoder and decoder in ACELP GSC in OMASA */ +#define NONBE_1273_ISM_METADATA_COUNTER /* VA: issue 1273: fix counter overflow in ISM metadata encoder */ +#define NONBE_1279_COUNTER_OVERFLOW /* VA: issue 1279: Avoid possible overflow of counter st->Nb_ACELP_frames */ +#define NONBE_1244_FIX_SWB_BWE_MEMORY /* VA: issue 1244: fix to SWB BWE memory in case of switching from FB coding - pending a review by Huawei */ +#define NONBE_FIX_1277_EVS_DTX_HIGH_RATE_THRESHOLD /* VA/Eri: issue 1277: Fix Mismatch in DTX high-rate threshold between EVS float and BASOP */ + +#define NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL /* Nokia: add fix for precision limitation in comparison with masa2total energy ratio threshold to be aligned with BASOP*/ /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/ivas_qmetadata_dec.c b/lib_dec/ivas_qmetadata_dec.c index ef5da3cb5db9d8510a35f401d439b68886d334d3..349cf13a45a6b07cf64ad47a66c2523ff01b861e 100644 --- a/lib_dec/ivas_qmetadata_dec.c +++ b/lib_dec/ivas_qmetadata_dec.c @@ -40,6 +40,10 @@ #include "ivas_rom_dec.h" #include "wmc_auto.h" #include "prot.h" +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +#include "basop_settings.h" +#endif + /*-----------------------------------------------------------------------* * Local function prototypes @@ -97,7 +101,16 @@ static int16_t read_surround_coherence_hr( uint16_t *bitstream, int16_t *p_bit_p static int16_t read_coherence_data_hr_512( uint16_t *bitstream, int16_t *p_bit_pos, IVAS_QMETADATA *hQMetaData, const int16_t idx_dir, const int16_t nbits_coh ); -static void read_stream_dct_coeffs_omasa( int16_t *q_idx, float *q_dct_data, const int16_t len_stream, uint16_t *bit_stream, int16_t *index, const int16_t first_line ); +static void read_stream_dct_coeffs_omasa( int16_t *q_idx, +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + Word32 *q_dct_data_fx, +#else + float *q_dct_data, +#endif + const int16_t len_stream, + uint16_t *bit_stream, + int16_t *index, + const int16_t first_line ); /*-----------------------------------------------------------------------* @@ -4108,7 +4121,7 @@ static int16_t read_surround_coherence_hr( } else { - idx_ER[j] = 7; // masa_sq( error_ratio_surr, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); + idx_ER[j] = 7; /* masa_sq( error_ratio_surr, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); */ no_cv_vec[j] = idx_cb_sur_coh_masa[idx_ER[j]] + 2; } } @@ -4248,7 +4261,11 @@ static void decode_combined_index( static void read_stream_dct_coeffs_omasa( int16_t *q_idx, +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + Word32 *q_dct_data_fx, +#else float *q_dct_data, +#endif const int16_t len_stream, uint16_t *bit_stream, int16_t *index, @@ -4256,11 +4273,16 @@ static void read_stream_dct_coeffs_omasa( { int16_t sign; int16_t i, j, i_min; - +#ifndef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL float step; +#endif int16_t GR1, GR2; - +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + int64_t step_fx; + step_fx = STEP_M2T_FX; +#else step = STEP_M2T; +#endif sign = 1; if ( first_line == 0 ) { @@ -4325,6 +4347,20 @@ static void read_stream_dct_coeffs_omasa( } /* deindex */ +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + q_dct_data_fx[0] = (Word32) ( ( step_fx * q_idx[0] ) >> 6 ); /* Q25 */ + for ( i = 1; i < len_stream; i++ ) + { + if ( ( q_idx[i] & 1 ) == 0 ) + { + q_dct_data_fx[i] = (Word32) ( ( step_fx * ( -q_idx[i] ) ) >> 7 ); /* Q25 */ + } + ELSE + { + q_dct_data_fx[i] = (Word32) ( ( step_fx * ( q_idx[i] + 1 ) ) >> 7 ); /* Q25 */ + } + } +#else q_dct_data[0] = q_idx[0] * step; for ( i = 1; i < len_stream; i++ ) { @@ -4337,7 +4373,7 @@ static void read_stream_dct_coeffs_omasa( q_dct_data[i] = ( ( q_idx[i] + 1 ) >> 1 ) * step; } } - +#endif return; } @@ -4356,8 +4392,13 @@ void ivas_omasa_decode_masa_to_total( { int16_t i, j, k; int16_t q_idx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + Word32 q_dct_data_fx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS], + dct_data_tmp_fx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; +#else float q_dct_data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS], dct_data_tmp[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; +#endif int16_t n_streams, len_stream; /* Setup coding parameters */ @@ -4372,10 +4413,95 @@ void ivas_omasa_decode_masa_to_total( set_s( q_idx, 0, nbands * nblocks ); for ( i = 0; i < n_streams; i++ ) { - read_stream_dct_coeffs_omasa( &q_idx[i * len_stream], &q_dct_data[i * len_stream], len_stream, bit_stream, index, i == 0 ); + read_stream_dct_coeffs_omasa( &q_idx[i * len_stream], +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + &q_dct_data_fx[i * len_stream], +#else + &q_dct_data[i * len_stream], +#endif + len_stream, bit_stream, index, i == 0 ); } /* inverse DCT2 transform */ +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + SWITCH( len_stream ) + { + case 4: + matrix_product_q30_fx( dct4_fx, nblocks, nblocks, 1, q_dct_data_fx, nblocks, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nblocks ); /*Q30*/ + BREAK; + case 5: + matrix_product_q30_fx( dct5_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nbands ); /*Q30*/ + BREAK; + case 8: + matrix_product_q30_fx( dct8_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nbands ); /*Q30*/ + BREAK; + case 12: + matrix_product_q30_fx( dct12_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nbands ); /*Q30*/ + BREAK; + case 20: + matrix_product_fx( dct5_fx, nbands, nbands, 1, q_dct_data_fx, nbands, nblocks, 0, dct_data_tmp_fx ); + matrix_product_q30_fx( dct_data_tmp_fx, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data_fx ); /* reuse of variable*/ + BREAK; + case 32: + matrix_product_fx( dct8_fx, nbands, nbands, 1, q_dct_data_fx, nbands, nblocks, 0, dct_data_tmp_fx ); + matrix_product_q30_fx( dct_data_tmp_fx, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data_fx ); + BREAK; + default: + printf( "Incorrect number of coefficients for OMASA.\n" ); + BREAK; + } + + /* this is to make sure the comparison to the threshold 0.98 will go the same way in */ + /* fixed point and floating point without having to drag the fixed point values to the */ + /* comparison place in the code; 1052266987 is 0.98 in Q30 it is not needed in the fixed point*/ + + for ( i = 0; i < nblocks * nbands; i++ ) + { + if ( q_dct_data_fx[i] >= 1052266987 && q_dct_data_fx[i] < 1052400000 ) + { + q_dct_data_fx[i] = 1052400000; + } + } + + k = 0; + for ( i = 0; i < nblocks; i++ ) + { + for ( j = 0; j < nbands; j++ ) + { + masa_to_total_energy_ratio[i][j] = q_dct_data_fx[k] / (float) ( 1 << 30 ); + masa_to_total_energy_ratio[i][j] = max( 0.0f, masa_to_total_energy_ratio[i][j] ); + masa_to_total_energy_ratio[i][j] = min( 1.0f, masa_to_total_energy_ratio[i][j] ); + k++; + } + } + + if ( nblocks == 1 ) + { + for ( i = 1; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + for ( j = 0; j < nbands; j++ ) + { + masa_to_total_energy_ratio[i][j] = masa_to_total_energy_ratio[0][j]; + } + } + } + + if ( nbands == 1 ) + { + for ( j = 1; j < 5; j++ ) + { + for ( i = 0; i < nblocks; i++ ) + { + masa_to_total_energy_ratio[i][j] = masa_to_total_energy_ratio[i][0]; + } + } + } + +#else switch ( len_stream ) { case 4: @@ -4439,6 +4565,6 @@ void ivas_omasa_decode_masa_to_total( } } } - +#endif return; } diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index b12783d1c84b55fc5c190ad655af34844f9e4afd..45d633cfc94c71cf600733d08df72c2acc4bc28b 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -167,7 +167,14 @@ ivas_error acelp_core_enc( { st->Nb_ACELP_frames = 0; } +#ifdef NONBE_1279_COUNTER_OVERFLOW + if ( st->Nb_ACELP_frames < MAX16B ) + { + st->Nb_ACELP_frames++; + } +#else st->Nb_ACELP_frames++; +#endif if ( st->L_frame == L_FRAME ) { diff --git a/lib_enc/dtx.c b/lib_enc/dtx.c index 37ba226601656b4197162281175dd9daec0ca7b3..4efa8e1f63c553a92f113e7b0e8697b1a514e485 100644 --- a/lib_enc/dtx.c +++ b/lib_enc/dtx.c @@ -65,6 +65,13 @@ #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_80k /* maximum bitrate to which the default DTX is applied in IVAS; otherwise DTX is applied only in silence */ + +#ifdef NONBE_FIX_1277_EVS_DTX_HIGH_RATE_THRESHOLD +#define DTX_THR_EVS 15 /* lp_noise threshold for DTX at higher bitrates in EVS */ // ToDo: to be removed once EVS is CR fixed +#define DTX_THR 5 /* lp_noise threshold for DTX at higher bitrates */ +#endif + + /*-------------------------------------------------------------------* * Local function prototypes *-------------------------------------------------------------------*/ @@ -89,6 +96,15 @@ void dtx( DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc; int16_t last_br_cng_flag, last_br_flag, br_dtx_flag; int32_t total_brate_ref; +#ifdef NONBE_FIX_1277_EVS_DTX_HIGH_RATE_THRESHOLD + int16_t dtx_thr; + + dtx_thr = DTX_THR; + if ( st->element_mode == EVS_MONO ) + { + dtx_thr = DTX_THR_EVS; // ToDo: to be removed once EVS is CR fixed + } +#endif total_brate_ref = st->total_brate; @@ -99,10 +115,18 @@ void dtx( } else { +#ifdef NONBE_FIX_1277_EVS_DTX_HIGH_RATE_THRESHOLD + last_br_cng_flag = st->last_total_brate_cng <= MAX_BRATE_DTX_EVS || st->lp_noise < dtx_thr || ( st->element_mode == IVAS_SCE && st->last_total_brate_cng <= MAX_BRATE_DTX_IVAS ); +#else 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 ); +#endif last_br_flag = ( st->element_mode == EVS_MONO && st->last_total_brate <= MAX_BRATE_DTX_EVS ) || ( st->element_mode != EVS_MONO && last_ivas_total_brate <= MAX_BRATE_DTX_IVAS ) || +#ifdef NONBE_FIX_1277_EVS_DTX_HIGH_RATE_THRESHOLD + st->lp_noise < dtx_thr; +#else st->lp_noise < 15; +#endif } /* Initialization */ @@ -181,7 +205,11 @@ void dtx( { 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 ) || +#ifdef NONBE_FIX_1277_EVS_DTX_HIGH_RATE_THRESHOLD + st->lp_noise < dtx_thr; +#else st->lp_noise < 15; +#endif } if ( st->Opt_DTX_ON && vad == 0 && diff --git a/lib_enc/ivas_ism_metadata_enc.c b/lib_enc/ivas_ism_metadata_enc.c index c7b991e2f67912cc3472d0e489917bf779f53d8f..b27235ae4b711057f1ae751f708d242c9e677619 100644 --- a/lib_enc/ivas_ism_metadata_enc.c +++ b/lib_enc/ivas_ism_metadata_enc.c @@ -276,7 +276,9 @@ ivas_error ivas_ism_metadata_enc( } else if ( hIsmMeta[ch]->ism_md_fec_cnt_enc == ISM_MD_FEC_CNT_MAX ) { - +#ifdef NONBE_1273_ISM_METADATA_COUNTER + hIsmMeta[ch]->ism_md_fec_cnt_enc = 0; +#endif lowrate_metadata_flag[ch] = 1; hIsmMeta[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX; @@ -556,6 +558,9 @@ ivas_error ivas_ism_metadata_enc( if ( hIsmMeta[ch]->ism_metadata_flag == 0 ) { hIsmMeta[ch]->ism_md_fec_cnt_enc++; +#ifdef NONBE_1273_ISM_METADATA_COUNTER + hIsmMeta[ch]->ism_md_fec_cnt_enc = min( hIsmMeta[ch]->ism_md_fec_cnt_enc, ISM_MD_FEC_CNT_MAX ); +#endif } else { @@ -700,6 +705,9 @@ ivas_error ivas_ism_metadata_enc( if ( hIsmMeta[ch]->ism_metadata_flag == 0 ) { hIsmMeta[ch]->ism_md_fec_cnt_enc++; +#ifdef NONBE_1273_ISM_METADATA_COUNTER + hIsmMeta[ch]->ism_md_fec_cnt_enc = min( hIsmMeta[ch]->ism_md_fec_cnt_enc, ISM_MD_FEC_CNT_MAX ); +#endif } else { diff --git a/lib_enc/ivas_qmetadata_enc.c b/lib_enc/ivas_qmetadata_enc.c index 562a4fa14e22fd44197863cb51a59d17e14ba4f4..550f1fb69795dda41ab700370531732b70b7714d 100644 --- a/lib_enc/ivas_qmetadata_enc.c +++ b/lib_enc/ivas_qmetadata_enc.c @@ -41,7 +41,9 @@ #include "ivas_stat_enc.h" #include "wmc_auto.h" #include "prot.h" - +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL +#include "basop_settings.h" +#endif /*-----------------------------------------------------------------------* * Local function prototypes @@ -6030,12 +6032,21 @@ void ivas_omasa_encode_masa_to_total( float data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; float q_dct_data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; float step = STEP_M2T; + int16_t q_idx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; float dct_data_tmp[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; float dct_data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; + int16_t bits_pos, nb_bits; int16_t n_streams, len_stream; +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + Word32 q_dct_data_fx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS], + dct_data_tmp_fx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; + + int64_t step_fx; + step_fx = STEP_M2T_FX; +#endif #ifdef DEBUG_MODE_QMETADATA static FILE *pF = NULL; static FILE *pF_ratio = NULL; @@ -6144,6 +6155,97 @@ void ivas_omasa_encode_masa_to_total( } /* reconstruct masa2total */ +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + q_dct_data_fx[0] = (Word32) ( ( step_fx * q_idx[0] ) >> 6 ); // Q25 + for ( i = 1; i < len_stream; i++ ) + { + if ( ( q_idx[i] & 1 ) == 0 ) + { + q_dct_data_fx[i] = (Word32) ( ( step_fx * ( -q_idx[i] ) ) >> 7 ); // Q25 + } + ELSE + { + q_dct_data_fx[i] = (Word32) ( ( step_fx * ( q_idx[i] + 1 ) ) >> 7 ); // Q25 + } + } + SWITCH( len_stream ) + { + case 4: + matrix_product_q30_fx( dct4_fx, nblocks, nblocks, 1, q_dct_data_fx, nblocks, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nblocks ); /*Q30*/ + BREAK; + case 5: + matrix_product_q30_fx( dct5_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nbands ); /*Q30*/ + BREAK; + case 8: + matrix_product_q30_fx( dct8_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nbands ); /*Q30*/ + BREAK; + case 12: + matrix_product_q30_fx( dct12_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + mvl2l( dct_data_tmp_fx, q_dct_data_fx, nbands ); /*Q30*/ + BREAK; + case 20: + matrix_product_fx( dct5_fx, nbands, nbands, 1, q_dct_data_fx, nbands, nblocks, 0, dct_data_tmp_fx ); + matrix_product_q30_fx( dct_data_tmp_fx, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data_fx ); /* reuse of variable*/ + BREAK; + case 32: + matrix_product_fx( dct8_fx, nbands, nbands, 1, q_dct_data_fx, nbands, nblocks, 0, dct_data_tmp_fx ); + matrix_product_q30_fx( dct_data_tmp_fx, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data_fx ); + BREAK; + default: + printf( "Incorrect number of coefficients for OMASA.\n" ); + BREAK; + } + + /* this is to make sure the comparison to the threshold 0.98 will go the same way in */ + /* fixed point and floating point without having to drag the fixed point values to the */ + /* comparison place in the code; */ + /* 1052266987 is 0.98 in Q30 it is not needed in the fixed point */ + for ( i = 0; i < nblocks * nbands; i++ ) + { + if ( q_dct_data_fx[i] >= 1052266987 && q_dct_data_fx[i] < 1052400000 ) + { + q_dct_data_fx[i] = 1052400000; + } + } + + k = 0; + for ( i = 0; i < nblocks; i++ ) + { + for ( j = 0; j < nbands; j++ ) + { + masa_to_total_energy_ratio[i][j] = q_dct_data_fx[k] / (float) ( 1 << 30 ); + masa_to_total_energy_ratio[i][j] = max( 0.0f, masa_to_total_energy_ratio[i][j] ); + masa_to_total_energy_ratio[i][j] = min( 1.0f, masa_to_total_energy_ratio[i][j] ); + k++; + } + } + + if ( nblocks == 1 ) + { + for ( i = 1; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + for ( j = 0; j < nbands; j++ ) + { + masa_to_total_energy_ratio[i][j] = masa_to_total_energy_ratio[0][j]; + } + } + } + + if ( nbands == 1 ) + { + for ( j = 1; j < 5; j++ ) + { + for ( i = 0; i < nblocks; i++ ) + { + masa_to_total_energy_ratio[i][j] = masa_to_total_energy_ratio[i][0]; + } + } + } + +#else q_dct_data[0] = q_idx[0] * step; for ( i = 1; i < len_stream; i++ ) { @@ -6196,9 +6298,14 @@ void ivas_omasa_encode_masa_to_total( { masa_to_total_energy_ratio[i][j] = max( 0.0f, q_dct_data[k] ); masa_to_total_energy_ratio[i][j] = min( 1.0f, masa_to_total_energy_ratio[i][j] ); +#ifdef NONBE_1231_BASOP_819_THRESHOLD_MASA2TOTAL + int_tmp = (int32_t) ( MASA_SUR_COH_PRECISION * masa_to_total_energy_ratio[i][j] ); + masa_to_total_energy_ratio[i][j] = (float) ( int_tmp * MASA_SUR_COH_THRESHOLD ); +#endif k++; } } +#endif assert( nb_bits == ( hMetaData->nb_bits_tot - bits_pos ) ); #ifdef DEBUG_MODE_QMETADATA diff --git a/lib_enc/swb_pre_proc.c b/lib_enc/swb_pre_proc.c index 610d485db4d49b2d9521338c8e9019415880ce1e..6e17526ad649d25ebb4451b939a98c4b5818291c 100644 --- a/lib_enc/swb_pre_proc.c +++ b/lib_enc/swb_pre_proc.c @@ -442,7 +442,11 @@ void swb_pre_proc( if ( st->last_extl != SWB_BWE && st->last_extl != FB_BWE ) { /* resample 48 kHz to 32kHz */ +#ifdef NONBE_1244_FIX_SWB_BWE_MEMORY + if ( ( st->last_bwidth == FB && st->element_mode == EVS_MONO ) || ( st->bwidth == FB && st->element_mode > EVS_MONO ) ) // note: once EVS i CR fixed, the condition will simplify to "if ( st->bwidth == FB )" only +#else if ( st->last_bwidth == FB ) +#endif { inner_frame = L_FRAME48k; inner_Fs = 48000; diff --git a/scripts/config/ivas_modes.json b/scripts/config/ivas_modes.json index 05e49d687d15f36f923925ec83fc0c452a1514dd..236802a1268bcdd55fdaf95bf242eade8d3d48e6 100644 --- a/scripts/config/ivas_modes.json +++ b/scripts/config/ivas_modes.json @@ -1946,7 +1946,7 @@ "EXT": [] }, "in_config": "MASA2TC", - "table_name": "MASA 2TC @{table_bitrate} kbps {bandwidth}", + "table_name": "MASA 2TC @{table_bitrate} kbps RS {bandwidth}", "nummetadata": 1, "metadatafilenames": [ "{item}.met" @@ -1954,9 +1954,6 @@ "rs": true, "amr": false, "mono": false, - "rs": true, - "amr": false, - "mono": false, "bitrates": { "wb": { "all": "{sw_files_path}/sw_13k2_512k.bin" @@ -3310,7 +3307,7 @@ "EXT": [] }, "in_config": "ISM3", - "table_name": "ISM3@{table_bitrate} kbps {bandwidth}", + "table_name": "ISM3@{table_bitrate} kbps RS {bandwidth}", "nummetadata": 3, "metadatafilenames": [ "stvISM{mdi}.csv" diff --git a/scripts/diff_complexity.py b/scripts/diff_complexity.py index 1193b5b1c4b5b29a4d7c31104f7dc1e8288e4a4f..1093438d7cd381cfc07010f24e04ce1b6030196d 100755 --- a/scripts/diff_complexity.py +++ b/scripts/diff_complexity.py @@ -28,6 +28,13 @@ submitted to and settled by the final, binding jurisdiction of the courts of Mun 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 re +from io import StringIO +from pathlib import Path +from shutil import get_terminal_size + +import pandas as pd """ Script to diff IVAS logs produced by WMC tool instrumented binaries @@ -38,47 +45,65 @@ the United Nations Convention on Contracts on the International Sales of Goods. This allows: cdiff """ -import argparse -import re -from io import StringIO -from shutil import get_terminal_size -import pandas as pd - -REGEX_WMOPS_TABLE = r"\s?\w+(\s+\w+\.\w+)(\s+\w+\.\w+){3,6}" -REGEX_ROM = ( - r"((\w+\s+\w+)|(\w+\s+\w+\s+)\(.+\))\s?size\s+\(.+\/(\w+)\/.+\)\:\s(\d+)\s+\w+" -) +# without WMC_AUTO, can collide with manual instrumentation +# REGEX_WMOPS_TABLE = r"(\w+)(?:\[WMC_AUTO\])?((\s+\d+\.\d+){4,})" +REGEX_WMOPS_TABLE = r"(\w+(\[WMC_AUTO\])?)((\s+\d+\.\d+){4,})" +REGEX_ROM = r"(\w+\s+ROM.+)size.+\/([\w\_]+)\/.+:\s(\d+)" REGEX_MAX_MEM = r"(Maximum\s+.+)\s+size\:\s+(\d+)" +SUMMARY_COL_NAMES = ["BSL", "CUT", "CUT - BSL"] + +SORT_DICT = { + "min": "WMOPs min", + "avg": "WMOPs avg", + "max": "WMOPs max", + "cmin": "WMOPs(cum) min", + "cavg": "WMOPs(cum) avg", + "cmax": "WMOPs(cum) max", + "calls": "Calls", +} + PD_STRING_KWARGS = { - "index": False, + "index": True, "justify": "center", "max_colwidth": 30, } + NOCOLOUR = "\x1b[0m" RED = "\x1b[31m" GREEN = "\x1b[32m" BLUE = "\x1b[34m" +ROUTINE_NAME_MAP = {"_ivas_fx": "", "_fx": "", "_w32_x": ""} + + +def sanitize_routine_names(df): + # apply the mapping to remove or change routine names + for k, v in ROUTINE_NAME_MAP.items(): + df["Routine"] = df["Routine"].str.replace(k, v) + return df + -def log2df(log_file): +def log2df(log_file, rename=False): """ Parse a WMC tool logfile to a pandas dataframe """ with open(log_file, "r") as log: logfile = "".join(line for line in log) + # apply regexes wmops = [ - re.sub(r"\s+", ",", w.group().strip()) + re.sub(r"\s+", ",", w.expand(r"\1\3")) for w in re.finditer(REGEX_WMOPS_TABLE, logfile) ] - memory = [m.expand(r"\1 (\4), \5") for m in re.finditer(REGEX_ROM, logfile)] - memory.extend([m.expand(r"\1, \2") for m in re.finditer(REGEX_MAX_MEM, logfile)]) + memory = [m.expand(r"\1(\2),\3") for m in re.finditer(REGEX_ROM, logfile)] + memory.extend([m.expand(r"\1,\2") for m in re.finditer(REGEX_MAX_MEM, logfile)]) if not wmops or not memory: raise ValueError(f"Error parsing {log_file}!") + # convert to dataframe wmops = pd.read_csv( StringIO("\n".join(wmops)), header=None, @@ -94,123 +119,191 @@ def log2df(log_file): ], ) memory = pd.read_csv( - StringIO("\n".join(memory)), header=None, names=["Type", "Words"] - ) + StringIO("\n".join(memory)), header=None, names=["Type", "Bytes"] + ).set_index("Type") + memory["Bytes"] = memory["Bytes"].astype("int") + + # sanitize names + if rename: + wmops = sanitize_routine_names(wmops) + return wmops, memory -def main(bsl, cut, out_file, quiet=False, verbose=False): - if not quiet: - print(GREEN + f"Baseline conditon: {bsl}" + NOCOLOUR) - print(RED + f"Condition under test: {cut}" + NOCOLOUR) +def diff_wmops(bsl, cut): + # get total values + def get_tot(df): + return df[df["Routine"] == "total"].set_index("Routine").iloc[:, 1:4] - bsl_wmops, bsl_mem = log2df(bsl) - cut_wmops, cut_mem = log2df(cut) + bsl_wmops_tot = get_tot(bsl) + cut_wmops_tot = get_tot(cut) - if verbose: - PD_STRING_KWARGS["line_width"] = get_terminal_size()[0] - # outer merge on routines, only identical rows are tagged "BOTH" - merge = ( - pd.merge( - cut_wmops.set_index("Routine").drop("total").reset_index(), - bsl_wmops.set_index("Routine").drop("total").reset_index(), - how="outer", - indicator="Source", - ) - .sort_values(["Routine", "Source"], ascending=[True, False]) - .set_index("Source") - ) - merge.index = merge.index.rename_categories( - { - "left_only": RED + "CUT", - "right_only": GREEN + "BSL", - "both": BLUE + "BOTH", - } - ) + # build the wmops and memory tables + table_wmops = pd.concat( + [bsl_wmops_tot, cut_wmops_tot, cut_wmops_tot - bsl_wmops_tot] + ).T + table_wmops.columns = SUMMARY_COL_NAMES - unique = ( - merge.drop(BLUE + "BOTH", errors="ignore") - .reset_index() - .sort_values(["Routine", "Source"], ascending=[True, False]) - ) - common = ( - merge.drop(GREEN + "BSL", errors="ignore") - .drop(RED + "CUT", errors="ignore") - .reset_index() - .sort_values("Routine", ascending=False) - ) + return table_wmops - if not unique.empty: - print( - "Complexity difference of routines".center( - PD_STRING_KWARGS["line_width"], "-" - ) - ) - print(unique.to_string(**PD_STRING_KWARGS) + NOCOLOUR) - - if not common.empty: - print( - "Routines with no differences".center( - PD_STRING_KWARGS["line_width"], "-" - ) - ) - print(common.to_string(**PD_STRING_KWARGS) + NOCOLOUR) - else: - print( - "No differences in complexity of routines".center( - PD_STRING_KWARGS["line_width"], "-" - ) - ) - print(merge.to_string(**PD_STRING_KWARGS)) - SEPARATOR = "_" * PD_STRING_KWARGS["line_width"] - print(NOCOLOUR + SEPARATOR) - table_wmops = pd.concat( - [ - bsl_wmops.iloc[-1][2:5], - cut_wmops.iloc[-1][2:5], - cut_wmops.iloc[-1][2:5] - bsl_wmops.iloc[-1][2:5], - ], - axis=1, +def diff_mem(bsl, cut): + table_mem = pd.concat([bsl, cut, cut - bsl], axis=1) + table_mem.columns = SUMMARY_COL_NAMES + + return table_mem + + +def diff_routines(bsl, cut): + # outer merge on routines, only identical rows are tagged "BOTH" + merge = ( + pd.merge( + cut.set_index("Routine").drop("total").reset_index(), + bsl.set_index("Routine").drop("total").reset_index(), + how="outer", + indicator="Source", + ) + .sort_values(["Routine", "Source"], ascending=[True, False]) + .set_index("Source") + ) + merge.index = merge.index.rename_categories( + { + "left_only": "CUT", + "right_only": "BSL", + "both": "BOTH", + } ) - table_wmops.columns = ["BSL", "CUT", "CUT - BSL"] - table_mem = pd.concat( - [ - bsl_mem.iloc[:, 1], - cut_mem.iloc[:, 1], - cut_mem.iloc[:, 1] - bsl_mem.iloc[:, 1], - ], - axis=1, + # split into differing and identical routines + diff = ( + merge.drop("BOTH", errors="ignore") + .reset_index() + .sort_values(["Routine", "Source"], ascending=[True, False]) + ) + same = ( + merge.drop("BSL", errors="ignore") + .drop("CUT", errors="ignore") + .reset_index() + .sort_values("Routine", ascending=False) ) - table_mem.set_index(bsl_mem.iloc[:, 0], inplace=True) - table_mem.columns = ["BSL", "CUT", "CUT - BSL"] - table = pd.concat([table_wmops, table_mem]) + # get the intersection of the routines so we can calculate the diff + bsl = diff[diff["Source"] == "BSL"].drop(columns="Source").set_index("Routine") + cut = diff[diff["Source"] == "CUT"].drop(columns="Source").set_index("Routine") + overlaps = bsl.index.intersection(cut.index) - def fmt_diff(x): - if isinstance(x, int): - fmt = "{}" - else: - fmt = "{:.3f}" + # find the diff for intersecting routines + routines_diff = cut.loc[overlaps] - bsl.loc[overlaps] + + # retrieve the unique routines for each side + bsl_unique = bsl[~bsl.index.isin(overlaps)] + cut_unique = cut[~cut.index.isin(overlaps)] - if x > 0: - return RED + fmt.format(x) + NOCOLOUR - if x < 0: - return GREEN + fmt.format(x) + NOCOLOUR - else: - return BLUE + fmt.format(x) + NOCOLOUR + return bsl_unique, cut_unique, same, diff, routines_diff - table["CUT - BSL"] = table["CUT - BSL"].apply(fmt_diff) + +def main( + bsl, + cut, + out_file, + detailed=False, + sort_key=None, + quiet=False, + dump_bsl=None, + dump_cut=None, +): if not quiet: - print() - print(table.to_string(justify="left")) + print(GREEN + f"Baseline conditon: {bsl}" + NOCOLOUR) + print(RED + f"Condition under test: {cut}" + NOCOLOUR) + + # parse log files to dataframe + bsl_wmops, bsl_mem = log2df(bsl, True) + cut_wmops, cut_mem = log2df(cut, True) + + # get wmops and memory diff and concatenate into the summary table + table_wmops = diff_wmops(bsl_wmops, cut_wmops) + table_mem = diff_mem(bsl_mem, cut_mem) + summary_table = pd.concat([table_wmops, table_mem]) + if detailed: + bsl_unique, cut_unique, same, diff, routines_diff = diff_routines( + bsl_wmops, cut_wmops + ) + if sort_key: + for df in [bsl_unique, cut_unique, same, diff, routines_diff]: + df.sort_values([SORT_DICT[sort_key]], inplace=True) + + # write output files if out_file: - table.to_csv(out_file) - elif not quiet: - print("\nNo output file specified - console output only!") + summary_table.to_csv(out_file) + if detailed: + detailed_output = out_file.with_stem(f"{out_file.stem}_diff_detailed") + routines_diff.to_csv(detailed_output) + + if dump_bsl: + w, m = log2df(bsl) + pd.concat([w, m.T]).set_index("Routine").to_csv(args.dump_bsl) + if not quiet: + print(GREEN + f"Wrote BSL data to {args.dump_bsl}" + NOCOLOUR) + if dump_cut: + w, m = log2df(cut) + pd.concat([w, m.T]).set_index("Routine").to_csv(args.dump_cut) + if not quiet: + print(RED + f"Wrote CUT data to {args.dump_cut}" + NOCOLOUR) + + # print to CLI + if not quiet: + PD_STRING_KWARGS["line_width"] = get_terminal_size()[0] + + def fmt_df(x, has_int=False, diff=False): + x = float(x) + fmt = "{:.3f}" + if has_int and x % 1 == 0: + fmt = "{:.0f}" + if diff: + if x > 0: + return RED + fmt.format(x) + NOCOLOUR + elif x < 0: + return GREEN + fmt.format(x) + NOCOLOUR + else: + return BLUE + fmt.format(x) + NOCOLOUR + else: + return fmt.format(x) + + def print_df(df, title, has_int=False, diff=False): + df = df.map(fmt_df, has_int=has_int, diff=diff) + print(title.center(PD_STRING_KWARGS["line_width"], "-")) + print(df.to_string(**PD_STRING_KWARGS) + NOCOLOUR) + + if detailed: + if not same.empty: + print(BLUE) + same = same.drop(columns="Source").set_index("Routine") + print_df(same, "Routines with no differences") + if not bsl_unique.empty: + print(GREEN) + print_df(bsl_unique, "Routines only in BSL") + if not cut_unique.empty: + print(RED) + print_df(cut_unique, "Routines only in CUT") + if not routines_diff.empty: + print_df(routines_diff, "Diff of routines", diff=True) + + # summary table + summary_table["BSL"] = summary_table["BSL"].apply( + fmt_df, + has_int=True, + ) + summary_table["CUT"] = summary_table["CUT"].apply( + fmt_df, + has_int=True, + ) + summary_table["CUT - BSL"] = summary_table["CUT - BSL"].apply( + fmt_df, has_int=True, diff=True + ) + print("WMOPs and Memory Summary".center(PD_STRING_KWARGS["line_width"], "-")) + print(summary_table.to_string(justify="left")) if __name__ == "__main__": @@ -220,46 +313,61 @@ if __name__ == "__main__": parser.add_argument( "bsl", - type=str, + type=Path, help="input logfile for baseline condition", ) - parser.add_argument( "cut", - type=str, + type=Path, help="input logfile for condition under test", ) - parser.add_argument( "-o", - "--outfile", - required=False, - type=str, + "--output", + type=Path, help="output csv table", ) - parser.add_argument( - "-q", - "--quiet", - required=False, + "-db", + "--dump_bsl", + type=Path, + help="Dump BSL data to specified .csv file", + ) + parser.add_argument( + "-dc", + "--dump_cut", + type=Path, + help="Dump CUT data to specified .csv file", + ) + parser.add_argument( + "-d", + "--detailed", action="store_true", - help="no console output", - default=False, + help="print detailed info about routines, if used with -o/--output, writes an addtional _detailed.csv file", ) - parser.add_argument( - "-v", - "--verbose", - required=False, + "-s", + "--sort", + choices=SORT_DICT.keys(), + default=None, + help="Sort WMOPs data by this column, only affects detailed output (default = %(default)s)", + ) + parser.add_argument( + "-q", + "--quiet", action="store_true", - help="print detailed info about routines", - default=False, + help="no console output", ) args = parser.parse_args() - if args.verbose and args.quiet: - print("Both verbose and quiet options specified, defaulting to verbose") - args.quiet = False - - main(args.bsl, args.cut, args.outfile, args.quiet, args.verbose) + main( + args.bsl, + args.cut, + args.output, + args.detailed, + args.sort, + args.quiet, + args.dump_bsl, + args.dump_cut, + ) diff --git a/scripts/parse_complexity_run_logs.py b/scripts/parse_complexity_run_logs.py new file mode 100644 index 0000000000000000000000000000000000000000..f10dd2a7c817e3ce057c6be4d2e37ab70efd56eb --- /dev/null +++ b/scripts/parse_complexity_run_logs.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +""" +(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +# place this script along with diff_complexity.py in the root folder of the logs +from diff_complexity import ( + log2df, + diff_wmops, + diff_mem, +) +from pathlib import Path +import pandas as pd +from tqdm import tqdm +import numpy as np + +REF_LOGDIR = Path("float_detail_run_21_1_2025/output/logs") +CUT_LOGDIR = Path("basop_detail_run_21_1_2025/output/logs") + +ref_logfiles = sorted( + f + for f in REF_LOGDIR.glob("*.txt") + if not f.name.endswith("pcm.txt") and "dec" in f.stem + # and "ltv48_STEREO" in f.stem +) +cut_logfiles = sorted( + f + for f in CUT_LOGDIR.glob("*.txt") + if not f.name.endswith("pcm.txt") and "dec" in f.stem + # and "ltv48_STEREO" in f.stem +) + +unique = set(f.name for f in ref_logfiles).difference(f.name for f in cut_logfiles) +if unique: + raise FileNotFoundError( + f"One or more files were not found in either directory {unique}" + ) + +records = [] +crashes = [] +for ref, cut in tqdm(zip(ref_logfiles, cut_logfiles), total=len(ref_logfiles)): + # parse logfiles + try: + ref_wmops, ref_mem = log2df(ref) + except ValueError: + crashes.append(str(ref)) + continue + try: + cut_wmops, cut_mem = log2df(cut) + except ValueError: + crashes.append(str(cut)) + continue + + # get the diff for wmops and memory + wmops = diff_wmops(ref_wmops, cut_wmops) + mem = diff_mem(ref_mem, cut_mem) + + # only extract the difference column + diff = pd.DataFrame(pd.concat([wmops, mem])["CUT - BSL"]).T + diff.rename({"CUT - BSL": "Values"}, inplace=True, axis=1) + + diff.insert(0, "Name", ref.stem) + records.append(diff) + +df = pd.DataFrame(np.squeeze(records), columns=diff.columns) +df.set_index("Name", inplace=True) +df.sort_values("WMOPs max", inplace=True, ascending=False) +df.to_csv("all_diff.csv", float_format="%.3f") + +with open("crashes.log", "w") as f: + [print(c, file=f) for c in crashes] diff --git a/scripts/split_rendering/lc3plus/.gitignore b/scripts/split_rendering/lc3plus_basop/.gitignore similarity index 100% rename from scripts/split_rendering/lc3plus/.gitignore rename to scripts/split_rendering/lc3plus_basop/.gitignore diff --git a/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test.c b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test.c new file mode 100644 index 0000000000000000000000000000000000000000..d4617c13c2af27742de23d0d44e6c284ef7289d2 --- /dev/null +++ b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test.c @@ -0,0 +1,875 @@ +/****************************************************************************************************** + +(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include +#include "options.h" +#include "isar_lc3plus_enc.h" +#include "isar_lc3plus_common.h" +#include "isar_lc3plus_dec.h" +#include "ivas_error_utils.h" +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#include "lc3.h" +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#define MAX_SAMPLES_PER_CHANNEL 960 / 4 +#else +#define MAX_SAMPLES_PER_CHANNEL 960 +#endif +#define DEFAULT_BPS 256000 + +#ifndef PCM_SAMPLE_TYPEDEF_DEFINED +#define PCM_SAMPLE_TYPEDEF_DEFINED +typedef int32_t PcmSample; +#endif + +static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config, uint32_t bps ) +{ + ivas_error err; + int32_t encDelay = -1; + int32_t decDelay = -1; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + err = ISAR_LC3PLUS_ENC_GetDelay( encHandle, &encDelay ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return err; + } + if ( encDelay == -1 || encDelay == 0 ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "encDelay is zero or uninitialized\n" ); + } + + /* encode one frame */ + int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us ); + PcmSample *pcm_in[2]; + PcmSample pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + PcmSample pcm_in_ch2[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch2, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_in[0] = pcm_in_ch1; + pcm_in[1] = pcm_in_ch2; + + int32_t bitstreamSizePerIvasFrame = 0; + err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return err; + } + uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame ); + memset( bitstream_out, 0, bitstreamSizePerIvasFrame ); + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int perChannelBitrate = lc3plus_enc_get_real_bitrate(encHandle->handles[0]); + int perLc3plusFrameDataBlockOctets = encHandle->num_ftds * perChannelBitrate / 8 / (1000*1000/config.lc3plus_frame_duration_us); + int targetOctets = bps / 8 / (1000*1000/config.isar_frame_duration_us); + printf("IVAS-FS=%i LC3plus-FS=%i ch=%i targetBps=%i targetOctets=%i\n", config.isar_frame_duration_us, config.lc3plus_frame_duration_us, config.channels, bps, targetOctets); + printf(" coreBps=%i corePerChBps=%i coreCodecOctets=%i nFtds=%i \n", perChannelBitrate * encHandle->num_encs, perChannelBitrate, perLc3plusFrameDataBlockOctets, encHandle->num_ftds); + int pfOctets = bitstreamSizePerIvasFrame - perLc3plusFrameDataBlockOctets; + int pfBps = pfOctets * 8 * (1000*1000 / config.isar_frame_duration_us); + printf(" payloadFormatBps=%i payloadFormatOctets=%i \n\n", pfBps, pfOctets); + if(pfBps <= 0) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return err; + } + + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out, bitstreamSizePerIvasFrame, Q_in ); +#else + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out ); +#endif + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + free( bitstream_out ); + return err; + } + ISAR_LC3PLUS_ENC_Close( &encHandle ); + + /* decode one frame */ + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + free( bitstream_out ); + return err; + } + + err = ISAR_LC3PLUS_DEC_GetDelay( decHandle, &decDelay ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + if ( decDelay == -1 || decDelay == 0 ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "decDelay is zero or uninitialized\n" ); + } + + uint8_t *bitstream_in = bitstream_out; + + PcmSample *pcm_out[2]; + PcmSample pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + PcmSample pcm_out_ch2[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch2, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_out[0] = pcm_out_ch1; + pcm_out[1] = pcm_out_ch2; + + err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + + err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + + err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + + return 0; +} + + +static int openCloseEncoder( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + uint32_t bps = 128000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return 0; +} + +static int tryOpenEncoderWithInvalidBitrate( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + /* lc3plus max bitrate is 320000 per channel */ + uint32_t invalid_high_bps = 700000; + uint32_t invalid_low_bps = 8; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + uint32_t limitedBitrate; +#endif + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, invalid_high_bps, &encHandle ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* setting an invalid bitrate should result in a limited bitrate*/ + if ( IVAS_ERR_OK != err ) +#else + /* setting an invalid bitrate should trigger an error - which is what we expect */ + if ( IVAS_ERR_LC3PLUS_INVALID_BITRATE != err ) +#endif + { + return 1; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + limitedBitrate = lc3plus_enc_get_real_bitrate(encHandle->handles[0]); + if(limitedBitrate != 320000) + { + return 1; + } +#endif + ISAR_LC3PLUS_ENC_Close(&encHandle); + err = ISAR_LC3PLUS_ENC_Open( config, invalid_low_bps, &encHandle ); + /* setting an invalid bitrate should trigger an error - which is what we expect */ + if ( IVAS_ERR_LC3PLUS_INVALID_BITRATE != err ) + { + return 1; + } + ISAR_LC3PLUS_ENC_Close(&encHandle); + return 0; +} + +static int tryOpenEncoderWithInvalidFrameDuration( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.lc3plus_frame_duration_us = 1234; /*unsupported frame duration*/ + uint32_t bps = 320000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + /* setting an invalid fame duration should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int tryOpenEncoderWithInvalidSampleRate( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.samplerate = 1234; /*unsupported sample rate */ + uint32_t bps = 320000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + /* setting an invalid sample rate should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int tryCallEncoderApiWithInvalidParams( void ) +{ + ISAR_LC3PLUS_ENC_HANDLE invalidEncHandle = NULL; + int32_t *invalidBsSize = NULL; + int32_t bsSize; + int32_t *invalidDelayInSamples = NULL; + int32_t delayInSamples; + PcmSample **invalidPcm_in = NULL; + void *invalidBitstream_out = NULL; + + const int16_t numSamplesPerChannels = MAX_SAMPLES_PER_CHANNEL; + PcmSample *pcm_in[1]; + PcmSample pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_in[0] = pcm_in_ch1; + uint8_t bitstream_out[1200]; + + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetDelay( invalidEncHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetDelay( invalidEncHandle, &delayInSamples ) ) + { + return 1; + } + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, invalidBsSize ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, &bsSize ) ) + { + return 1; + } + ISAR_LC3PLUS_ENC_Close( &invalidEncHandle ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, invalidBitstream_out, bsSize, Q_in ) ) +#else + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, invalidBitstream_out ) ) +#endif + { + return 1; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + memset(Q_in, 0, sizeof(Q_in) ); + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, invalidBitstream_out, bsSize, Q_in) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, bitstream_out, bsSize, Q_in ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, bitstream_out, bsSize, Q_in ) ) +#else + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, invalidBitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, bitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, bitstream_out ) ) +#endif + { + return 1; + } + return 0; +} + + +static int tryCallDecoderApiWithInvalidParams( void ) +{ + ISAR_LC3PLUS_DEC_HANDLE invalidDecHandle = NULL; + + int32_t *invalidDelayInSamples = NULL; + int32_t delayInSamples; + PcmSample **invalidPcm_out = NULL; + void *invalidBitstream_in = NULL; + int32_t invalidBitstream_in_size = 0; + int32_t bitstream_in_size = 100; + + const int16_t numSamplesPerChannels = MAX_SAMPLES_PER_CHANNEL; + PcmSample *pcm_out[1]; + PcmSample pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_out[0] = pcm_out_ch1; + uint8_t bitstream_in[1200]; + + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_GetDelay( invalidDecHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_GetDelay( invalidDecHandle, &delayInSamples ) ) + { + return 1; + } + ISAR_LC3PLUS_DEC_Close( &invalidDecHandle ); + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, bitstream_in_size, pcm_out ) ) + { + return 1; + } + + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Conceal( invalidDecHandle, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Conceal( invalidDecHandle, pcm_out ) ) + { + return 1; + } + return 0; +} + +static int openCloseDecoderWithCaching( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + return 0; +} + +static int openCloseDecoderWithoutCaching( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + return 0; +} + + +static int tryOpenDecoderWithInvalidFrameDuration( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.lc3plus_frame_duration_us = 1234; /*unsupported frame duration*/ + + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + /* setting an invalid fame duration should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int tryOpenDecoderWithInvalidSampleRate( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.samplerate = 1234; /*unsupported sample rate*/ + + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + /* setting an invalid sample rate should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int encodeOneFrame( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + uint32_t bps = 128000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + return err; + + int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us ); + + PcmSample *pcm[1]; + PcmSample pcm_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm[0] = pcm_ch1; + + int32_t bitstreamSizePerIvasFrame = 0; + err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame ); + if ( IVAS_ERR_OK != err ) + return err; + uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame ); + memset( bitstream_out, 0, bitstreamSizePerIvasFrame ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm, bitstream_out, bitstreamSizePerIvasFrame, Q_in ); + +#else + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm, bitstream_out ); +#endif + if ( IVAS_ERR_OK != err ) + return err; + + ISAR_LC3PLUS_ENC_Close( &encHandle ); + free( bitstream_out ); + return 0; +} + + +static int encodeAndDecodeOneMonoFrame( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + uint32_t bps = 128000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + /* encode one frame */ + int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us ); + PcmSample *pcm_in[1]; + PcmSample pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_in[0] = pcm_in_ch1; + + int32_t bitstreamSizePerIvasFrame = 0; + err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame ); + if ( IVAS_ERR_OK != err ) + return err; + + uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame ); + memset( bitstream_out, 0, bitstreamSizePerIvasFrame ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out, bitstreamSizePerIvasFrame, Q_in ); +#else + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out ); +#endif + if ( IVAS_ERR_OK != err ) + return err; + ISAR_LC3PLUS_ENC_Close( &encHandle ); + + /* decode one frame */ + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + uint8_t *bitstream_in = bitstream_out; + + PcmSample *pcm_out[1]; + PcmSample pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_out[0] = pcm_out_ch1; + err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + + return 0; +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_32kHz( void ) +{ + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 32000 }; + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_16kHz( void ) +{ + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 16000 }; + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas5msLc3plus5ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3plus10ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneMonoFrameIvas20msLc3plus10ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 1, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneMonoFrameIvas5msLc3plus5ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 1, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus2_5ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 2.5 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 2.5 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_80kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 82*1000 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_96kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 98*1000 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_124kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 126*1000 ); +} + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_800kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 800*1000 ); +} +#endif + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_204800bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 204800 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_205600bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 205600 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_206400bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 206400 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_207200bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 207200 ); +} + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#include "ivas_lc3plus_unit_test_payload_format.c" +#endif + +int main( + int argc, + char *argv[] ) +{ + (void)argc; + (void)argv; + int ret = 0; + ret = openCloseEncoder(); + if ( ret != 0 ) + return 1; + ret = tryOpenEncoderWithInvalidBitrate(); + if ( ret != 0 ) + return 1; + ret = tryOpenEncoderWithInvalidFrameDuration(); + if ( ret != 0 ) + return 1; + ret = tryOpenEncoderWithInvalidSampleRate(); + if ( ret != 0 ) + return 1; + ret = tryCallEncoderApiWithInvalidParams(); + if ( ret != 0 ) + return 1; + ret = openCloseDecoderWithCaching(); + if ( ret != 0 ) + return 1; + ret = openCloseDecoderWithoutCaching(); + if ( ret != 0 ) + return 1; + ret = tryOpenDecoderWithInvalidFrameDuration(); + if ( ret != 0 ) + return 1; + ret = tryOpenDecoderWithInvalidSampleRate(); + if ( ret != 0 ) + return 1; + ret = tryCallDecoderApiWithInvalidParams(); + if ( ret != 0 ) + return 1; + ret = encodeOneFrame(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneMonoFrame(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_32kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_16kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas5msLc3plus5ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3plus10ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneMonoFrameIvas20msLc3plus10ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneMonoFrameIvas5msLc3plus5ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus2_5ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_80kbpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_96kbpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_124kbpsPerChannel(); + if ( ret != 0 ) + return 1; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_800kbpsPerChannel(); + if ( ret != 0 ) + return 1; +#endif + /* start configs around the FDL threshold */ + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_204800bpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_205600bpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_206400bpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_207200bpsPerChannel(); + if ( ret != 0 ) + return 1; + /* end configs around the FDL threshold */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ret = run_all_payload_tests(); + if ( ret != 0 ) + return 1; +#endif + return 0; +} +#else +int main( void ) +{ + return EXIT_SUCCESS; +} +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test_payload_format.c b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test_payload_format.c new file mode 100644 index 0000000000000000000000000000000000000000..a303d01f53ee873fe70c0fbad2a9b6a540daa154 --- /dev/null +++ b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test_payload_format.c @@ -0,0 +1,451 @@ +/****************************************************************************************************** + +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. 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 "isar_lc3plus_payload.h" +#include "ivas_error_utils.h" +#include "isar_lc3plus_common.h" +#include "options.h" + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + +/* included by ivas_lc3plus_unit_test.c */ + +#define LC3PLUS_MAX_NUM_CODERS 16 +#define LC3PLUS_MAX_BS_SIZE LC3PLUS_MAX_NUM_CODERS *( 720 * LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES ) +#define SIZE_70 70 +#define SIZE_160 160 +#define SIZE_320 320 +#define SIZE_600 600 + +static int pack_and_unpack_payload_config_2ch_10ms_lc3plus_20ms_ivas( void ) +{ + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = SIZE_160; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_01 = &sender_ftds[1]; + ftd_R_01->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_01->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_R_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_01->frame_data = NULL; + ftd_R_01->frame_data_length = SIZE_600; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_02 = &sender_ftds[2]; + ftd_L_02->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_02->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_L_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_02->frame_data = NULL; + ftd_L_02->frame_data_length = SIZE_320; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_02 = &sender_ftds[3]; + ftd_R_02->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_R_02->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_R_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_02->frame_data = NULL; + ftd_R_02->frame_data_length = SIZE_160; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_160]; + memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) ); + uint8_t frame_data_R_01[SIZE_600]; + memset( frame_data_R_01, 0x02, sizeof( frame_data_R_01 ) ); + uint8_t frame_data_L_02[SIZE_320]; + memset( frame_data_L_02, 0x03, sizeof( frame_data_L_02 ) ); + uint8_t frame_data_R_02[SIZE_160]; + memset( frame_data_R_02, 0x04, sizeof( frame_data_R_02 ) ); + memcpy( sender_ftds[0].frame_data, frame_data_L_01, sender_ftds[0].frame_data_length ); + memcpy( sender_ftds[1].frame_data, frame_data_R_01, sender_ftds[1].frame_data_length ); + memcpy( sender_ftds[2].frame_data, frame_data_L_02, sender_ftds[2].frame_data_length ); + memcpy( sender_ftds[3].frame_data, frame_data_R_02, sender_ftds[3].frame_data_length ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + + assert( payload_config.fdl_request == fdl_req ); + assert( payload_config.frame_duration_us == 10000 ); + assert( payload_config.high_resolution_enabled == 0 ); + assert( payload_config.sampling_rate_hz == 48000 ); + assert( payload_config.num_ftds == 4 ); + assert( payload_config.num_media_times == 2 ); + assert( payload_config.num_channels == 2 ); + for ( int32_t i = 0; i < payload_config.num_ftds; ++i ) + { + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].h == sender_ftds[i].h ); + assert( payload_config.ftds[i].fdi == sender_ftds[i].fdi ); + assert( payload_config.ftds[i].bwr == sender_ftds[i].bwr ); + assert( payload_config.ftds[i].fc == sender_ftds[i].fc ); + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].frame_data != sender_ftds[i].frame_data ); + assert( 0 == memcmp( payload_config.ftds[i].frame_data, sender_ftds[i].frame_data, sender_ftds[i].frame_data_length ) ); + } + + free( receiverBuffer ); + return 0; +} + +static int pack_and_unpack_payload_config_2ch_5ms_lc3plus_20ms_ivas( void ) +{ + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_01 = &sender_ftds[1]; + ftd_R_01->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_01->frame_data = NULL; + ftd_R_01->frame_data_length = SIZE_320; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_02 = &sender_ftds[2]; + ftd_L_02->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_02->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_02->frame_data = NULL; + ftd_L_02->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_02 = &sender_ftds[3]; + ftd_R_02->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_02->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_02->frame_data = NULL; + ftd_R_02->frame_data_length = SIZE_160; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_03 = &sender_ftds[4]; + ftd_L_03->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_03->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_03->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_03->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_03->frame_data = NULL; + ftd_L_03->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_03 = &sender_ftds[5]; + ftd_R_03->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_03->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_03->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_03->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_03->frame_data = NULL; + ftd_R_03->frame_data_length = SIZE_320; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_04 = &sender_ftds[6]; + ftd_L_04->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_04->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_04->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_04->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_04->frame_data = NULL; + ftd_L_04->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_04 = &sender_ftds[7]; + ftd_R_04->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_R_04->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_04->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_04->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_04->frame_data = NULL; + ftd_R_04->frame_data_length = SIZE_160; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_70]; + assert( ftd_L_01->frame_data_length == sizeof( frame_data_L_01 ) ); + memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) ); + uint8_t frame_data_R_01[SIZE_320]; + assert( ftd_R_01->frame_data_length == sizeof( frame_data_R_01 ) ); + memset( frame_data_R_01, 0x02, sizeof( frame_data_R_01 ) ); + uint8_t frame_data_L_02[SIZE_70]; + assert( ftd_L_02->frame_data_length == sizeof( frame_data_L_02 ) ); + memset( frame_data_L_02, 0x03, sizeof( frame_data_L_02 ) ); + uint8_t frame_data_R_02[SIZE_160]; + assert( ftd_R_02->frame_data_length == sizeof( frame_data_R_02 ) ); + memset( frame_data_R_02, 0x04, sizeof( frame_data_R_02 ) ); + uint8_t frame_data_L_03[SIZE_70]; + assert( ftd_L_03->frame_data_length == sizeof( frame_data_L_03 ) ); + memset( frame_data_L_03, 0x05, sizeof( frame_data_L_03 ) ); + uint8_t frame_data_R_03[SIZE_320]; + assert( ftd_R_03->frame_data_length == sizeof( frame_data_R_03 ) ); + memset( frame_data_R_03, 0x06, sizeof( frame_data_R_03 ) ); + uint8_t frame_data_L_04[SIZE_70]; + assert( ftd_L_04->frame_data_length == sizeof( frame_data_L_04 ) ); + memset( frame_data_L_04, 0x07, sizeof( frame_data_L_04 ) ); + uint8_t frame_data_R_04[SIZE_160]; + assert( ftd_R_04->frame_data_length == sizeof( frame_data_R_04 ) ); + memset( frame_data_R_04, 0x08, sizeof( frame_data_R_04 ) ); + memcpy( sender_ftds[0].frame_data, frame_data_L_01, sender_ftds[0].frame_data_length ); + memcpy( sender_ftds[1].frame_data, frame_data_R_01, sender_ftds[1].frame_data_length ); + memcpy( sender_ftds[2].frame_data, frame_data_L_02, sender_ftds[2].frame_data_length ); + memcpy( sender_ftds[3].frame_data, frame_data_R_02, sender_ftds[3].frame_data_length ); + memcpy( sender_ftds[4].frame_data, frame_data_L_03, sender_ftds[4].frame_data_length ); + memcpy( sender_ftds[5].frame_data, frame_data_R_03, sender_ftds[5].frame_data_length ); + memcpy( sender_ftds[6].frame_data, frame_data_L_04, sender_ftds[6].frame_data_length ); + memcpy( sender_ftds[7].frame_data, frame_data_R_04, sender_ftds[7].frame_data_length ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + + assert( payload_config.fdl_request == fdl_req ); + assert( payload_config.frame_duration_us == 5000 ); + assert( payload_config.high_resolution_enabled == 0 ); + assert( payload_config.sampling_rate_hz == 48000 ); + assert( payload_config.num_ftds == 8 ); + assert( payload_config.num_media_times == 4 ); + assert( payload_config.num_channels == 2 ); + for ( int32_t i = 0; i < payload_config.num_ftds; ++i ) + { + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].h == sender_ftds[i].h ); + assert( payload_config.ftds[i].fdi == sender_ftds[i].fdi ); + assert( payload_config.ftds[i].bwr == sender_ftds[i].bwr ); + assert( payload_config.ftds[i].fc == sender_ftds[i].fc ); + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].frame_data != sender_ftds[i].frame_data ); + assert( 0 == memcmp( payload_config.ftds[i].frame_data, sender_ftds[i].frame_data, sender_ftds[i].frame_data_length ) ); + } + + free( receiverBuffer ); + return 0; +} + +static int try_unpack_invalid_values( void ) +{ + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_LENGTH_3_MAX; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = SIZE_70; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_70]; + assert( ftd_L_01->frame_data_length == sizeof( frame_data_L_01 ) ); + memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + int32_t fdl_req_length; + error = LC3PLUS_RTP_frame_data_length_get_size( &fdl_req_length, fdl_req ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_frame_data_length_get_size error\n" ); + } + for ( int16_t packed_buffer_incorrect_size = 0; packed_buffer_incorrect_size < ( fdl_req_length + 2 + SIZE_70 ); ++packed_buffer_incorrect_size ) + { + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_incorrect_size ); + if ( error == LC3PLUS_RTP_ERR_NO_ERROR ) + { + free( receiverBuffer ); + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed to detect error\n" ); + } + } + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + free( receiverBuffer ); + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + free( receiverBuffer ); + return 0; +} + +#define LC3PLUS_RTP_TEST_NUM_FTDS_UT 3 +static int pack_and_unpack_different_fdl_sizes( void ) +{ + int32_t iFtdUt; + LC3PLUS_RTP_FDL fdl_requests_ut[LC3PLUS_RTP_TEST_NUM_FTDS_UT]; + fdl_requests_ut[0] = LC3PLUS_RTP_FDL_LENGTH_1_MIN; + fdl_requests_ut[1] = LC3PLUS_RTP_FDL_LENGTH_2_MIN; + fdl_requests_ut[2] = LC3PLUS_RTP_FDL_LENGTH_3_MIN; + + for ( iFtdUt = 0; iFtdUt < LC3PLUS_RTP_TEST_NUM_FTDS_UT; ++iFtdUt ) + { + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = fdl_requests_ut[iFtdUt]; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_requests_ut[iFtdUt], sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_600]; + assert( ftd_L_01->frame_data_length <= sizeof( frame_data_L_01 ) ); + memset( frame_data_L_01, 0x01, ftd_L_01->frame_data_length ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + free( receiverBuffer ); + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + assert( payload_config.fdl_request == fdl_requests_ut[iFtdUt] ); + assert( payload_config.ftds[0].frame_data_length == fdl_requests_ut[iFtdUt] ); + free( receiverBuffer ); + } + return 0; +} + +static int run_all_payload_tests( void ) +{ + if ( pack_and_unpack_payload_config_2ch_10ms_lc3plus_20ms_ivas() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + if ( pack_and_unpack_payload_config_2ch_5ms_lc3plus_20ms_ivas() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + if ( try_unpack_invalid_values() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + if ( pack_and_unpack_different_fdl_sizes() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + return 0; +} +#endif diff --git a/scripts/split_rendering/lc3plus_basop/split_rend_lc3plus_cmdlines.py b/scripts/split_rendering/lc3plus_basop/split_rend_lc3plus_cmdlines.py new file mode 100644 index 0000000000000000000000000000000000000000..033c25bb6027ab2752bf58c33ec9b70cdff50650 --- /dev/null +++ b/scripts/split_rendering/lc3plus_basop/split_rend_lc3plus_cmdlines.py @@ -0,0 +1,191 @@ +""" +Generate command lines for split rendering with LC3plus +""" + +import itertools +import os + +# Paths +ENC_PATH = "./IVAS_cod" +DEC_PATH = "./IVAS_dec" +REND_PATH = "./IVAS_rend" +TEMP_DIR = "tmp" + +# Config values to iterate over +ISM_CONFIGS_NUM_OBJECTS = [1, 2, 3, 4] +IVAS_BITRATES = [128000] +PRE_HEAD_ROT_FILES = [ + "Workspace_msvc/trajectories/pre-renderer_pose_files/pre_yaw-20static.csv" +] +POST_HEAD_ROT_FILES = [ + "Workspace_msvc/trajectories/post-renderer_pose_files/post_0static.csv" +] +RENDER_CONFIG_FILES = [ + ####################################################### + # Alternative 2 - LC3plus with CLDFB pose correction + "Workspace_msvc/renderer_configs/split_renderer_config_768_1dof.txt", + "Workspace_msvc/renderer_configs/split_renderer_config_512_2dof.txt", + None, # Alternative 2 is the default when no rendering config file is given on command line + ####################################################### + # Alternative 3 - LC3plus with multi-stream (TD) pose correction + "Workspace_msvc/renderer_configs/split_renderer_config_768_1dof_tdposecorr.txt", + "Workspace_msvc/renderer_configs/split_renderer_config_1536_2dof_tdposecorr.txt", +] + + +def audio_for_ism(num_objects): + return f"scripts/testv/stv{num_objects}ISM48s.wav" + + +def metadata_for_ism(num_objects): + return f"scripts/testv/stvISM{num_objects}.csv" + + +def basename(file_path): + basename_w_ext = os.path.basename(file_path) + return os.path.splitext(basename_w_ext)[0] + + +# Full chain: IVAS_cod -> IVAS_dec -> IVAS_rend(post) +def full_chain( + num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, post_head_rot_file +): + bs_name = f"{TEMP_DIR}/ism{num_objects}_b{ivas_bitrate}_full_chain.g192" + cod = [ + ENC_PATH, + "-ism", + str(num_objects), + *[metadata_for_ism(i + 1) for i in range(num_objects)], + str(ivas_bitrate), + "48", + audio_for_ism(num_objects), + bs_name, + ] + + render_config_infix = ( + f"##{basename(render_config_file)}" if render_config_file else "" + ) + split_bs_name = bs_name.replace( + ".g192", f"##{basename(pre_head_rot_file)}{render_config_infix}##split.bs" + ) + render_config_args = ( + ["-render_config", render_config_file] if render_config_file else [] + ) + dec = [ + DEC_PATH, + "-T", + pre_head_rot_file, + *render_config_args, + "SPLIT_BINAURAL", + "48", + bs_name, + split_bs_name, + ] + + binaural_output_name = split_bs_name.replace( + ".bs", f"##{basename(post_head_rot_file)}##binaural.wav" + ) + rend = [ + REND_PATH, + "-i", + split_bs_name, + "-if", + "BINAURAL_SPLIT_CODED", + "-of", + "BINAURAL", + "-fs", + "48", + "-tf", + post_head_rot_file, + "-o", + binaural_output_name, + ] + + return [cod, dec, rend] + + +# Renderer chain: IVAS_rend(pre) -> IVAS_rend(post) +def rend_chain(num_objects, pre_head_rot_file, render_config_file, post_head_rot_file): + render_config_infix = ( + f"##{basename(render_config_file)}" if render_config_file else "" + ) + split_bs_name = f"{TEMP_DIR}/ism{num_objects}_rend_chain##{basename(pre_head_rot_file)}{render_config_infix}##split.bs" + render_config_args = ( + ["-render_config", render_config_file] if render_config_file else [] + ) + pre = [ + REND_PATH, + "-i", + audio_for_ism(num_objects), + "-if", + f"ISM{num_objects}", + "-im", + *[metadata_for_ism(i + 1) for i in range(num_objects)], + "-of", + "BINAURAL_SPLIT_CODED", + "-fs", + "48", + *render_config_args, + "-tf", + pre_head_rot_file, + "-o", + split_bs_name, + ] + + binaural_output_name = split_bs_name.replace( + ".bs", f"##{basename(post_head_rot_file)}##binaural.wav" + ) + post = [ + REND_PATH, + "-i", + split_bs_name, + "-if", + "BINAURAL_SPLIT_CODED", + "-of", + "BINAURAL", + "-fs", + "48", + "-tf", + post_head_rot_file, + "-o", + binaural_output_name, + ] + + return [pre, post] + + +def print_command_list(list_of_lists): + for lst in list_of_lists: + print(" ".join(lst)) + print("") # newline + + +def main(): + print("\n##########################################") + print("# Full chain: enc -> dec -> rend(post)") + print("##########################################\n") + for args_full_chain in itertools.product( + # Ordering here must match argument order in function call below! + ISM_CONFIGS_NUM_OBJECTS, + IVAS_BITRATES, + PRE_HEAD_ROT_FILES, + RENDER_CONFIG_FILES, + POST_HEAD_ROT_FILES, + ): + print_command_list(full_chain(*args_full_chain)) + + print("\n##########################################") + print("# Renderer chain: rend(pre) -> rend(post)") + print("##########################################\n") + for args_rend_chain in itertools.product( + # Ordering here must match argument order in function call below! + ISM_CONFIGS_NUM_OBJECTS, + PRE_HEAD_ROT_FILES, + RENDER_CONFIG_FILES, + POST_HEAD_ROT_FILES, + ): + print_command_list(rend_chain(*args_rend_chain)) + + +if __name__ == "__main__": + main() diff --git a/scripts/split_rendering/lc3plus_float/.gitignore b/scripts/split_rendering/lc3plus_float/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..9cd2def1f8d1ce4f0300a90324e6479906a6f5cb --- /dev/null +++ b/scripts/split_rendering/lc3plus_float/.gitignore @@ -0,0 +1 @@ +ivas_lc3plus_unit_test \ No newline at end of file diff --git a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c b/scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test.c similarity index 100% rename from scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c rename to scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test.c diff --git a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_payload_format.c b/scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test_payload_format.c similarity index 100% rename from scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_payload_format.c rename to scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test_payload_format.c